]> git.mxchange.org Git - friendica.git/blobdiff - src/Module/Contact.php
Use centralized function to fetch query results
[friendica.git] / src / Module / Contact.php
index b63aa0f5d72f04ba20883ee5abe80a95f8fbbb74..c7b2870ece4c9523ac7dcd78483727aadc9bdd8f 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * @copyright Copyright (C) 2010-2021, the Friendica project
+ * @copyright Copyright (C) 2010-2022, the Friendica project
  *
  * @license GNU AGPL version 3 or any later version
  *
@@ -25,10 +25,7 @@ use Friendica\BaseModule;
 use Friendica\Content\ContactSelector;
 use Friendica\Content\Nav;
 use Friendica\Content\Pager;
-use Friendica\Content\Text\BBCode;
 use Friendica\Content\Widget;
-use Friendica\Core\ACL;
-use Friendica\Core\Hook;
 use Friendica\Core\Protocol;
 use Friendica\Core\Renderer;
 use Friendica\Core\Theme;
@@ -38,10 +35,7 @@ use Friendica\DI;
 use Friendica\Model;
 use Friendica\Model\User;
 use Friendica\Module\Security\Login;
-use Friendica\Network\HTTPException\BadRequestException;
 use Friendica\Network\HTTPException\NotFoundException;
-use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Strings;
 
 /**
  *  Manages and show Contacts and their content
@@ -53,6 +47,7 @@ class Contact extends BaseModule
        const TAB_PROFILE = 3;
        const TAB_CONTACTS = 4;
        const TAB_ADVANCED = 5;
+       const TAB_MEDIA = 6;
 
        private static function batchActions()
        {
@@ -60,33 +55,32 @@ class Contact extends BaseModule
                        return;
                }
 
-               $contacts_id = $_POST['contact_batch'];
+               $redirectUrl = $_POST['redirect_url'] ?? 'contact';
 
-               $stmt = DBA::select('contact', ['id', 'archive'], ['id' => $contacts_id, 'uid' => local_user(), 'self' => false, 'deleted' => false]);
-               $orig_records = DBA::toArray($stmt);
+               self::checkFormSecurityTokenRedirectOnError($redirectUrl, 'contact_batch_actions');
+
+               $orig_records = Model\Contact::selectToArray(['id', 'uid'], ['id' => $_POST['contact_batch'], 'uid' => [0, local_user()], 'self' => false, 'deleted' => false]);
 
                $count_actions = 0;
                foreach ($orig_records as $orig_record) {
-                       $contact_id = $orig_record['id'];
-                       if (!empty($_POST['contacts_batch_update'])) {
-                               self::updateContactFromPoll($contact_id);
+                       $cdata = Model\Contact::getPublicAndUserContactID($orig_record['id'], local_user());
+                       if (empty($cdata) || public_contact() === $cdata['public']) {
+                               // No action available on your own contact
+                               continue;
+                       }
+
+                       if (!empty($_POST['contacts_batch_update']) && $cdata['user']) {
+                               self::updateContactFromPoll($cdata['user']);
                                $count_actions++;
                        }
+
                        if (!empty($_POST['contacts_batch_block'])) {
-                               self::blockContact($contact_id);
+                               self::toggleBlockContact($cdata['public'], local_user());
                                $count_actions++;
                        }
+
                        if (!empty($_POST['contacts_batch_ignore'])) {
-                               self::ignoreContact($contact_id);
-                               $count_actions++;
-                       }
-                       if (!empty($_POST['contacts_batch_archive'])
-                               && self::archiveContact($contact_id, $orig_record)
-                       ) {
-                               $count_actions++;
-                       }
-                       if (!empty($_POST['contacts_batch_drop'])) {
-                               self::dropContact($orig_record);
+                               self::toggleIgnoreContact($cdata['public']);
                                $count_actions++;
                        }
                }
@@ -94,13 +88,11 @@ class Contact extends BaseModule
                        info(DI::l10n()->tt('%d contact edited.', '%d contacts edited.', $count_actions));
                }
 
-               DI::baseUrl()->redirect('contact');
+               DI::baseUrl()->redirect($redirectUrl);
        }
 
-       public static function post(array $parameters = [])
+       protected function post(array $request = [])
        {
-               $a = DI::app();
-
                if (!local_user()) {
                        return;
                }
@@ -108,60 +100,18 @@ class Contact extends BaseModule
                // @TODO: Replace with parameter from router
                if (DI::args()->getArgv()[1] === 'batch') {
                        self::batchActions();
-                       return;
-               }
-
-               // @TODO: Replace with parameter from router
-               $contact_id = intval(DI::args()->getArgv()[1]);
-               if (!$contact_id) {
-                       return;
-               }
-
-               if (!DBA::exists('contact', ['id' => $contact_id, 'uid' => local_user(), 'deleted' => false])) {
-                       notice(DI::l10n()->t('Could not access contact record.'));
-                       DI::baseUrl()->redirect('contact');
-                       return; // NOTREACHED
-               }
-
-               Hook::callAll('contact_edit_post', $_POST);
-
-               $hidden = !empty($_POST['hidden']);
-
-               $notify = !empty($_POST['notify']);
-
-               $fetch_further_information = intval($_POST['fetch_further_information'] ?? 0);
-
-               $remote_self = $_POST['remote_self'] ?? false;
-
-               $ffi_keyword_denylist = Strings::escapeHtml(trim($_POST['ffi_keyword_denylist'] ?? ''));
-
-               $priority = intval($_POST['poll'] ?? 0);
-               if ($priority > 5 || $priority < 0) {
-                       $priority = 0;
-               }
-
-               $info = Strings::escapeHtml(trim($_POST['info'] ?? ''));
-
-               $r = DBA::update('contact', [
-                       'priority'   => $priority,
-                       'info'       => $info,
-                       'hidden'     => $hidden,
-                       'notify_new_posts' => $notify,
-                       'fetch_further_information' => $fetch_further_information,
-                       'remote_self' => $remote_self,
-                       'ffi_keyword_denylist'     => $ffi_keyword_denylist],
-                       ['id' => $contact_id, 'uid' => local_user()]
-               );
-
-               if (!DBA::isResult($r)) {
-                       notice(DI::l10n()->t('Failed to update contact record.'));
                }
-               return;
        }
 
        /* contact actions */
 
-       private static function updateContactFromPoll($contact_id)
+       /**
+        * @param int $contact_id Id of contact with uid != 0
+        * @throws NotFoundException
+        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+        * @throws \ImagickException
+        */
+       public static function updateContactFromPoll(int $contact_id)
        {
                $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user(), 'deleted' => false]);
                if (!DBA::isResult($contact)) {
@@ -169,11 +119,10 @@ class Contact extends BaseModule
                }
 
                if ($contact['network'] == Protocol::OSTATUS) {
-                       $user = Model\User::getById($contact['uid']);
-                       $result = Model\Contact::createFromProbe($user, $contact['url'], false, $contact['network']);
+                       $result = Model\Contact::createFromProbeForUser($contact['uid'], $contact['url'], $contact['network']);
 
                        if ($result['success']) {
-                               DBA::update('contact', ['subhub' => 1], ['id' => $contact_id]);
+                               Model\Contact::update(['subhub' => 1], ['id' => $contact_id]);
                        }
 
                        // pull feed and consume it, which should subscribe to the hub.
@@ -183,81 +132,41 @@ class Contact extends BaseModule
                }
        }
 
-       private static function updateContactFromProbe($contact_id)
-       {
-               $contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => [0, local_user()], 'deleted' => false]);
-               if (!DBA::isResult($contact)) {
-                       return;
-               }
-
-               // Update the entry in the contact table
-               Model\Contact::updateFromProbe($contact_id);
-       }
-
        /**
         * Toggles the blocked status of a contact identified by id.
         *
-        * @param $contact_id
+        * @param int $contact_id Id of the contact with uid = 0
+        * @param int $owner_id   Id of the user we want to block the contact for
         * @throws \Exception
         */
-       private static function blockContact($contact_id)
+       private static function toggleBlockContact(int $contact_id, int $owner_id)
        {
-               $blocked = !Model\Contact\User::isBlocked($contact_id, local_user());
-               Model\Contact\User::setBlocked($contact_id, local_user(), $blocked);
+               $blocked = !Model\Contact\User::isBlocked($contact_id, $owner_id);
+               Model\Contact\User::setBlocked($contact_id, $owner_id, $blocked);
        }
 
        /**
         * Toggles the ignored status of a contact identified by id.
         *
-        * @param $contact_id
+        * @param int $contact_id Id of the contact with uid = 0
         * @throws \Exception
         */
-       private static function ignoreContact($contact_id)
+       private static function toggleIgnoreContact(int $contact_id)
        {
                $ignored = !Model\Contact\User::isIgnored($contact_id, local_user());
                Model\Contact\User::setIgnored($contact_id, local_user(), $ignored);
        }
 
-       /**
-        * Toggles the archived status of a contact identified by id.
-        * If the current status isn't provided, this will always archive the contact.
-        *
-        * @param $contact_id
-        * @param $orig_record
-        * @return bool
-        * @throws \Exception
-        */
-       private static function archiveContact($contact_id, $orig_record)
-       {
-               $archived = empty($orig_record['archive']);
-               $r = DBA::update('contact', ['archive' => $archived], ['id' => $contact_id, 'uid' => local_user()]);
-
-               return DBA::isResult($r);
-       }
-
-       private static function dropContact($orig_record)
-       {
-               $owner = Model\User::getOwnerDataById(local_user());
-               if (!DBA::isResult($owner)) {
-                       return;
-               }
-
-               Model\Contact::terminateFriendship($owner, $orig_record, true);
-               Model\Contact::remove($orig_record['id']);
-       }
-
-       public static function content(array $parameters = [], $update = 0)
+       protected function content(array $request = []): string
        {
                if (!local_user()) {
                        return Login::form($_SERVER['REQUEST_URI']);
                }
 
-               $a = DI::app();
-
-               $search = Strings::escapeTags(trim($_GET['search'] ?? ''));
-               $nets   = Strings::escapeTags(trim($_GET['nets']   ?? ''));
-               $rel    = Strings::escapeTags(trim($_GET['rel']    ?? ''));
-               $group  = Strings::escapeTags(trim($_GET['group']  ?? ''));
+               $search = trim($_GET['search'] ?? '');
+               $nets   = trim($_GET['nets']   ?? '');
+               $rel    = trim($_GET['rel']    ?? '');
+               $group  = trim($_GET['group']  ?? '');
 
                $accounttype = $_GET['accounttype'] ?? '';
                $accounttypeid = User::getAccountTypeByString($accounttype);
@@ -269,65 +178,19 @@ class Contact extends BaseModule
                $page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.css'));
                $page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput-typeahead.css'));
 
-               $contact = null;
-               // @TODO: Replace with parameter from router
-               if (DI::args()->getArgc() == 2 && intval(DI::args()->getArgv()[1])
-                       || DI::args()->getArgc() == 3 && intval(DI::args()->getArgv()[1]) && in_array(DI::args()->getArgv()[2], ['posts', 'conversations'])
-               ) {
-                       $contact_id = intval(DI::args()->getArgv()[1]);
-
-                       // Ensure to use the user contact when the public contact was provided
-                       $data = Model\Contact::getPublicAndUserContactID($contact_id, local_user());
-                       if (!empty($data['user']) && ($contact_id == $data['public'])) {
-                               $contact_id = $data['user'];
-                       }
-
-                       $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'deleted' => false]);
-
-                       // Don't display contacts that are about to be deleted
-                       if ($contact['network'] == Protocol::PHANTOM) {
-                               $contact = false;
-                       }
-               }
-
-               if (DBA::isResult($contact)) {
-                       if ($contact['self']) {
-                               // @TODO: Replace with parameter from router
-                               if ((DI::args()->getArgc() == 3) && intval(DI::args()->getArgv()[1]) && in_array(DI::args()->getArgv()[2], ['posts', 'conversations'])) {
-                                       DI::baseUrl()->redirect('profile/' . $contact['nick']);
-                               } else {
-                                       DI::baseUrl()->redirect('profile/' . $contact['nick'] . '/profile');
-                               }
-                       }
-
-                       $vcard_widget = Widget\VCard::getHTML($contact);
-
-                       $findpeople_widget = '';
-                       $follow_widget = '';
-                       $account_widget = '';
-                       $networks_widget = '';
-                       $rel_widget = '';
-
-                       if ($contact['uid'] != 0) {
-                               $groups_widget = Model\Group::sidebarWidget('contact', 'group', 'full', 'everyone', $contact_id);
-                       } else {
-                               $groups_widget = '';
-                       }
+               $vcard_widget = '';
+               $findpeople_widget = Widget::findPeople();
+               if (isset($_GET['add'])) {
+                       $follow_widget = Widget::follow($_GET['add']);
                } else {
-                       $vcard_widget = '';
-                       $findpeople_widget = Widget::findPeople();
-                       if (isset($_GET['add'])) {
-                               $follow_widget = Widget::follow($_GET['add']);
-                       } else {
-                               $follow_widget = Widget::follow();
-                       }
-
-                       $account_widget = Widget::accounttypes($_SERVER['REQUEST_URI'], $accounttype);
-                       $networks_widget = Widget::networks($_SERVER['REQUEST_URI'], $nets);
-                       $rel_widget = Widget::contactRels($_SERVER['REQUEST_URI'], $rel);
-                       $groups_widget = Widget::groups($_SERVER['REQUEST_URI'], $group);
+                       $follow_widget = Widget::follow();
                }
 
+               $account_widget = Widget::accounttypes($_SERVER['REQUEST_URI'], $accounttype);
+               $networks_widget = Widget::networks($_SERVER['REQUEST_URI'], $nets);
+               $rel_widget = Widget::contactRels($_SERVER['REQUEST_URI'], $rel);
+               $groups_widget = Widget::groups($_SERVER['REQUEST_URI'], $group);
+
                DI::page()['aside'] .= $vcard_widget . $findpeople_widget . $follow_widget . $account_widget . $groups_widget . $networks_widget . $rel_widget;
 
                $tpl = Renderer::getMarkupTemplate('contacts-head.tpl');
@@ -338,304 +201,8 @@ class Contact extends BaseModule
                $o = '';
                Nav::setSelected('contact');
 
-               if (!local_user()) {
-                       notice(DI::l10n()->t('Permission denied.'));
-                       return Login::form();
-               }
-
-               if (DI::args()->getArgc() == 3) {
-                       $contact_id = intval(DI::args()->getArgv()[1]);
-                       if (!$contact_id) {
-                               throw new BadRequestException();
-                       }
-
-                       // @TODO: Replace with parameter from router
-                       $cmd = DI::args()->getArgv()[2];
-
-                       $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false, 'deleted' => false]);
-                       if (!DBA::isResult($orig_record)) {
-                               throw new NotFoundException(DI::l10n()->t('Contact not found'));
-                       }
-
-                       if ($cmd === 'update' && ($orig_record['uid'] != 0)) {
-                               self::updateContactFromPoll($contact_id);
-                               DI::baseUrl()->redirect('contact/' . $contact_id);
-                               // NOTREACHED
-                       }
-
-                       if ($cmd === 'updateprofile') {
-                               self::updateContactFromProbe($contact_id);
-                               DI::baseUrl()->redirect('contact/' . $contact_id);
-                               // NOTREACHED
-                       }
-
-                       if ($cmd === 'block') {
-                               if (public_contact() === $contact_id) {
-                                       throw new BadRequestException(DI::l10n()->t('You can\'t block yourself'));
-                               }
-
-                               self::blockContact($contact_id);
-
-                               $blocked = Model\Contact\User::isBlocked($contact_id, local_user());
-                               info(($blocked ? DI::l10n()->t('Contact has been blocked') : DI::l10n()->t('Contact has been unblocked')));
-
-                               DI::baseUrl()->redirect('contact/' . $contact_id);
-                               // NOTREACHED
-                       }
-
-                       if ($cmd === 'ignore') {
-                               if (public_contact() === $contact_id) {
-                                       throw new BadRequestException(DI::l10n()->t('You can\'t ignore yourself'));
-                               }
-
-                               self::ignoreContact($contact_id);
-
-                               $ignored = Model\Contact\User::isIgnored($contact_id, local_user());
-                               info(($ignored ? DI::l10n()->t('Contact has been ignored') : DI::l10n()->t('Contact has been unignored')));
-
-                               DI::baseUrl()->redirect('contact/' . $contact_id);
-                               // NOTREACHED
-                       }
-
-                       if ($cmd === 'archive' && ($orig_record['uid'] != 0)) {
-                               $r = self::archiveContact($contact_id, $orig_record);
-                               if ($r) {
-                                       $archived = (($orig_record['archive']) ? 0 : 1);
-                                       info((($archived) ? DI::l10n()->t('Contact has been archived') : DI::l10n()->t('Contact has been unarchived')));
-                               }
-
-                               DI::baseUrl()->redirect('contact/' . $contact_id);
-                               // NOTREACHED
-                       }
-
-                       if ($cmd === 'drop' && ($orig_record['uid'] != 0)) {
-                               // Check if we should do HTML-based delete confirmation
-                               if (!empty($_REQUEST['confirm'])) {
-                                       DI::page()['aside'] = '';
-
-                                       return Renderer::replaceMacros(Renderer::getMarkupTemplate('contact_drop_confirm.tpl'), [
-                                               '$header' => DI::l10n()->t('Drop contact'),
-                                               '$contact' => self::getContactTemplateVars($orig_record),
-                                               '$method' => 'get',
-                                               '$message' => DI::l10n()->t('Do you really want to delete this contact?'),
-                                               '$confirm' => DI::l10n()->t('Yes'),
-                                               '$confirm_url' => DI::args()->getCommand(),
-                                               '$confirm_name' => 'confirmed',
-                                               '$cancel' => DI::l10n()->t('Cancel'),
-                                       ]);
-                               }
-                               // Now check how the user responded to the confirmation query
-                               if (!empty($_REQUEST['canceled'])) {
-                                       DI::baseUrl()->redirect('contact');
-                               }
-
-                               self::dropContact($orig_record);
-                               info(DI::l10n()->t('Contact has been removed.'));
-
-                               DI::baseUrl()->redirect('contact');
-                               // NOTREACHED
-                       }
-                       if ($cmd === 'posts') {
-                               return self::getPostsHTML($a, $contact_id);
-                       }
-                       if ($cmd === 'conversations') {
-                               return self::getConversationsHMTL($a, $contact_id, $update);
-                       }
-               }
-
                $_SESSION['return_path'] = DI::args()->getQueryString();
 
-               if (!empty($contact)) {
-                       DI::page()['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('contact_head.tpl'), [
-                               '$baseurl' => DI::baseUrl()->get(true),
-                       ]);
-
-                       $contact['blocked']  = Model\Contact\User::isBlocked($contact['id'], local_user());
-                       $contact['readonly'] = Model\Contact\User::isIgnored($contact['id'], local_user());
-
-                       $relation_text = '';
-                       switch ($contact['rel']) {
-                               case Model\Contact::FRIEND:
-                                       $relation_text = DI::l10n()->t('You are mutual friends with %s');
-                                       break;
-
-                               case Model\Contact::FOLLOWER;
-                                       $relation_text = DI::l10n()->t('You are sharing with %s');
-                                       break;
-
-                               case Model\Contact::SHARING;
-                                       $relation_text = DI::l10n()->t('%s is sharing with you');
-                                       break;
-
-                               default:
-                                       break;
-                       }
-
-                       if ($contact['uid'] == 0) {
-                               $relation_text = '';
-                       }
-
-                       if (!in_array($contact['network'], array_merge(Protocol::FEDERATED, [Protocol::TWITTER]))) {
-                               $relation_text = '';
-                       }
-
-                       $relation_text = sprintf($relation_text, $contact['name']);
-
-                       $url = Model\Contact::magicLinkByContact($contact);
-                       if (strpos($url, 'redir/') === 0) {
-                               $sparkle = ' class="sparkle" ';
-                       } else {
-                               $sparkle = '';
-                       }
-
-                       $insecure = DI::l10n()->t('Private communications are not available for this contact.');
-
-                       $last_update = (($contact['last-update'] <= DBA::NULL_DATETIME) ? DI::l10n()->t('Never') : DateTimeFormat::local($contact['last-update'], 'D, j M Y, g:i A'));
-
-                       if ($contact['last-update'] > DBA::NULL_DATETIME) {
-                               $last_update .= ' ' . ($contact['failed'] ? DI::l10n()->t('(Update was not successful)') : DI::l10n()->t('(Update was successful)'));
-                       }
-                       $lblsuggest = (($contact['network'] === Protocol::DFRN) ? DI::l10n()->t('Suggest friends') : '');
-
-                       $poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]);
-
-                       $nettype = DI::l10n()->t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact['url'], $contact['protocol'], $contact['gsid']));
-
-                       // tabs
-                       $tab_str = self::getTabsHTML($contact, self::TAB_PROFILE);
-
-                       $lost_contact = (($contact['archive'] && $contact['term-date'] > DBA::NULL_DATETIME && $contact['term-date'] < DateTimeFormat::utcNow()) ? DI::l10n()->t('Communications lost with this contact!') : '');
-
-                       $fetch_further_information = null;
-                       if ($contact['network'] == Protocol::FEED) {
-                               $fetch_further_information = [
-                                       'fetch_further_information',
-                                       DI::l10n()->t('Fetch further information for feeds'),
-                                       $contact['fetch_further_information'],
-                                       DI::l10n()->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.'),
-                                       [
-                                               '0' => DI::l10n()->t('Disabled'),
-                                               '1' => DI::l10n()->t('Fetch information'),
-                                               '3' => DI::l10n()->t('Fetch keywords'),
-                                               '2' => DI::l10n()->t('Fetch information and keywords')
-                                       ]
-                               ];
-                       }
-
-                       // Disable remote self for everything except feeds.
-                       // There is an issue when you repeat an item from maybe twitter and you got comments from friendica and twitter
-                       // Problem is, you couldn't reply to both networks.
-                       $allow_remote_self = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::FEED, Protocol::DFRN, Protocol::DIASPORA, Protocol::TWITTER])
-                               && DI::config()->get('system', 'allow_users_remote_self');
-
-                       if ($contact['network'] == Protocol::FEED) {
-                               $remote_self_options = [Model\Contact::MIRROR_DEACTIVATED => DI::l10n()->t('No mirroring'),
-                                       Model\Contact::MIRROR_FORWARDED => DI::l10n()->t('Mirror as forwarded posting'),
-                                       Model\Contact::MIRROR_OWN_POST => DI::l10n()->t('Mirror as my own posting')];
-                       } elseif (in_array($contact['network'], [Protocol::ACTIVITYPUB])) {
-                               $remote_self_options = [Model\Contact::MIRROR_DEACTIVATED => DI::l10n()->t('No mirroring'),
-                               Model\Contact::MIRROR_NATIVE_RESHARE => DI::l10n()->t('Native reshare')];
-                       } elseif (in_array($contact['network'], [Protocol::DFRN])) {
-                               $remote_self_options = [Model\Contact::MIRROR_DEACTIVATED => DI::l10n()->t('No mirroring'),
-                               Model\Contact::MIRROR_OWN_POST => DI::l10n()->t('Mirror as my own posting'),
-                               Model\Contact::MIRROR_NATIVE_RESHARE => DI::l10n()->t('Native reshare')];
-                       } else {
-                               $remote_self_options = [Model\Contact::MIRROR_DEACTIVATED => DI::l10n()->t('No mirroring'),
-                                       Model\Contact::MIRROR_OWN_POST => DI::l10n()->t('Mirror as my own posting')];
-                       }
-
-                       $poll_interval = null;
-                       if ((($contact['network'] == Protocol::FEED) && !DI::config()->get('system', 'adjust_poll_frequency')) || ($contact['network']== Protocol::MAIL)) {
-                               $poll_interval = ContactSelector::pollInterval($contact['priority'], !$poll_enabled);
-                       }
-
-                       // Load contactact related actions like hide, suggest, delete and others
-                       $contact_actions = self::getContactActions($contact);
-
-                       if ($contact['uid'] != 0) {
-                               $lbl_info1 = DI::l10n()->t('Contact Information / Notes');
-                               $contact_settings_label = DI::l10n()->t('Contact Settings');
-                       } else {
-                               $lbl_info1 = null;
-                               $contact_settings_label = null;
-                       }
-
-                       $tpl = Renderer::getMarkupTemplate('contact_edit.tpl');
-                       $o .= Renderer::replaceMacros($tpl, [
-                               '$header'         => DI::l10n()->t('Contact'),
-                               '$tab_str'        => $tab_str,
-                               '$submit'         => DI::l10n()->t('Submit'),
-                               '$lbl_info1'      => $lbl_info1,
-                               '$lbl_info2'      => DI::l10n()->t('Their personal note'),
-                               '$reason'         => trim(Strings::escapeTags($contact['reason'])),
-                               '$infedit'        => DI::l10n()->t('Edit contact notes'),
-                               '$common_link'    => 'contact/' . $contact['id'] . '/contacts/common',
-                               '$relation_text'  => $relation_text,
-                               '$visit'          => DI::l10n()->t('Visit %s\'s profile [%s]', $contact['name'], $contact['url']),
-                               '$blockunblock'   => DI::l10n()->t('Block/Unblock contact'),
-                               '$ignorecont'     => DI::l10n()->t('Ignore contact'),
-                               '$lblrecent'      => DI::l10n()->t('View conversations'),
-                               '$lblsuggest'     => $lblsuggest,
-                               '$nettype'        => $nettype,
-                               '$poll_interval'  => $poll_interval,
-                               '$poll_enabled'   => $poll_enabled,
-                               '$lastupdtext'    => DI::l10n()->t('Last update:'),
-                               '$lost_contact'   => $lost_contact,
-                               '$updpub'         => DI::l10n()->t('Update public posts'),
-                               '$last_update'    => $last_update,
-                               '$udnow'          => DI::l10n()->t('Update now'),
-                               '$contact_id'     => $contact['id'],
-                               '$block_text'     => ($contact['blocked'] ? DI::l10n()->t('Unblock') : DI::l10n()->t('Block')),
-                               '$ignore_text'    => ($contact['readonly'] ? DI::l10n()->t('Unignore') : DI::l10n()->t('Ignore')),
-                               '$insecure'       => (in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA]) ? '' : $insecure),
-                               '$info'           => $contact['info'],
-                               '$cinfo'          => ['info', '', $contact['info'], ''],
-                               '$blocked'        => ($contact['blocked'] ? DI::l10n()->t('Currently blocked') : ''),
-                               '$ignored'        => ($contact['readonly'] ? DI::l10n()->t('Currently ignored') : ''),
-                               '$archived'       => ($contact['archive'] ? DI::l10n()->t('Currently archived') : ''),
-                               '$pending'        => ($contact['pending'] ? DI::l10n()->t('Awaiting connection acknowledge') : ''),
-                               '$hidden'         => ['hidden', DI::l10n()->t('Hide this contact from others'), ($contact['hidden'] == 1), DI::l10n()->t('Replies/likes to your public posts <strong>may</strong> still be visible')],
-                               '$notify'         => ['notify', DI::l10n()->t('Notification for new posts'), ($contact['notify_new_posts'] == 1), DI::l10n()->t('Send a notification of every new post of this contact')],
-                               '$fetch_further_information' => $fetch_further_information,
-                               '$ffi_keyword_denylist' => ['ffi_keyword_denylist', DI::l10n()->t('Keyword Deny List'), $contact['ffi_keyword_denylist'], DI::l10n()->t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')],
-                               '$photo'          => Model\Contact::getPhoto($contact),
-                               '$name'           => $contact['name'],
-                               '$sparkle'        => $sparkle,
-                               '$url'            => $url,
-                               '$profileurllabel'=> DI::l10n()->t('Profile URL'),
-                               '$profileurl'     => $contact['url'],
-                               '$account_type'   => Model\Contact::getAccountType($contact),
-                               '$location'       => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['location']),
-                               '$location_label' => DI::l10n()->t('Location:'),
-                               '$xmpp'           => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['xmpp']),
-                               '$xmpp_label'     => DI::l10n()->t('XMPP:'),
-                               '$matrix'         => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['matrix']),
-                               '$matrix_label'   => DI::l10n()->t('Matrix:'),
-                               '$about'          => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['about'], BBCode::EXTERNAL),
-                               '$about_label'    => DI::l10n()->t('About:'),
-                               '$keywords'       => $contact['keywords'],
-                               '$keywords_label' => DI::l10n()->t('Tags:'),
-                               '$contact_action_button' => DI::l10n()->t('Actions'),
-                               '$contact_actions'=> $contact_actions,
-                               '$contact_status' => DI::l10n()->t('Status'),
-                               '$contact_settings_label' => $contact_settings_label,
-                               '$contact_profile_label' => DI::l10n()->t('Profile'),
-                               '$allow_remote_self' => $allow_remote_self,
-                               '$remote_self'       => ['remote_self',
-                                       DI::l10n()->t('Mirror postings from this contact'),
-                                       $contact['remote_self'],
-                                       DI::l10n()->t('Mark this contact as remote_self, this will cause friendica to repost new entries from this contact.'),
-                                       $remote_self_options
-                               ],
-                       ]);
-
-                       $arr = ['contact' => $contact, 'output' => $o];
-
-                       Hook::callAll('contact_edit', $arr);
-
-                       return $arr['output'];
-               }
-
                $sql_values = [local_user()];
 
                // @TODO: Replace with parameter from router
@@ -708,42 +275,25 @@ class Contact extends BaseModule
                }
 
                if ($group) {
-                       $sql_extra = " AND EXISTS(SELECT `id` FROM `group_member` WHERE `gid` = ? AND `contact`.`id` = `contact-id`)";
+                       $sql_extra .= " AND EXISTS(SELECT `id` FROM `group_member` WHERE `gid` = ? AND `contact`.`id` = `contact-id`)";
                        $sql_values[] = $group;
                }
 
-               $total = 0;
-               $stmt = DBA::p("SELECT COUNT(*) AS `total`
-                       FROM `contact`
-                       WHERE `uid` = ?
-                       AND `self` = 0
-                       AND NOT `deleted`
-                       $sql_extra
-                       " . Widget::unavailableNetworks(),
-                       $sql_values
-               );
-               if (DBA::isResult($stmt)) {
-                       $total = DBA::fetch($stmt)['total'];
-               }
-               DBA::close($stmt);
+               $networks = Widget::unavailableNetworks();
+               $sql_extra .= " AND NOT `network` IN (" . substr(str_repeat("?, ", count($networks)), 0, -2) . ")";
+               $sql_values = array_merge($sql_values, $networks);
 
-               $pager = new Pager(DI::l10n(), DI::args()->getQueryString());
+               $condition = ["`uid` = ? AND NOT `self` AND NOT `deleted`" . $sql_extra];
+               $condition = array_merge($condition, $sql_values);
+
+               $total = DBA::count('contact', $condition);
 
-               $sql_values[] = $pager->getStart();
-               $sql_values[] = $pager->getItemsPerPage();
+               $pager = new Pager(DI::l10n(), DI::args()->getQueryString());
 
                $contacts = [];
 
-               $stmt = DBA::p("SELECT *
-                       FROM `contact`
-                       WHERE `uid` = ?
-                       AND `self` = 0
-                       AND NOT `deleted`
-                       $sql_extra
-                       ORDER BY `name` ASC
-                       LIMIT ?, ?",
-                       $sql_values
-               );
+               $stmt = DBA::select('contact', [], $condition, ['order' => ['name'], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]]);
+
                while ($contact = DBA::fetch($stmt)) {
                        $contact['blocked'] = Model\Contact\User::isBlocked($contact['id'], local_user());
                        $contact['readonly'] = Model\Contact\User::isIgnored($contact['id'], local_user());
@@ -841,14 +391,12 @@ class Contact extends BaseModule
                        '$submit'     => DI::l10n()->t('Find'),
                        '$cmd'        => DI::args()->getCommand(),
                        '$contacts'   => $contacts,
-                       '$contact_drop_confirm' => DI::l10n()->t('Do you really want to delete this contact?'),
+                       '$form_security_token'  => BaseModule::getFormSecurityToken('contact_batch_actions'),
                        'multiselect' => 1,
                        '$batch_actions' => [
                                'contacts_batch_update'  => DI::l10n()->t('Update'),
                                'contacts_batch_block'   => DI::l10n()->t('Block') . '/' . DI::l10n()->t('Unblock'),
                                'contacts_batch_ignore'  => DI::l10n()->t('Ignore') . '/' . DI::l10n()->t('Unignore'),
-                               'contacts_batch_archive' => DI::l10n()->t('Archive') . '/' . DI::l10n()->t('Unarchive'),
-                               'contacts_batch_drop'    => DI::l10n()->t('Delete'),
                        ],
                        '$h_batch_actions' => DI::l10n()->t('Batch Actions'),
                        '$paginate'   => $pager->renderFull($total),
@@ -897,6 +445,14 @@ class Contact extends BaseModule
                                'id'    => 'posts-tab',
                                'accesskey' => 'p',
                        ],
+                       [
+                               'label' => DI::l10n()->t('Media'),
+                               'url'   => 'contact/' . $pcid . '/media',
+                               'sel'   => (($active_tab == self::TAB_MEDIA) ? 'active' : ''),
+                               'title' => DI::l10n()->t('Posts containing media objects'),
+                               'id'    => 'media-tab',
+                               'accesskey' => 'd',
+                       ],
                        [
                                'label' => DI::l10n()->t('Profile'),
                                'url'   => 'contact/' . $cid,
@@ -930,77 +486,6 @@ class Contact extends BaseModule
                return $tab_str;
        }
 
-       public static function getConversationsHMTL($a, $contact_id, $update, $parent = 0)
-       {
-               $o = '';
-
-               if (!$update) {
-                       // We need the editor here to be able to reshare an item.
-                       if (local_user()) {
-                               $x = [
-                                       'is_owner' => true,
-                                       'allow_location' => $a->user['allow_location'],
-                                       'default_location' => $a->user['default-location'],
-                                       'nickname' => $a->user['nickname'],
-                                       'lockstate' => (is_array($a->user) && (strlen($a->user['allow_cid']) || strlen($a->user['allow_gid']) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid'])) ? 'lock' : 'unlock'),
-                                       'acl' => ACL::getFullSelectorHTML(DI::page(), $a->user, true),
-                                       'bang' => '',
-                                       'visitor' => 'block',
-                                       'profile_uid' => local_user(),
-                               ];
-                               $o = status_editor($a, $x, 0, true);
-                       }
-               }
-
-               $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id, 'deleted' => false]);
-
-               if (!$update) {
-                       $o .= self::getTabsHTML($contact, self::TAB_CONVERSATIONS);
-               }
-
-               if (DBA::isResult($contact)) {
-                       if (!$update) {
-                               $profiledata = Model\Contact::getByURLForUser($contact['url'], local_user());
-                               DI::page()['aside'] = Widget\VCard::getHTML($profiledata);
-                       } else {
-                               DI::page()['aside'] = '';
-                       }
-
-                       if ($contact['uid'] == 0) {
-                               $o .= Model\Contact::getPostsFromId($contact['id'], true, $update, $parent);
-                       } else {
-                               $o .= Model\Contact::getPostsFromUrl($contact['url'], true, $update, $parent);
-                       }
-               }
-
-               return $o;
-       }
-
-       private static function getPostsHTML($a, $contact_id)
-       {
-               $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id, 'deleted' => false]);
-
-               $o = self::getTabsHTML($contact, self::TAB_POSTS);
-
-               if (DBA::isResult($contact)) {
-                       $profiledata = Model\Contact::getByURLForUser($contact['url'], local_user());
-
-                       if (local_user() && in_array($profiledata['network'], Protocol::FEDERATED)) {
-                               $profiledata['remoteconnect'] = DI::baseUrl() . '/follow?url=' . urlencode($profiledata['url']);
-                       }
-
-                       DI::page()['aside'] = Widget\VCard::getHTML($profiledata);
-
-                       if ($contact['uid'] == 0) {
-                               $o .= Model\Contact::getPostsFromId($contact['id']);
-                       } else {
-                               $o .= Model\Contact::getPostsFromUrl($contact['url']);
-                       }
-               }
-
-               return $o;
-       }
-
        /**
         * Return the fields for the contact template
         *
@@ -1073,91 +558,10 @@ class Contact extends BaseModule
                        'details'      => $contact['location'],
                        'tags'         => $contact['keywords'],
                        'about'        => $contact['about'],
-                       'account_type' => Model\Contact::getAccountType($contact),
+                       'account_type' => Model\Contact::getAccountType($contact['contact-type']),
                        'sparkle'      => $sparkle,
                        'itemurl'      => ($contact['addr'] ?? '') ?: $contact['url'],
                        'network'      => ContactSelector::networkToName($contact['network'], $contact['url'], $contact['protocol'], $contact['gsid']),
                ];
        }
-
-       /**
-        * Gives a array with actions which can performed to a given contact
-        *
-        * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others
-        *
-        * @param array $contact Data about the Contact
-        * @return array with contact related actions
-        */
-       private static function getContactActions($contact)
-       {
-               $poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]);
-               $contact_actions = [];
-
-               // Provide friend suggestion only for Friendica contacts
-               if ($contact['network'] === Protocol::DFRN) {
-                       $contact_actions['suggest'] = [
-                               'label' => DI::l10n()->t('Suggest friends'),
-                               'url'   => 'fsuggest/' . $contact['id'],
-                               'title' => '',
-                               'sel'   => '',
-                               'id'    => 'suggest',
-                       ];
-               }
-
-               if ($poll_enabled) {
-                       $contact_actions['update'] = [
-                               'label' => DI::l10n()->t('Update now'),
-                               'url'   => 'contact/' . $contact['id'] . '/update',
-                               'title' => '',
-                               'sel'   => '',
-                               'id'    => 'update',
-                       ];
-               }
-
-               if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
-                       $contact_actions['updateprofile'] = [
-                               'label' => DI::l10n()->t('Refetch contact data'),
-                               'url'   => 'contact/' . $contact['id'] . '/updateprofile',
-                               'title' => '',
-                               'sel'   => '',
-                               'id'    => 'updateprofile',
-                       ];
-               }
-
-               $contact_actions['block'] = [
-                       'label' => (intval($contact['blocked']) ? DI::l10n()->t('Unblock') : DI::l10n()->t('Block')),
-                       'url'   => 'contact/' . $contact['id'] . '/block',
-                       'title' => DI::l10n()->t('Toggle Blocked status'),
-                       'sel'   => (intval($contact['blocked']) ? 'active' : ''),
-                       'id'    => 'toggle-block',
-               ];
-
-               $contact_actions['ignore'] = [
-                       'label' => (intval($contact['readonly']) ? DI::l10n()->t('Unignore') : DI::l10n()->t('Ignore')),
-                       'url'   => 'contact/' . $contact['id'] . '/ignore',
-                       'title' => DI::l10n()->t('Toggle Ignored status'),
-                       'sel'   => (intval($contact['readonly']) ? 'active' : ''),
-                       'id'    => 'toggle-ignore',
-               ];
-
-               if ($contact['uid'] != 0) {
-                       $contact_actions['archive'] = [
-                               'label' => (intval($contact['archive']) ? DI::l10n()->t('Unarchive') : DI::l10n()->t('Archive')),
-                               'url'   => 'contact/' . $contact['id'] . '/archive',
-                               'title' => DI::l10n()->t('Toggle Archive status'),
-                               'sel'   => (intval($contact['archive']) ? 'active' : ''),
-                               'id'    => 'toggle-archive',
-                       ];
-
-                       $contact_actions['delete'] = [
-                               'label' => DI::l10n()->t('Delete'),
-                               'url'   => 'contact/' . $contact['id'] . '/drop',
-                               'title' => DI::l10n()->t('Delete contact'),
-                               'sel'   => '',
-                               'id'    => 'delete',
-                       ];
-               }
-
-               return $contact_actions;
-       }
 }