4 * @file mod/contacts.php
7 use Friendica\Core\System;
8 use Friendica\Core\Worker;
9 use Friendica\Database\DBM;
10 use Friendica\Model\Contact;
11 use Friendica\Model\GContact;
12 use Friendica\Model\Group;
13 use Friendica\Network\Probe;
15 require_once 'include/contact_selectors.php';
16 require_once 'include/contact_widgets.php';
17 require_once 'mod/proxy.php';
19 function contacts_init(App $a)
25 $nets = defaults($_GET, 'nets', '');
30 if (!x($a->page, 'aside')) {
31 $a->page['aside'] = '';
35 if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && ($a->argv[2] == "posts"))) {
36 $contact_id = intval($a->argv[1]);
37 $contact = dba::select('contact', [], ['id' => $contact_id, 'uid' => local_user()], ['limit' => 1]);
40 if (DBM::is_result($contact)) {
41 $a->data['contact'] = $contact;
43 if (($a->data['contact']['network'] != "") && ($a->data['contact']['network'] != NETWORK_DFRN)) {
44 $networkname = format_network_name($a->data['contact']['network'], $a->data['contact']['url']);
49 /// @TODO Add nice spaces
50 $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), array(
51 '$name' => htmlentities($a->data['contact']['name']),
52 '$photo' => $a->data['contact']['photo'],
53 '$url' => ($a->data['contact']['network'] == NETWORK_DFRN) ? "redir/" . $a->data['contact']['id'] : $a->data['contact']['url'],
54 '$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""),
55 '$network_name' => $networkname,
56 '$network' => t('Network:'),
57 '$account_type' => Contact::getAccountType($a->data['contact'])
60 $findpeople_widget = '';
62 $networks_widget = '';
65 $networks_widget = networks_widget('contacts', $nets);
66 if (isset($_GET['add'])) {
67 $follow_widget = follow_widget($_GET['add']);
69 $follow_widget = follow_widget();
72 $findpeople_widget = findpeople_widget();
75 $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 0, $contact_id);
77 $a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"), array(
78 '$vcard_widget' => $vcard_widget,
79 '$findpeople_widget' => $findpeople_widget,
80 '$follow_widget' => $follow_widget,
81 '$groups_widget' => $groups_widget,
82 '$networks_widget' => $networks_widget
85 $base = System::baseUrl();
86 $tpl = get_markup_template("contacts-head.tpl");
87 $a->page['htmlhead'] .= replace_macros($tpl, array(
88 '$baseurl' => System::baseUrl(true),
92 $tpl = get_markup_template("contacts-end.tpl");
93 $a->page['end'] .= replace_macros($tpl, array(
94 '$baseurl' => System::baseUrl(true),
99 function contacts_batch_actions(App $a)
101 $contacts_id = $_POST['contact_batch'];
102 if (!is_array($contacts_id)) {
106 $orig_records = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND `uid` = %d AND `self` = 0",
107 implode(",", $contacts_id),
112 foreach ($orig_records as $orig_record) {
113 $contact_id = $orig_record['id'];
114 if (x($_POST, 'contacts_batch_update')) {
115 _contact_update($contact_id);
118 if (x($_POST, 'contacts_batch_block')) {
119 $r = _contact_block($contact_id, $orig_record);
124 if (x($_POST, 'contacts_batch_ignore')) {
125 $r = _contact_ignore($contact_id, $orig_record);
130 if (x($_POST, 'contacts_batch_archive')) {
131 $r = _contact_archive($contact_id, $orig_record);
136 if (x($_POST, 'contacts_batch_drop')) {
137 _contact_drop($orig_record);
141 if ($count_actions > 0) {
142 info(tt("%d contact edited.", "%d contacts edited.", $count_actions));
145 if (x($_SESSION, 'return_url')) {
146 goaway('' . $_SESSION['return_url']);
152 function contacts_post(App $a)
158 if ($a->argv[1] === "batch") {
159 contacts_batch_actions($a);
163 $contact_id = intval($a->argv[1]);
168 $orig_record = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
172 if (!DBM::is_result($orig_record)) {
173 notice(t('Could not access contact record.') . EOL);
175 return; // NOTREACHED
178 call_hooks('contact_edit_post', $_POST);
180 $profile_id = intval($_POST['profile-assign']);
182 $r = q("SELECT `id` FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
186 if (!DBM::is_result($r)) {
187 notice(t('Could not locate selected profile.') . EOL);
192 $hidden = intval($_POST['hidden']);
194 $notify = intval($_POST['notify']);
196 $fetch_further_information = intval($_POST['fetch_further_information']);
198 $ffi_keyword_blacklist = escape_tags(trim($_POST['ffi_keyword_blacklist']));
200 $priority = intval($_POST['poll']);
201 if ($priority > 5 || $priority < 0) {
205 $info = escape_tags(trim($_POST['info']));
207 $r = q("UPDATE `contact` SET `profile-id` = %d, `priority` = %d , `info` = '%s',
208 `hidden` = %d, `notify_new_posts` = %d, `fetch_further_information` = %d,
209 `ffi_keyword_blacklist` = '%s' WHERE `id` = %d AND `uid` = %d",
215 intval($fetch_further_information),
216 dbesc($ffi_keyword_blacklist),
220 if (DBM::is_result($r)) {
221 info(t('Contact updated.') . EOL);
223 notice(t('Failed to update contact record.') . EOL);
226 $contact = dba::select('contact', [], ['id' => $contact_id, 'uid' => local_user()], ['limit' => 1]);
227 if (DBM::is_result($contact)) {
228 $a->data['contact'] = $contact;
233 /* contact actions */
235 function _contact_update($contact_id)
237 $contact = dba::select('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()], ['limit' => 1]);
238 if (!DBM::is_result($contact)) {
242 $uid = $contact["uid"];
244 if ($r[0]["network"] == NETWORK_OSTATUS) {
245 $result = Contact::create($uid, $contact["url"], false, $contact["network"]);
247 if ($result['success']) {
248 q("UPDATE `contact` SET `subhub` = 1 WHERE `id` = %d", intval($contact_id));
251 // pull feed and consume it, which should subscribe to the hub.
252 Worker::add(PRIORITY_HIGH, "OnePoll", $contact_id, "force");
256 function _contact_update_profile($contact_id)
258 $contact = dba::select('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()], ['limit' => 1]);
259 if (!DBM::is_result($contact)) {
263 $uid = $contact["uid"];
265 $data = Probe::uri($contact["url"], "", 0, false);
267 // "Feed" or "Unknown" is mostly a sign of communication problems
268 if ((in_array($data["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) && ($data["network"] != $contact["network"])) {
272 $updatefields = array("name", "nick", "url", "addr", "batch", "notify", "poll", "request", "confirm",
273 "poco", "network", "alias");
276 if ($data["network"] == NETWORK_OSTATUS) {
277 $result = Contact::create($uid, $data["url"], false);
279 if ($result['success']) {
280 $update["subhub"] = true;
284 foreach ($updatefields AS $field) {
285 if (isset($data[$field]) && ($data[$field] != "")) {
286 $update[$field] = $data[$field];
290 $update["nurl"] = normalise_link($data["url"]);
294 if (isset($data["priority"]) && ($data["priority"] != 0)) {
295 $query = "`priority` = " . intval($data["priority"]);
298 foreach ($update AS $key => $value) {
303 $query .= "`" . $key . "` = '" . dbesc($value) . "'";
310 $r = q("UPDATE `contact` SET $query WHERE `id` = %d AND `uid` = %d",
315 // Update the entry in the contact table
316 Contact::updateAvatar($data['photo'], local_user(), $contact_id, true);
318 // Update the entry in the gcontact table
319 GContact::updateFromProbe($data["url"]);
322 function _contact_block($contact_id, $orig_record)
324 $blocked = (($orig_record['blocked']) ? 0 : 1);
325 $r = q("UPDATE `contact` SET `blocked` = %d WHERE `id` = %d AND `uid` = %d",
330 return DBM::is_result($r);
333 function _contact_ignore($contact_id, $orig_record)
335 $readonly = (($orig_record['readonly']) ? 0 : 1);
336 $r = q("UPDATE `contact` SET `readonly` = %d WHERE `id` = %d AND `uid` = %d",
341 return DBM::is_result($r);
344 function _contact_archive($contact_id, $orig_record)
346 $archived = (($orig_record['archive']) ? 0 : 1);
347 $r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d",
353 q("UPDATE `item` SET `private` = 2 WHERE `contact-id` = %d AND `uid` = %d", intval($contact_id), intval(local_user()));
355 return DBM::is_result($r);
358 function _contact_drop($orig_record)
362 $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid`
363 WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1",
364 intval($a->user['uid'])
366 if (!DBM::is_result($r)) {
370 Contact::terminateFriendship($r[0], $orig_record);
371 Contact::remove($orig_record['id']);
374 function contacts_content(App $a)
378 nav_set_selected('contacts');
381 notice(t('Permission denied.') . EOL);
386 $contact_id = intval($a->argv[1]);
393 $orig_record = dba::select('contact', [], ['id' => $contact_id, 'uid' => local_user(), 'self' => false], ['limit' => 1]);
394 if (!DBM::is_result($orig_record)) {
395 notice(t('Could not access contact record.') . EOL);
397 return; // NOTREACHED
400 if ($cmd === 'update') {
401 _contact_update($contact_id);
402 goaway('contacts/' . $contact_id);
406 if ($cmd === 'updateprofile') {
407 _contact_update_profile($contact_id);
408 goaway('crepair/' . $contact_id);
412 if ($cmd === 'block') {
413 $r = _contact_block($contact_id, $orig_record);
415 $blocked = (($orig_record['blocked']) ? 0 : 1);
416 info((($blocked) ? t('Contact has been blocked') : t('Contact has been unblocked')) . EOL);
419 goaway('contacts/' . $contact_id);
420 return; // NOTREACHED
423 if ($cmd === 'ignore') {
424 $r = _contact_ignore($contact_id, $orig_record);
426 $readonly = (($orig_record['readonly']) ? 0 : 1);
427 info((($readonly) ? t('Contact has been ignored') : t('Contact has been unignored')) . EOL);
430 goaway('contacts/' . $contact_id);
431 return; // NOTREACHED
434 if ($cmd === 'archive') {
435 $r = _contact_archive($contact_id, $orig_record);
437 $archived = (($orig_record['archive']) ? 0 : 1);
438 info((($archived) ? t('Contact has been archived') : t('Contact has been unarchived')) . EOL);
441 goaway('contacts/' . $contact_id);
442 return; // NOTREACHED
445 if ($cmd === 'drop') {
446 // Check if we should do HTML-based delete confirmation
447 if (x($_REQUEST, 'confirm')) {
448 // <form> can't take arguments in its "action" parameter
449 // so add any arguments as hidden inputs
450 $query = explode_querystring($a->query_string);
452 foreach ($query['args'] as $arg) {
453 if (strpos($arg, 'confirm=') === false) {
454 $arg_parts = explode('=', $arg);
455 $inputs[] = array('name' => $arg_parts[0], 'value' => $arg_parts[1]);
459 $a->page['aside'] = '';
461 return replace_macros(get_markup_template('contact_drop_confirm.tpl'), array(
462 '$header' => t('Drop contact'),
463 '$contact' => _contact_detail_for_template($orig_record),
465 '$message' => t('Do you really want to delete this contact?'),
466 '$extra_inputs' => $inputs,
467 '$confirm' => t('Yes'),
468 '$confirm_url' => $query['base'],
469 '$confirm_name' => 'confirmed',
470 '$cancel' => t('Cancel'),
473 // Now check how the user responded to the confirmation query
474 if (x($_REQUEST, 'canceled')) {
475 if (x($_SESSION, 'return_url')) {
476 goaway('' . $_SESSION['return_url']);
482 _contact_drop($orig_record);
483 info(t('Contact has been removed.') . EOL);
484 if (x($_SESSION, 'return_url')) {
485 goaway('' . $_SESSION['return_url']);
489 return; // NOTREACHED
491 if ($cmd === 'posts') {
492 return contact_posts($a, $contact_id);
496 $_SESSION['return_url'] = $a->query_string;
498 if ((x($a->data, 'contact')) && (is_array($a->data['contact']))) {
499 $contact_id = $a->data['contact']['id'];
500 $contact = $a->data['contact'];
502 $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), array(
503 '$baseurl' => System::baseUrl(true),
505 $a->page['end'] .= replace_macros(get_markup_template('contact_end.tpl'), array(
506 '$baseurl' => System::baseUrl(true),
509 require_once 'include/contact_selectors.php';
513 switch ($contact['rel']) {
514 case CONTACT_IS_FRIEND:
515 $dir_icon = 'images/lrarrow.gif';
516 $relation_text = t('You are mutual friends with %s');
518 case CONTACT_IS_FOLLOWER;
519 $dir_icon = 'images/larrow.gif';
520 $relation_text = t('You are sharing with %s');
522 case CONTACT_IS_SHARING;
523 $dir_icon = 'images/rarrow.gif';
524 $relation_text = t('%s is sharing with you');
530 if (!in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA))) {
534 $relation_text = sprintf($relation_text, htmlentities($contact['name']));
536 if (($contact['network'] === NETWORK_DFRN) && ($contact['rel'])) {
537 $url = "redir/{$contact['id']}";
538 $sparkle = ' class="sparkle" ';
540 $url = $contact['url'];
544 $insecure = t('Private communications are not available for this contact.');
546 $last_update = (($contact['last-update'] <= NULL_DATE) ? t('Never') : datetime_convert('UTC', date_default_timezone_get(), $contact['last-update'], 'D, j M Y, g:i A'));
548 if ($contact['last-update'] > NULL_DATE) {
549 $last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? t("\x28Update was successful\x29") : t("\x28Update was not successful\x29"));
551 $lblsuggest = (($contact['network'] === NETWORK_DFRN) ? t('Suggest friends') : '');
553 $poll_enabled = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_FEED, NETWORK_MAIL));
555 $nettype = t('Network type: %s', network_to_name($contact['network'], $contact["url"]));
558 $tab_str = contacts_tab($a, $contact_id, 2);
560 $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < datetime_convert('', '', 'now')) ? t('Communications lost with this contact!') : '');
562 $fetch_further_information = null;
563 if ($contact['network'] == NETWORK_FEED) {
564 $fetch_further_information = array(
565 'fetch_further_information',
566 t('Fetch further information for feeds'),
567 $contact['fetch_further_information'],
568 t("Fetch information like preview pictures, title and teaser from the feed item. You can activate this if the feed doesn't contain much text. Keywords are taken from the meta header in the feed item and are posted as hash tags."),
569 array('0' => t('Disabled'),
570 '1' => t('Fetch information'),
571 '3' => t('Fetch keywords'),
572 '2' => t('Fetch information and keywords')
577 $poll_interval = null;
578 if (in_array($contact['network'], array(NETWORK_FEED, NETWORK_MAIL))) {
579 $poll_interval = contact_poll_interval($contact['priority'], (!$poll_enabled));
582 $profile_select = null;
583 if ($contact['network'] == NETWORK_DFRN) {
584 $profile_select = contact_profile_assign($contact['profile-id'], (($contact['network'] !== NETWORK_DFRN) ? true : false));
589 if (in_array($contact['network'], array(NETWORK_DIASPORA, NETWORK_OSTATUS))) {
590 if ($contact['rel'] == CONTACT_IS_FOLLOWER) {
591 $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]);
592 $follow_text = t("Connect/Follow");
593 } elseif ($contact['rel'] == CONTACT_IS_FRIEND) {
594 $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]);
595 $follow_text = t("Disconnect/Unfollow");
599 // Load contactact related actions like hide, suggest, delete and others
600 $contact_actions = contact_actions($contact);
602 $tpl = get_markup_template("contact_edit.tpl");
603 $o .= replace_macros($tpl, array(
604 '$header' => t("Contact"),
605 '$tab_str' => $tab_str,
606 '$submit' => t('Submit'),
607 '$lbl_vis1' => t('Profile Visibility'),
608 '$lbl_vis2' => t('Please choose the profile you would like to display to %s when viewing your profile securely.', $contact['name']),
609 '$lbl_info1' => t('Contact Information / Notes'),
610 '$lbl_info2' => t('Their personal note'),
611 '$reason' => trim(notags($contact['reason'])),
612 '$infedit' => t('Edit contact notes'),
613 '$common_link' => 'common/loc/' . local_user() . '/' . $contact['id'],
614 '$relation_text' => $relation_text,
615 '$visit' => t('Visit %s\'s profile [%s]', $contact['name'], $contact['url']),
616 '$blockunblock' => t('Block/Unblock contact'),
617 '$ignorecont' => t('Ignore contact'),
618 '$lblcrepair' => t("Repair URL settings"),
619 '$lblrecent' => t('View conversations'),
620 '$lblsuggest' => $lblsuggest,
621 '$nettype' => $nettype,
622 '$poll_interval' => $poll_interval,
623 '$poll_enabled' => $poll_enabled,
624 '$lastupdtext' => t('Last update:'),
625 '$lost_contact' => $lost_contact,
626 '$updpub' => t('Update public posts'),
627 '$last_update' => $last_update,
628 '$udnow' => t('Update now'),
629 '$follow' => $follow,
630 '$follow_text' => $follow_text,
631 '$profile_select' => $profile_select,
632 '$contact_id' => $contact['id'],
633 '$block_text' => (($contact['blocked']) ? t('Unblock') : t('Block') ),
634 '$ignore_text' => (($contact['readonly']) ? t('Unignore') : t('Ignore') ),
635 '$insecure' => (($contact['network'] !== NETWORK_DFRN && $contact['network'] !== NETWORK_MAIL && $contact['network'] !== NETWORK_FACEBOOK && $contact['network'] !== NETWORK_DIASPORA) ? $insecure : ''),
636 '$info' => $contact['info'],
637 '$cinfo' => array('info', '', $contact['info'], ''),
638 '$blocked' => (($contact['blocked']) ? t('Currently blocked') : ''),
639 '$ignored' => (($contact['readonly']) ? t('Currently ignored') : ''),
640 '$archived' => (($contact['archive']) ? t('Currently archived') : ''),
641 '$pending' => (($contact['pending']) ? t('Awaiting connection acknowledge') : ''),
642 '$hidden' => array('hidden', t('Hide this contact from others'), ($contact['hidden'] == 1), t('Replies/likes to your public posts <strong>may</strong> still be visible')),
643 '$notify' => array('notify', t('Notification for new posts'), ($contact['notify_new_posts'] == 1), t('Send a notification of every new post of this contact')),
644 '$fetch_further_information' => $fetch_further_information,
645 '$ffi_keyword_blacklist' => $contact['ffi_keyword_blacklist'],
646 '$ffi_keyword_blacklist' => array('ffi_keyword_blacklist', t('Blacklisted keywords'), $contact['ffi_keyword_blacklist'], t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')),
647 '$photo' => $contact['photo'],
648 '$name' => htmlentities($contact['name']),
649 '$dir_icon' => $dir_icon,
650 '$sparkle' => $sparkle,
652 '$profileurllabel' => t('Profile URL'),
653 '$profileurl' => $contact['url'],
654 '$account_type' => Contact::getAccountType($contact),
655 '$location' => bbcode($contact["location"]),
656 '$location_label' => t("Location:"),
657 '$xmpp' => bbcode($contact["xmpp"]),
658 '$xmpp_label' => t("XMPP:"),
659 '$about' => bbcode($contact["about"], false, false),
660 '$about_label' => t("About:"),
661 '$keywords' => $contact["keywords"],
662 '$keywords_label' => t("Tags:"),
663 '$contact_action_button' => t("Actions"),
664 '$contact_actions' => $contact_actions,
665 '$contact_status' => t("Status"),
666 '$contact_settings_label' => t('Contact Settings'),
667 '$contact_profile_label' => t("Profile"),
670 $arr = array('contact' => $contact, 'output' => $o);
672 call_hooks('contact_edit', $arr);
674 return $arr['output'];
683 if (($a->argc == 2) && ($a->argv[1] === 'all')) {
686 } elseif (($a->argc == 2) && ($a->argv[1] === 'blocked')) {
687 $sql_extra = " AND `blocked` = 1 ";
689 } elseif (($a->argc == 2) && ($a->argv[1] === 'hidden')) {
690 $sql_extra = " AND `hidden` = 1 ";
692 } elseif (($a->argc == 2) && ($a->argv[1] === 'ignored')) {
693 $sql_extra = " AND `readonly` = 1 ";
695 } elseif (($a->argc == 2) && ($a->argv[1] === 'archived')) {
696 $sql_extra = " AND `archive` = 1 ";
699 $sql_extra = " AND `blocked` = 0 ";
702 $search = x($_GET, 'search') ? notags(trim($_GET['search'])) : '';
703 $nets = x($_GET, 'nets' ) ? notags(trim($_GET['nets'])) : '';
707 'label' => t('Suggestions'),
710 'title' => t('Suggest potential friends'),
711 'id' => 'suggestions-tab',
715 'label' => t('All Contacts'),
716 'url' => 'contacts/all',
717 'sel' => ($all) ? 'active' : '',
718 'title' => t('Show all contacts'),
719 'id' => 'showall-tab',
723 'label' => t('Unblocked'),
725 'sel' => ((!$all) && (!$blocked) && (!$hidden) && (!$search) && (!$nets) && (!$ignored) && (!$archived)) ? 'active' : '',
726 'title' => t('Only show unblocked contacts'),
727 'id' => 'showunblocked-tab',
731 'label' => t('Blocked'),
732 'url' => 'contacts/blocked',
733 'sel' => ($blocked) ? 'active' : '',
734 'title' => t('Only show blocked contacts'),
735 'id' => 'showblocked-tab',
739 'label' => t('Ignored'),
740 'url' => 'contacts/ignored',
741 'sel' => ($ignored) ? 'active' : '',
742 'title' => t('Only show ignored contacts'),
743 'id' => 'showignored-tab',
747 'label' => t('Archived'),
748 'url' => 'contacts/archived',
749 'sel' => ($archived) ? 'active' : '',
750 'title' => t('Only show archived contacts'),
751 'id' => 'showarchived-tab',
755 'label' => t('Hidden'),
756 'url' => 'contacts/hidden',
757 'sel' => ($hidden) ? 'active' : '',
758 'title' => t('Only show hidden contacts'),
759 'id' => 'showhidden-tab',
764 $tab_tpl = get_markup_template('common_tabs.tpl');
765 $t = replace_macros($tab_tpl, array('$tabs' => $tabs));
773 $search_hdr = $search;
774 $search_txt = dbesc(protect_sprintf(preg_quote($search)));
775 $sql_extra .= " AND (name REGEXP '$search_txt' OR url REGEXP '$search_txt' OR nick REGEXP '$search_txt') ";
779 $sql_extra .= sprintf(" AND network = '%s' ", dbesc($nets));
782 $sql_extra2 = ((($sort_type > 0) && ($sort_type <= CONTACT_IS_FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : '');
784 $r = q("SELECT COUNT(*) AS `total` FROM `contact`
785 WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ",
786 intval($_SESSION['uid'])
788 if (DBM::is_result($r)) {
789 $a->set_pager_total($r[0]['total']);
790 $total = $r[0]['total'];
793 $sql_extra3 = unavailable_networks();
797 $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 $sql_extra3 ORDER BY `name` ASC LIMIT %d , %d ",
798 intval($_SESSION['uid']),
799 intval($a->pager['start']),
800 intval($a->pager['itemspage'])
802 if (DBM::is_result($r)) {
803 foreach ($r as $rr) {
804 $contacts[] = _contact_detail_for_template($rr);
808 $tpl = get_markup_template("contacts-template.tpl");
809 $o .= replace_macros($tpl, array(
810 '$baseurl' => System::baseUrl(),
811 '$header' => t('Contacts') . (($nets) ? ' - ' . network_to_name($nets) : ''),
814 '$search' => $search_hdr,
815 '$desc' => t('Search your contacts'),
816 '$finding' => $searching ? t('Results for: %s', $search) : "",
817 '$submit' => t('Find'),
819 '$contacts' => $contacts,
820 '$contact_drop_confirm' => t('Do you really want to delete this contact?'),
822 '$batch_actions' => array(
823 'contacts_batch_update' => t('Update'),
824 'contacts_batch_block' => t('Block') . "/" . t("Unblock"),
825 "contacts_batch_ignore" => t('Ignore') . "/" . t("Unignore"),
826 "contacts_batch_archive" => t('Archive') . "/" . t("Unarchive"),
827 "contacts_batch_drop" => t('Delete'),
829 '$h_batch_actions' => t('Batch Actions'),
830 '$paginate' => paginate($a),
837 * @brief List of pages for the Contact TabBar
839 * Available Pages are 'Status', 'Profile', 'Contacts' and 'Common Friends'
842 * @param int $contact_id The ID of the contact
843 * @param int $active_tab 1 if tab should be marked as active
847 function contacts_tab($a, $contact_id, $active_tab)
852 'label' => t('Status'),
853 'url' => "contacts/" . $contact_id . "/posts",
854 'sel' => (($active_tab == 1) ? 'active' : ''),
855 'title' => t('Status Messages and Posts'),
856 'id' => 'status-tab',
860 'label' => t('Profile'),
861 'url' => "contacts/" . $contact_id,
862 'sel' => (($active_tab == 2) ? 'active' : ''),
863 'title' => t('Profile Details'),
864 'id' => 'profile-tab',
869 // Show this tab only if there is visible friend list
870 $x = GContact::countAllFriends(local_user(), $contact_id);
872 $tabs[] = array('label' => t('Contacts'),
873 'url' => "allfriends/" . $contact_id,
874 'sel' => (($active_tab == 3) ? 'active' : ''),
875 'title' => t('View all contacts'),
876 'id' => 'allfriends-tab',
880 // Show this tab only if there is visible common friend list
881 $common = GContact::countCommonFriends(local_user(), $contact_id);
883 $tabs[] = array('label' => t('Common Friends'),
884 'url' => "common/loc/" . local_user() . "/" . $contact_id,
885 'sel' => (($active_tab == 4) ? 'active' : ''),
886 'title' => t('View all common friends'),
887 'id' => 'common-loc-tab',
892 $tabs[] = array('label' => t('Advanced'),
893 'url' => 'crepair/' . $contact_id,
894 'sel' => (($active_tab == 5) ? 'active' : ''),
895 'title' => t('Advanced Contact Settings'),
896 'id' => 'advanced-tab',
900 $tab_tpl = get_markup_template('common_tabs.tpl');
901 $tab_str = replace_macros($tab_tpl, array('$tabs' => $tabs));
906 function contact_posts($a, $contact_id)
908 $o = contacts_tab($a, $contact_id, 1);
910 $contact = dba::select('contact', ['url'], ['id' => $contact_id], ['limit' => 1]);
911 if (DBM::is_result($contact)) {
912 $a->page['aside'] = "";
913 profile_load($a, "", 0, Contact::getDetailsByURL($contact["url"]));
914 $o .= Contact::getPostsFromUrl($contact["url"]);
920 function _contact_detail_for_template($rr)
924 switch ($rr['rel']) {
925 case CONTACT_IS_FRIEND:
926 $dir_icon = 'images/lrarrow.gif';
927 $alt_text = t('Mutual Friendship');
929 case CONTACT_IS_FOLLOWER;
930 $dir_icon = 'images/larrow.gif';
931 $alt_text = t('is a fan of yours');
933 case CONTACT_IS_SHARING;
934 $dir_icon = 'images/rarrow.gif';
935 $alt_text = t('you are a fan of');
940 if (($rr['network'] === NETWORK_DFRN) && ($rr['rel'])) {
941 $url = "redir/{$rr['id']}";
942 $sparkle = ' class="sparkle" ';
949 'img_hover' => t('Visit %s\'s profile [%s]', $rr['name'], $rr['url']),
950 'edit_hover' => t('Edit contact'),
951 'photo_menu' => Contact::photoMenu($rr),
953 'alt_text' => $alt_text,
954 'dir_icon' => $dir_icon,
955 'thumb' => proxy_url($rr['thumb'], false, PROXY_SIZE_THUMB),
956 'name' => htmlentities($rr['name']),
957 'username' => htmlentities($rr['name']),
958 'account_type' => Contact::getAccountType($rr),
959 'sparkle' => $sparkle,
960 'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']),
962 'network' => network_to_name($rr['network'], $rr['url']),
967 * @brief Gives a array with actions which can performed to a given contact
969 * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others
971 * @param array $contact Data about the Contact
972 * @return array with contact related actions
974 function contact_actions($contact)
976 $poll_enabled = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_FEED, NETWORK_MAIL));
977 $contact_actions = array();
979 // Provide friend suggestion only for Friendica contacts
980 if ($contact['network'] === NETWORK_DFRN) {
981 $contact_actions['suggest'] = array(
982 'label' => t('Suggest friends'),
983 'url' => 'fsuggest/' . $contact['id'],
991 $contact_actions['update'] = array(
992 'label' => t('Update now'),
993 'url' => 'contacts/' . $contact['id'] . '/update',
1000 $contact_actions['block'] = array(
1001 'label' => (intval($contact['blocked']) ? t('Unblock') : t('Block') ),
1002 'url' => 'contacts/' . $contact['id'] . '/block',
1003 'title' => t('Toggle Blocked status'),
1004 'sel' => (intval($contact['blocked']) ? 'active' : ''),
1005 'id' => 'toggle-block',
1008 $contact_actions['ignore'] = array(
1009 'label' => (intval($contact['readonly']) ? t('Unignore') : t('Ignore') ),
1010 'url' => 'contacts/' . $contact['id'] . '/ignore',
1011 'title' => t('Toggle Ignored status'),
1012 'sel' => (intval($contact['readonly']) ? 'active' : ''),
1013 'id' => 'toggle-ignore',
1016 $contact_actions['archive'] = array(
1017 'label' => (intval($contact['archive']) ? t('Unarchive') : t('Archive') ),
1018 'url' => 'contacts/' . $contact['id'] . '/archive',
1019 'title' => t('Toggle Archive status'),
1020 'sel' => (intval($contact['archive']) ? 'active' : ''),
1021 'id' => 'toggle-archive',
1024 $contact_actions['delete'] = array(
1025 'label' => t('Delete'),
1026 'url' => 'contacts/' . $contact['id'] . '/drop',
1027 'title' => t('Delete contact'),
1032 return $contact_actions;