diff --git a/boot.php b/boot.php index e92be51a9f..b1e98270c0 100644 --- a/boot.php +++ b/boot.php @@ -41,7 +41,7 @@ define('FRIENDICA_PLATFORM', 'Friendica'); define('FRIENDICA_CODENAME', 'The Tazmans Flax-lily'); define('FRIENDICA_VERSION', '2018.08-dev'); define('DFRN_PROTOCOL_VERSION', '2.23'); -define('DB_UPDATE_VERSION', 1282); +define('DB_UPDATE_VERSION', 1283); define('NEW_UPDATE_ROUTINE_VERSION', 1170); /** diff --git a/config/dbstructure.json b/config/dbstructure.json index 2c1ecddc56..c467ba6bc7 100644 --- a/config/dbstructure.json +++ b/config/dbstructure.json @@ -1224,6 +1224,19 @@ "username": ["username(32)"] } }, + "user-contact": { + "comment": "User specific public contact data", + "fields": { + "cid": {"type": "int unsigned", "not null": "1", "default": "0", "primary": "1", "relation": {"contact": "id"}, "comment": "Contact id of the linked public contact"}, + "uid": {"type": "mediumint unsigned", "not null": "1", "default": "0", "primary": "1", "relation": {"user": "uid"}, "comment": "User id"}, + "blocked": {"type": "boolean", "comment": "Contact is completely blocked for this user"}, + "ignored": {"type": "boolean", "comment": "Posts from this contact are ignored"}, + "collapsed": {"type": "boolean", "comment": "Posts from this contact are collapsed"} + }, + "indexes": { + "PRIMARY": ["uid", "cid"] + } + }, "user-item": { "comment": "User specific item data", "fields": { diff --git a/database.sql b/database.sql index 0dbeb80dd0..60d4b1c88e 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2018.08-dev (The Tazmans Flax-lily) --- DB_UPDATE_VERSION 1282 +-- DB_UPDATE_VERSION 1283 -- ------------------------------------------ @@ -1173,6 +1173,18 @@ CREATE TABLE IF NOT EXISTS `userd` ( INDEX `username` (`username`(32)) ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Deleted usernames'; +-- +-- TABLE user-contact +-- +CREATE TABLE IF NOT EXISTS `user-contact` ( + `cid` int unsigned NOT NULL DEFAULT 0 COMMENT 'Contact id of the linked public contact', + `uid` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'User id', + `blocked` boolean COMMENT 'Contact is completely blocked for this user', + `ignored` boolean COMMENT 'Posts from this contact are ignored', + `collapsed` boolean COMMENT 'Posts from this contact are collapsed', + PRIMARY KEY(`uid`,`cid`) +) DEFAULT COLLATE utf8mb4_general_ci COMMENT='User specific public contact data'; + -- -- TABLE user-item -- diff --git a/include/conversation.php b/include/conversation.php index 5a26700fd7..ca01997f6a 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -517,6 +517,15 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o . "\r\n"; } + } elseif ($mode === 'contacts') { + $items = conversation_add_children($items, true, $order, $uid); + $profile_owner = 0; + + if (!$update) { + $live_update_div = '
' . "\r\n" + . "\r\n"; + } } elseif ($mode === 'search') { $live_update_div = '' . "\r\n"; } @@ -544,7 +553,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o $page_template = get_markup_template("conversation.tpl"); if (!empty($items)) { - if ($mode === 'community') { + if (in_array($mode, ['community', 'contacts'])) { $writable = true; } else { $writable = ($items[0]['uid'] == 0) && in_array($items[0]['network'], [Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]); diff --git a/mod/allfriends.php b/mod/allfriends.php index 32cd23ec6b..7623a9cd06 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -35,7 +35,7 @@ function allfriends_content(App $a) $uid = $a->user['uid']; - $contact = DBA::selectFirst('contact', ['name', 'url', 'photo'], ['id' => $cid, 'uid' => local_user()]); + $contact = DBA::selectFirst('contact', ['name', 'url', 'photo', 'uid', 'id'], ['id' => $cid, 'uid' => local_user()]); if (!DBA::isResult($contact)) { return; @@ -96,7 +96,7 @@ function allfriends_content(App $a) $entries[] = $entry; } - $tab_str = contacts_tab($a, $cid, 3); + $tab_str = contacts_tab($a, $contact, 4); $tpl = get_markup_template('viewcontact_template.tpl'); diff --git a/mod/common.php b/mod/common.php index 5955b51436..afe78ce460 100644 --- a/mod/common.php +++ b/mod/common.php @@ -38,14 +38,14 @@ function common_content(App $a) } if ($cmd === 'loc' && $cid) { - $contact = DBA::selectFirst('contact', ['name', 'url', 'photo'], ['id' => $cid, 'uid' => $uid]); + $contact = DBA::selectFirst('contact', ['name', 'url', 'photo', 'uid', 'id'], ['id' => $cid, 'uid' => $uid]); if (DBA::isResult($contact)) { $a->page['aside'] = ""; Profile::load($a, "", 0, Contact::getDetailsByURL($contact["url"])); } } else { - $contact = DBA::selectFirst('contact', ['name', 'url', 'photo'], ['self' => true, 'uid' => $uid]); + $contact = DBA::selectFirst('contact', ['name', 'url', 'photo', 'uid', 'id'], ['self' => true, 'uid' => $uid]); if (DBA::isResult($contact)) { $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), [ @@ -137,7 +137,7 @@ function common_content(App $a) $title = ''; $tab_str = ''; if ($cmd === 'loc' && $cid && local_user() == $uid) { - $tab_str = contacts_tab($a, $cid, 4); + $tab_str = contacts_tab($a, $contact, 4); } else { $title = L10n::t('Common Friends'); } diff --git a/mod/contacts.php b/mod/contacts.php index 9800dbdc1a..4e87697172 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -21,6 +21,7 @@ use Friendica\Model\Profile; use Friendica\Network\Probe; use Friendica\Util\DateTimeFormat; use Friendica\Util\Proxy as ProxyUtils; +use Friendica\Core\ACL; function contacts_init(App $a) { @@ -39,14 +40,18 @@ function contacts_init(App $a) $contact_id = null; $contact = null; - if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && ($a->argv[2] == "posts"))) { + if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']))) { $contact_id = intval($a->argv[1]); $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); + + if (!DBA::isResult($contact)) { + $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => 0]); + } } if (DBA::isResult($contact)) { if ($contact['self']) { - if (($a->argc == 3) && intval($a->argv[1]) && ($a->argv[2] == "posts")) { + if (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations'])) { goaway('profile/' . $contact['nick']); } else { goaway('profile/' . $contact['nick'] . '?tab=profile'); @@ -87,7 +92,11 @@ function contacts_init(App $a) $findpeople_widget = Widget::findPeople(); } - $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); + if ($contact['uid'] != 0) { + $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); + } else { + $groups_widget = null; + } $a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"), [ '$vcard_widget' => $vcard_widget, @@ -131,16 +140,12 @@ function contacts_batch_actions(App $a) $count_actions++; } if (x($_POST, 'contacts_batch_block')) { - $r = _contact_block($contact_id, $orig_record); - if ($r) { - $count_actions++; - } + _contact_block($contact_id); + $count_actions++; } if (x($_POST, 'contacts_batch_ignore')) { - $r = _contact_ignore($contact_id, $orig_record); - if ($r) { - $count_actions++; - } + _contact_ignore($contact_id); + $count_actions++; } if (x($_POST, 'contacts_batch_archive')) { $r = _contact_archive($contact_id, $orig_record); @@ -327,26 +332,16 @@ function _contact_update_profile($contact_id) GContact::updateFromProbe($data["url"]); } -function _contact_block($contact_id, $orig_record) +function _contact_block($contact_id) { - $blocked = (($orig_record['blocked']) ? 0 : 1); - $r = q("UPDATE `contact` SET `blocked` = %d WHERE `id` = %d AND `uid` = %d", - intval($blocked), - intval($contact_id), - intval(local_user()) - ); - return DBA::isResult($r); + $blocked = !Contact::isBlockedByUser($contact_id, local_user()); + Contact::setBlockedForUser($contact_id, local_user(), $blocked); } -function _contact_ignore($contact_id, $orig_record) +function _contact_ignore($contact_id) { - $readonly = (($orig_record['readonly']) ? 0 : 1); - $r = q("UPDATE `contact` SET `readonly` = %d WHERE `id` = %d AND `uid` = %d", - intval($readonly), - intval($contact_id), - intval(local_user()) - ); - return DBA::isResult($r); + $ignored = !Contact::isIgnoredByUser($contact_id, local_user()); + Contact::setIgnoredForUser($contact_id, local_user(), $ignored); } function _contact_archive($contact_id, $orig_record) @@ -376,7 +371,7 @@ function _contact_drop($orig_record) Contact::remove($orig_record['id']); } -function contacts_content(App $a) +function contacts_content(App $a, $update = 0) { $sort_type = 0; $o = ''; @@ -395,48 +390,46 @@ function contacts_content(App $a) $cmd = $a->argv[2]; - $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user(), 'self' => false]); + $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false]); if (!DBA::isResult($orig_record)) { notice(L10n::t('Could not access contact record.') . EOL); goaway('contacts'); return; // NOTREACHED } - if ($cmd === 'update') { + if ($cmd === 'update' && ($orig_record['uid'] != 0)) { _contact_update($contact_id); goaway('contacts/' . $contact_id); // NOTREACHED } - if ($cmd === 'updateprofile') { + if ($cmd === 'updateprofile' && ($orig_record['uid'] != 0)) { _contact_update_profile($contact_id); goaway('crepair/' . $contact_id); // NOTREACHED } if ($cmd === 'block') { - $r = _contact_block($contact_id, $orig_record); - if ($r) { - $blocked = (($orig_record['blocked']) ? 0 : 1); - info((($blocked) ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); - } + _contact_block($contact_id); + + $blocked = Contact::isBlockedByUser($contact_id, local_user()); + info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); goaway('contacts/' . $contact_id); return; // NOTREACHED } if ($cmd === 'ignore') { - $r = _contact_ignore($contact_id, $orig_record); - if ($r) { - $readonly = (($orig_record['readonly']) ? 0 : 1); - info((($readonly) ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); - } + _contact_ignore($contact_id); + + $ignored = Contact::isIgnoredByUser($contact_id, local_user()); + info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); goaway('contacts/' . $contact_id); return; // NOTREACHED } - if ($cmd === 'archive') { + if ($cmd === 'archive' && ($orig_record['uid'] != 0)) { $r = _contact_archive($contact_id, $orig_record); if ($r) { $archived = (($orig_record['archive']) ? 0 : 1); @@ -447,7 +440,7 @@ function contacts_content(App $a) return; // NOTREACHED } - if ($cmd === 'drop') { + if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { // Check if we should do HTML-based delete confirmation if (x($_REQUEST, 'confirm')) { // {{* End of the form *}} diff --git a/view/theme/frio/templates/contact_edit.tpl b/view/theme/frio/templates/contact_edit.tpl index 8dc0df38fe..a72ac5c605 100644 --- a/view/theme/frio/templates/contact_edit.tpl +++ b/view/theme/frio/templates/contact_edit.tpl @@ -26,8 +26,8 @@ {{/if}}