From: Hypolite Petovan Date: Thu, 7 Dec 2017 14:04:24 +0000 (-0500) Subject: Move Object\Contact to Model\Contact X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=a42595a30c6f6644674e3827c2867af37788b2d1;p=friendica.git Move Object\Contact to Model\Contact --- diff --git a/boot.php b/boot.php index 148ca5e6e2..fa26028113 100644 --- a/boot.php +++ b/boot.php @@ -27,8 +27,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Object\Contact; -use Friendica\Util\Lock; +use Friendica\Model\Contact; require_once 'include/network.php'; require_once 'include/plugin.php'; diff --git a/include/acl_selectors.php b/include/acl_selectors.php index f971d462b2..4ef6733035 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -6,8 +6,8 @@ use Friendica\App; use Friendica\Content\Feature; use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; -use Friendica\Object\Contact; require_once "include/contact_selectors.php"; require_once "include/contact_widgets.php"; diff --git a/include/api.php b/include/api.php index 37cf1eba05..e5963fb8fa 100644 --- a/include/api.php +++ b/include/api.php @@ -12,6 +12,7 @@ use Friendica\Core\Config; use Friendica\Core\NotificationsManager; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\Photo; use Friendica\Model\User; use Friendica\Network\FKOAuth1; @@ -24,7 +25,6 @@ use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\HTTPException\NotImplementedException; use Friendica\Network\HTTPException\UnauthorizedException; use Friendica\Network\HTTPException\TooManyRequestsException; -use Friendica\Object\Contact; use Friendica\Object\Image; use Friendica\Protocol\Diaspora; use Friendica\Util\XML; diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php index 3b1540473a..e1a67d432d 100644 --- a/include/bb2diaspora.php +++ b/include/bb2diaspora.php @@ -2,8 +2,8 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Model\Contact; use Friendica\Network\Probe; -use Friendica\Object\Contact; use League\HTMLToMarkdown\HtmlConverter; diff --git a/include/bbcode.php b/include/bbcode.php index 196c3ca3c1..b445fd01b0 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -5,7 +5,7 @@ use Friendica\Content\Smilies; use Friendica\Core\Cache; use Friendica\Core\System; use Friendica\Core\Config; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/oembed.php'; require_once 'include/event.php'; diff --git a/include/follow.php b/include/follow.php index 14b9c68ed5..e08136cab1 100644 --- a/include/follow.php +++ b/include/follow.php @@ -7,8 +7,8 @@ use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Network\Probe; -use Friendica\Object\Contact; use Friendica\Protocol\Diaspora; use Friendica\Protocol\OStatus; use Friendica\Protocol\PortableContact; diff --git a/include/identity.php b/include/identity.php index a3a007cc18..9a0900dc1f 100644 --- a/include/identity.php +++ b/include/identity.php @@ -12,7 +12,7 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/bbcode.php'; require_once 'mod/proxy.php'; diff --git a/include/items.php b/include/items.php index c32b4a0ba5..44fca51d8f 100644 --- a/include/items.php +++ b/include/items.php @@ -10,8 +10,8 @@ use Friendica\Core\PConfig; use Friendica\Core\Worker; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; -use Friendica\Object\Contact; use Friendica\Object\Image; use Friendica\Protocol\DFRN; use Friendica\Protocol\OStatus; diff --git a/include/like.php b/include/like.php index 1dcadde705..9a8b9b957b 100644 --- a/include/like.php +++ b/include/like.php @@ -4,7 +4,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; use Friendica\Protocol\Diaspora; /** diff --git a/include/post_update.php b/include/post_update.php index f67c064daf..7cbc6ece0d 100644 --- a/include/post_update.php +++ b/include/post_update.php @@ -5,8 +5,8 @@ use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; -use Friendica\Object\Contact; /** * @brief Calls the post update functions diff --git a/include/tags.php b/include/tags.php index 45a17f9c96..8d8fb76559 100644 --- a/include/tags.php +++ b/include/tags.php @@ -6,7 +6,7 @@ use Friendica\App; use Friendica\Content\Feature; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; function create_tags_from_item($itemid) { $profile_base = System::baseUrl(); @@ -157,13 +157,13 @@ function update_items() { /** * @brief Get alphabetical sorted array of used tags/terms of an user including * a weighting by frequency of use. - * + * * @param int $uid The user ID. * @param int $count Max number of displayed tags/terms. * @param int $owner_id The contact id of the owner of the tagged items. * @param string $flags Special item flags. * @param int $type The tag/term type. - * + * * @return arr Alphabetical sorted array of used tags of an user. */ function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG) { @@ -197,19 +197,19 @@ function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HA if(!DBM::is_result($r)) { return array(); } - + return tag_calc($r); } /** * @brief Construct a tag/term cloud block for an user. - * + * * @param int $uid The user ID. * @param int $count Max number of displayed tags/terms. * @param int $owner_id The contact ID of the owner of the tagged items. * @param string $flags Special item flags. * @param int $type The tag/term type. - * + * * @return string HTML formatted output. */ function wtagblock($uid, $count = 0,$owner_id = 0, $flags = '', $type = TERM_HASHTAG) { @@ -244,7 +244,7 @@ function wtagblock($uid, $count = 0,$owner_id = 0, $flags = '', $type = TERM_HAS /** * @brief Calculate weighting of tags according to the frequency of use. - * + * * @param array $arr Array of tags/terms with tag/term name and total count of use. * @return array Alphabetical sorted array of used tags/terms of an user. */ @@ -279,10 +279,10 @@ function tag_calc($arr) { /** * @brief Compare function to sort tags/terms alphabetically. - * + * * @param type $a * @param type $b - * + * * @return int */ function tags_sort($a, $b) { @@ -294,7 +294,7 @@ function tags_sort($a, $b) { /** * @brief Insert a tag cloud widget for the present profile. - * + * * @param int $limit Max number of displayed tags. * @return string HTML formattat output. */ diff --git a/include/threads.php b/include/threads.php index 00848ccc6e..494fbe1ce3 100644 --- a/include/threads.php +++ b/include/threads.php @@ -3,7 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; function add_thread($itemid, $onlyshadow = false) { $items = q("SELECT `uid`, `created`, `edited`, `commented`, `received`, `changed`, `wall`, `private`, `pubmail`, diff --git a/mod/admin.php b/mod/admin.php index 29e10bda83..321e7b6172 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -10,8 +10,8 @@ use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\User; -use Friendica\Object\Contact; require_once 'include/enotify.php'; require_once 'include/text.php'; diff --git a/mod/allfriends.php b/mod/allfriends.php index 3cfe6c0f9e..1eb4b0e1c4 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -5,8 +5,8 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; -use Friendica\Object\Contact; require_once 'include/contact_selectors.php'; require_once 'mod/contacts.php'; diff --git a/mod/cal.php b/mod/cal.php index 7eb31905b8..cef9857ea9 100644 --- a/mod/cal.php +++ b/mod/cal.php @@ -11,7 +11,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/event.php'; require_once 'include/redir.php'; diff --git a/mod/common.php b/mod/common.php index 9933c3f51f..d50dfcba78 100644 --- a/mod/common.php +++ b/mod/common.php @@ -4,8 +4,8 @@ */ use Friendica\App; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; -use Friendica\Object\Contact; require_once 'include/contact_selectors.php'; require_once 'mod/contacts.php'; diff --git a/mod/contacts.php b/mod/contacts.php index 9feacaf5e3..e9e55570df 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -6,9 +6,9 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; use Friendica\Network\Probe; -use Friendica\Object\Contact; require_once 'include/contact_selectors.php'; require_once 'mod/proxy.php'; diff --git a/mod/crepair.php b/mod/crepair.php index 7e1921f304..32db9be92c 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -5,7 +5,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/contact_selectors.php'; require_once 'mod/contacts.php'; diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index 18d9f25bf5..c999013eff 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -24,8 +24,8 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Network\Probe; -use Friendica\Object\Contact; use Friendica\Protocol\Diaspora; require_once 'include/enotify.php'; diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 61be7966e0..b81f26db9d 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -9,7 +9,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; use Friendica\Protocol\DFRN; require_once 'include/items.php'; diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php index 67395a9fcc..bff1464ae4 100644 --- a/mod/dfrn_request.php +++ b/mod/dfrn_request.php @@ -15,8 +15,8 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Network\Probe; -use Friendica\Object\Contact; require_once 'include/enotify.php'; require_once 'include/group.php'; diff --git a/mod/directory.php b/mod/directory.php index d8ad6aeaba..f29e3eb69b 100644 --- a/mod/directory.php +++ b/mod/directory.php @@ -3,7 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; function directory_init(App $a) { $a->set_pager_itemspage(60); diff --git a/mod/dirfind.php b/mod/dirfind.php index 4ba122b566..52dbf7512e 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -6,9 +6,9 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; use Friendica\Network\Probe; -use Friendica\Object\Contact; use Friendica\Protocol\PortableContact; require_once 'include/contact_widgets.php'; diff --git a/mod/display.php b/mod/display.php index e81e654acb..2d22637ece 100644 --- a/mod/display.php +++ b/mod/display.php @@ -4,7 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; use Friendica\Protocol\DFRN; function display_init(App $a) { diff --git a/mod/follow.php b/mod/follow.php index b5e73ca9a4..f0cffff4a1 100644 --- a/mod/follow.php +++ b/mod/follow.php @@ -3,8 +3,8 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Model\Contact; use Friendica\Network\Probe; -use Friendica\Object\Contact; require_once 'include/follow.php'; require_once 'include/contact_selectors.php'; diff --git a/mod/hovercard.php b/mod/hovercard.php index 5542fe5b98..496c5e0290 100644 --- a/mod/hovercard.php +++ b/mod/hovercard.php @@ -10,8 +10,8 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; -use Friendica\Object\Contact; function hovercard_init(App $a) { // Just for testing purposes diff --git a/mod/item.php b/mod/item.php index ffac1c8e44..c6478d99a0 100644 --- a/mod/item.php +++ b/mod/item.php @@ -22,9 +22,9 @@ use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; use Friendica\Network\Probe; -use Friendica\Object\Contact; use Friendica\Protocol\Diaspora; use Friendica\Protocol\Email; use Friendica\Util\Emailer; diff --git a/mod/match.php b/mod/match.php index 3a0d10c319..563ce5bedc 100644 --- a/mod/match.php +++ b/mod/match.php @@ -6,7 +6,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/text.php'; require_once 'include/contact_widgets.php'; diff --git a/mod/message.php b/mod/message.php index cefc44356f..7bb17f3906 100644 --- a/mod/message.php +++ b/mod/message.php @@ -4,7 +4,7 @@ use Friendica\App; use Friendica\Content\Smilies; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/acl_selectors.php'; require_once 'include/message.php'; diff --git a/mod/network.php b/mod/network.php index 7e61d083f6..3ac13b24e0 100644 --- a/mod/network.php +++ b/mod/network.php @@ -9,7 +9,7 @@ use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/conversation.php'; require_once 'include/group.php'; diff --git a/mod/nogroup.php b/mod/nogroup.php index 5fb9afc2ac..d7df8cb187 100644 --- a/mod/nogroup.php +++ b/mod/nogroup.php @@ -4,7 +4,7 @@ */ use Friendica\App; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/contact_selectors.php'; diff --git a/mod/photos.php b/mod/photos.php index 36a7d925d2..cc3ec71a65 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -8,9 +8,9 @@ use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\Photo; use Friendica\Network\Probe; -use Friendica\Object\Contact; use Friendica\Object\Image; require_once 'include/photos.php'; diff --git a/mod/ping.php b/mod/ping.php index 0f2a9584b8..883129d14f 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -9,7 +9,7 @@ use Friendica\Core\Cache; use Friendica\Core\System; use Friendica\Core\PConfig; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; use Friendica\Util\XML; require_once 'include/datetime.php'; diff --git a/mod/suggest.php b/mod/suggest.php index f05c76ceda..716f796248 100644 --- a/mod/suggest.php +++ b/mod/suggest.php @@ -5,8 +5,8 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; -use Friendica\Object\Contact; require_once 'include/contact_widgets.php'; diff --git a/mod/unfollow.php b/mod/unfollow.php index 3f94fb5760..907982cd8a 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -3,7 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/follow.php'; require_once 'include/contact_selectors.php'; diff --git a/mod/videos.php b/mod/videos.php index 412966f862..bb0e0c237f 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -5,7 +5,7 @@ use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once('include/items.php'); require_once('include/acl_selectors.php'); diff --git a/mod/viewcontacts.php b/mod/viewcontacts.php index 30ae92f8e3..1b4ff69c00 100644 --- a/mod/viewcontacts.php +++ b/mod/viewcontacts.php @@ -3,7 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once('include/contact_selectors.php'); diff --git a/src/Core/NotificationsManager.php b/src/Core/NotificationsManager.php index 42d514e618..9adac10c92 100644 --- a/src/Core/NotificationsManager.php +++ b/src/Core/NotificationsManager.php @@ -9,7 +9,7 @@ namespace Friendica\Core; use Friendica\Core\Pconfig; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'include/html2plain.php'; require_once 'include/datetime.php'; diff --git a/src/Model/Contact.php b/src/Model/Contact.php new file mode 100644 index 0000000000..3708603ba3 --- /dev/null +++ b/src/Model/Contact.php @@ -0,0 +1,947 @@ + intval($uid), 'self'])) { + return true; + } + + $user = dba::select('user', ['uid', 'username', 'nickname'], ['uid' => intval($uid)], ['limit' => 1]); + if (!DBM::is_result($user)) { + return false; + } + + $return = dba::insert('contact', [ + 'uid' => $user['uid'], + 'created' => datetime_convert(), + 'self' => 1, + 'name' => $user['username'], + 'nick' => $user['nickname'], + 'photo' => System::baseUrl() . '/photo/profile/' . $user['uid'] . '.jpg', + 'thumb' => System::baseUrl() . '/photo/avatar/' . $user['uid'] . '.jpg', + 'micro' => System::baseUrl() . '/photo/micro/' . $user['uid'] . '.jpg', + 'blocked' => 0, + 'pending' => 0, + 'url' => System::baseUrl() . '/profile/' . $user['nickname'], + 'nurl' => normalise_link(System::baseUrl() . '/profile/' . $user['nickname']), + 'addr' => $user['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3), + 'request' => System::baseUrl() . '/dfrn_request/' . $user['nickname'], + 'notify' => System::baseUrl() . '/dfrn_notify/' . $user['nickname'], + 'poll' => System::baseUrl() . '/dfrn_poll/' . $user['nickname'], + 'confirm' => System::baseUrl() . '/dfrn_confirm/' . $user['nickname'], + 'poco' => System::baseUrl() . '/poco/' . $user['nickname'], + 'name-date' => datetime_convert(), + 'uri-date' => datetime_convert(), + 'avatar-date' => datetime_convert(), + 'closeness' => 0 + ]); + + return $return; + } + + /** + * @brief Marks a contact for removal + * + * @param int $id contact id + * @return null + */ + public static function remove($id) + { + // We want just to make sure that we don't delete our "self" contact + $r = dba::select('contact', array('uid'), array('id' => $id, 'self' => false), array('limit' => 1)); + + if (!DBM::is_result($r) || !intval($r['uid'])) { + return; + } + + $archive = PConfig::get($r['uid'], 'system', 'archive_removed_contacts'); + if ($archive) { + dba::update('contact', array('archive' => true, 'network' => 'none', 'writable' => false), array('id' => $id)); + return; + } + + dba::delete('contact', array('id' => $id)); + + // Delete the rest in the background + Worker::add(PRIORITY_LOW, 'RemoveContact', $id); + } + + /** + * @brief Sends an unfriend message. Does not remove the contact + * + * @param array $user User unfriending + * @param array $contact Contact unfriended + * @return void + */ + public static function terminateFriendship(array $user, array $contact) + { + if ($contact['network'] === NETWORK_OSTATUS) { + // create an unfollow slap + $item = array(); + $item['verb'] = NAMESPACE_OSTATUS . "/unfollow"; + $item['follow'] = $contact["url"]; + $slap = OStatus::salmon($item, $user); + + if ((x($contact, 'notify')) && (strlen($contact['notify']))) { + Salmon::slapper($user, $contact['notify'], $slap); + } + } elseif ($contact['network'] === NETWORK_DIASPORA) { + Diaspora::sendUnshare($user, $contact); + } elseif ($contact['network'] === NETWORK_DFRN) { + DFRN::deliver($user, $contact, 'placeholder', 1); + } + } + + /** + * @brief Marks a contact for archival after a communication issue delay + * + * Contact has refused to recognise us as a friend. We will start a countdown. + * If they still don't recognise us in 32 days, the relationship is over, + * and we won't waste any more time trying to communicate with them. + * This provides for the possibility that their database is temporarily messed + * up or some other transient event and that there's a possibility we could recover from it. + * + * @param array $contact contact to mark for archival + * @return type + */ + public static function markForArchival(array $contact) + { + // Contact already archived or "self" contact? => nothing to do + if ($contact['archive'] || $contact['self']) { + return; + } + + if ($contact['term-date'] <= NULL_DATE) { + dba::update('contact', array('term-date' => datetime_convert()), array('id' => $contact['id'])); + + if ($contact['url'] != '') { + dba::update('contact', array('term-date' => datetime_convert()), array('`nurl` = ? AND `term-date` <= ? AND NOT `self`', normalise_link($contact['url']), NULL_DATE)); + } + } else { + /* @todo + * We really should send a notification to the owner after 2-3 weeks + * so they won't be surprised when the contact vanishes and can take + * remedial action if this was a serious mistake or glitch + */ + + /// @todo Check for contact vitality via probing + $expiry = $contact['term-date'] . ' + 32 days '; + if (datetime_convert() > datetime_convert('UTC', 'UTC', $expiry)) { + /* Relationship is really truly dead. archive them rather than + * delete, though if the owner tries to unarchive them we'll start + * the whole process over again. + */ + dba::update('contact', array('archive' => 1), array('id' => $contact['id'])); + + if ($contact['url'] != '') { + dba::update('contact', array('archive' => 1), array('nurl' => normalise_link($contact['url']), 'self' => false)); + } + } + } + } + + /** + * @brief Cancels the archival countdown + * + * @see Contact::markForArchival() + * + * @param array $contact contact to be unmarked for archival + * @return null + */ + public static function unmarkForArchival(array $contact) + { + $condition = array('`id` = ? AND (`term-date` > ? OR `archive`)', $contact['id'], NULL_DATE); + $exists = dba::exists('contact', $condition); + + // We don't need to update, we never marked this contact for archival + if (!$exists) { + return; + } + + // It's a miracle. Our dead contact has inexplicably come back to life. + $fields = array('term-date' => NULL_DATE, 'archive' => false); + dba::update('contact', $fields, array('id' => $contact['id'])); + + if ($contact['url'] != '') { + dba::update('contact', $fields, array('nurl' => normalise_link($contact['url']))); + } + } + + /** + * @brief Get contact data for a given profile link + * + * The function looks at several places (contact table and gcontact table) for the contact + * It caches its result for the same script execution to prevent duplicate calls + * + * @param string $url The profile link + * @param int $uid User id + * @param array $default If not data was found take this data as default value + * + * @return array Contact data + */ + public static function getDetailsByURL($url, $uid = -1, array $default = []) + { + static $cache = array(); + + if ($url == '') { + return $default; + } + + if ($uid == -1) { + $uid = local_user(); + } + + if (isset($cache[$url][$uid])) { + return $cache[$url][$uid]; + } + + $ssl_url = str_replace('http://', 'https://', $url); + + // Fetch contact data from the contact table for the given user + $s = dba::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` + FROM `contact` WHERE `nurl` = ? AND `uid` = ?", normalise_link($url), $uid); + $r = dba::inArray($s); + + // Fetch contact data from the contact table for the given user, checking with the alias + if (!DBM::is_result($r)) { + $s = dba::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` + FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ?", normalise_link($url), $url, $ssl_url, $uid); + $r = dba::inArray($s); + } + + // Fetch the data from the contact table with "uid=0" (which is filled automatically) + if (!DBM::is_result($r)) { + $s = dba::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` + FROM `contact` WHERE `nurl` = ? AND `uid` = 0", normalise_link($url)); + $r = dba::inArray($s); + } + + // Fetch the data from the contact table with "uid=0" (which is filled automatically) - checked with the alias + if (!DBM::is_result($r)) { + $s = dba::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` + FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = 0", normalise_link($url), $url, $ssl_url); + $r = dba::inArray($s); + } + + // Fetch the data from the gcontact table + if (!DBM::is_result($r)) { + $s = dba::p("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, + `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` + FROM `gcontact` WHERE `nurl` = ?", normalise_link($url)); + $r = dba::inArray($s); + } + + if (DBM::is_result($r)) { + // If there is more than one entry we filter out the connector networks + if (count($r) > 1) { + foreach ($r as $id => $result) { + if ($result["network"] == NETWORK_STATUSNET) { + unset($r[$id]); + } + } + } + + $profile = array_shift($r); + + // "bd" always contains the upcoming birthday of a contact. + // "birthday" might contain the birthday including the year of birth. + if ($profile["birthday"] > '0001-01-01') { + $bd_timestamp = strtotime($profile["birthday"]); + $month = date("m", $bd_timestamp); + $day = date("d", $bd_timestamp); + + $current_timestamp = time(); + $current_year = date("Y", $current_timestamp); + $current_month = date("m", $current_timestamp); + $current_day = date("d", $current_timestamp); + + $profile["bd"] = $current_year . "-" . $month . "-" . $day; + $current = $current_year . "-" . $current_month . "-" . $current_day; + + if ($profile["bd"] < $current) { + $profile["bd"] = ( ++$current_year) . "-" . $month . "-" . $day; + } + } else { + $profile["bd"] = '0001-01-01'; + } + } else { + $profile = $default; + } + + if (($profile["photo"] == "") && isset($default["photo"])) { + $profile["photo"] = $default["photo"]; + } + + if (($profile["name"] == "") && isset($default["name"])) { + $profile["name"] = $default["name"]; + } + + if (($profile["network"] == "") && isset($default["network"])) { + $profile["network"] = $default["network"]; + } + + if (($profile["thumb"] == "") && isset($profile["photo"])) { + $profile["thumb"] = $profile["photo"]; + } + + if (($profile["micro"] == "") && isset($profile["thumb"])) { + $profile["micro"] = $profile["thumb"]; + } + + if ((($profile["addr"] == "") || ($profile["name"] == "")) && ($profile["gid"] != 0) + && in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)) + ) { + Worker::add(PRIORITY_LOW, "UpdateGContact", $profile["gid"]); + } + + // Show contact details of Diaspora contacts only if connected + if (($profile["cid"] == 0) && ($profile["network"] == NETWORK_DIASPORA)) { + $profile["location"] = ""; + $profile["about"] = ""; + $profile["gender"] = ""; + $profile["birthday"] = '0001-01-01'; + } + + $cache[$url][$uid] = $profile; + + return $profile; + } + + /** + * @brief Get contact data for a given address + * + * The function looks at several places (contact table and gcontact table) for the contact + * + * @param string $addr The profile link + * @param int $uid User id + * + * @return array Contact data + */ + public static function getDetailsByAddr($addr, $uid = -1) + { + static $cache = array(); + + if ($addr == '') { + return array(); + } + + if ($uid == -1) { + $uid = local_user(); + } + + // Fetch contact data from the contact table for the given user + $r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` + FROM `contact` WHERE `addr` = '%s' AND `uid` = %d", dbesc($addr), intval($uid)); + + // Fetch the data from the contact table with "uid=0" (which is filled automatically) + if (!DBM::is_result($r)) + $r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, + `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` + FROM `contact` WHERE `addr` = '%s' AND `uid` = 0", dbesc($addr)); + + // Fetch the data from the gcontact table + if (!DBM::is_result($r)) + $r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, + `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` + FROM `gcontact` WHERE `addr` = '%s'", dbesc($addr)); + + if (!DBM::is_result($r)) { + $data = Probe::uri($addr); + + $profile = self::getDetailsByURL($data['url'], $uid); + } else { + $profile = $r[0]; + } + + return $profile; + } + + /** + * @brief Returns the data array for the photo menu of a given contact + * + * @param array $contact contact + * @param int $uid optional, default 0 + * @return array + */ + public static function photoMenu(array $contact, $uid = 0) + { + // @todo Unused, to be removed + $a = get_app(); + + $contact_url = ''; + $pm_url = ''; + $status_link = ''; + $photos_link = ''; + $posts_link = ''; + $contact_drop_link = ''; + $poke_link = ''; + + if ($uid == 0) { + $uid = local_user(); + } + + if ($contact['uid'] != $uid) { + if ($uid == 0) { + $profile_link = zrl($contact['url']); + $menu = array('profile' => array(t('View Profile'), $profile_link, true)); + + return $menu; + } + + $r = dba::select('contact', array(), array('nurl' => $contact['nurl'], 'network' => $contact['network'], 'uid' => $uid), array('limit' => 1)); + if ($r) { + return self::photoMenu($r, $uid); + } else { + $profile_link = zrl($contact['url']); + $connlnk = 'follow/?url=' . $contact['url']; + $menu = array( + 'profile' => array(t('View Profile'), $profile_link, true), + 'follow' => array(t('Connect/Follow'), $connlnk, true) + ); + + return $menu; + } + } + + $sparkle = false; + if ($contact['network'] === NETWORK_DFRN) { + $sparkle = true; + $profile_link = System::baseUrl() . '/redir/' . $contact['id']; + } else { + $profile_link = $contact['url']; + } + + if ($profile_link === 'mailbox') { + $profile_link = ''; + } + + if ($sparkle) { + $status_link = $profile_link . '?url=status'; + $photos_link = $profile_link . '?url=photos'; + $profile_link = $profile_link . '?url=profile'; + } + + if (in_array($contact['network'], array(NETWORK_DFRN, NETWORK_DIASPORA))) { + $pm_url = System::baseUrl() . '/message/new/' . $contact['id']; + } + + if ($contact['network'] == NETWORK_DFRN) { + $poke_link = System::baseUrl() . '/poke/?f=&c=' . $contact['id']; + } + + $contact_url = System::baseUrl() . '/contacts/' . $contact['id']; + + $posts_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/posts'; + $contact_drop_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/drop?confirm=1'; + + /** + * Menu array: + * "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ] + */ + $menu = array( + 'status' => array(t("View Status"), $status_link, true), + 'profile' => array(t("View Profile"), $profile_link, true), + 'photos' => array(t("View Photos"), $photos_link, true), + 'network' => array(t("Network Posts"), $posts_link, false), + 'edit' => array(t("View Contact"), $contact_url, false), + 'drop' => array(t("Drop Contact"), $contact_drop_link, false), + 'pm' => array(t("Send PM"), $pm_url, false), + 'poke' => array(t("Poke"), $poke_link, false), + ); + + + $args = array('contact' => $contact, 'menu' => &$menu); + + call_hooks('contact_photo_menu', $args); + + $menucondensed = array(); + + foreach ($menu as $menuname => $menuitem) { + if ($menuitem[1] != '') { + $menucondensed[$menuname] = $menuitem; + } + } + + return $menucondensed; + } + + /** + * @brief Returns ungrouped contact count or list for user + * + * Returns either the total number of ungrouped contacts for the given user + * id or a paginated list of ungrouped contacts. + * + * @param int $uid uid + * @param int $start optional, default 0 + * @param int $count optional, default 0 + * + * @return array + */ + public static function getUngroupedList($uid, $start = 0, $count = 0) + { + if (!$count) { + $r = q( + "SELECT COUNT(*) AS `total` + FROM `contact` + WHERE `uid` = %d + AND NOT `self` + AND NOT `blocked` + AND NOT `pending` + AND `id` NOT IN ( + SELECT DISTINCT(`contact-id`) + FROM `group_member` + WHERE `uid` = %d + )", intval($uid), intval($uid) + ); + + return $r; + } + + $r = q( + "SELECT * + FROM `contact` + WHERE `uid` = %d + AND NOT `self` + AND NOT `blocked` + AND NOT `pending` + AND `id` NOT IN ( + SELECT DISTINCT(`contact-id`) + FROM `group_member` WHERE `uid` = %d + ) + LIMIT %d, %d", intval($uid), intval($uid), intval($start), intval($count) + ); + return $r; + } + + /** + * @brief Fetch the contact id for a given url and user + * + * First lookup in the contact table to find a record matching either `url`, `nurl`, + * `addr` or `alias`. + * + * If there's no record and we aren't looking for a public contact, we quit. + * If there's one, we check that it isn't time to update the picture else we + * directly return the found contact id. + * + * Second, we probe the provided $url wether it's http://server.tld/profile or + * nick@server.tld. We quit if we can't get any info back. + * + * Third, we create the contact record if it doesn't exist + * + * Fourth, we update the existing record with the new data (avatar, alias, nick) + * if there's any updates + * + * @param string $url Contact URL + * @param integer $uid The user id for the contact (0 = public contact) + * @param boolean $no_update Don't update the contact + * + * @return integer Contact ID + */ + public static function getIdForURL($url, $uid = 0, $no_update = false) + { + logger("Get contact data for url " . $url . " and user " . $uid . " - " . System::callstack(), LOGGER_DEBUG); + + $contact_id = 0; + + if ($url == '') { + return 0; + } + + /// @todo Verify if we can't use Contact::getDetailsByUrl instead of the following + // We first try the nurl (http://server.tld/nick), most common case + $contact = dba::select('contact', array('id', 'avatar-date'), array('nurl' => normalise_link($url), 'uid' => $uid), array('limit' => 1)); + + // Then the addr (nick@server.tld) + if (!DBM::is_result($contact)) { + $contact = dba::select('contact', array('id', 'avatar-date'), array('addr' => $url, 'uid' => $uid), array('limit' => 1)); + } + + // Then the alias (which could be anything) + if (!DBM::is_result($contact)) { + // The link could be provided as http although we stored it as https + $ssl_url = str_replace('http://', 'https://', $url); + $r = dba::select('contact', array('id', 'avatar-date'), array('`alias` IN (?, ?, ?) AND `uid` = ?', $url, normalise_link($url), $ssl_url, $uid), array('limit' => 1)); + $contact = dba::fetch($r); + dba::close($r); + } + + if (DBM::is_result($contact)) { + $contact_id = $contact["id"]; + + // Update the contact every 7 days + $update_contact = ($contact['avatar-date'] < datetime_convert('', '', 'now -7 days')); + + // We force the update if the avatar is empty + if ($contact['avatar'] == '') { + $update_contact = true; + } + + if (!$update_contact || $no_update) { + return $contact_id; + } + } elseif ($uid != 0) { + // Non-existing user-specific contact, exiting + return 0; + } + + $data = Probe::uri($url, "", $uid); + + // Last try in gcontact for unsupported networks + if (!in_array($data["network"], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA, NETWORK_PUMPIO, NETWORK_MAIL))) { + if ($uid != 0) { + return 0; + } + + // Get data from the gcontact table + $gcontacts = dba::select('gcontact', array('name', 'nick', 'url', 'photo', 'addr', 'alias', 'network'), array('nurl' => normalise_link($url)), array('limit' => 1)); + if (!DBM::is_result($gcontacts)) { + return 0; + } + + $data = array_merge($data, $gcontacts); + } + + if (!$contact_id && ($data["alias"] != '') && ($data["alias"] != $url)) { + $contact_id = self::getIdForURL($data["alias"], $uid, true); + } + + $url = $data["url"]; + if (!$contact_id) { + dba::insert( + 'contact', array('uid' => $uid, 'created' => datetime_convert(), 'url' => $data["url"], + 'nurl' => normalise_link($data["url"]), 'addr' => $data["addr"], + 'alias' => $data["alias"], 'notify' => $data["notify"], 'poll' => $data["poll"], + 'name' => $data["name"], 'nick' => $data["nick"], 'photo' => $data["photo"], + 'keywords' => $data["keywords"], 'location' => $data["location"], 'about' => $data["about"], + 'network' => $data["network"], 'pubkey' => $data["pubkey"], + 'rel' => CONTACT_IS_SHARING, 'priority' => $data["priority"], + 'batch' => $data["batch"], 'request' => $data["request"], + 'confirm' => $data["confirm"], 'poco' => $data["poco"], + 'name-date' => datetime_convert(), 'uri-date' => datetime_convert(), + 'avatar-date' => datetime_convert(), 'writable' => 1, 'blocked' => 0, + 'readonly' => 0, 'pending' => 0) + ); + + $s = dba::select('contact', array('id'), array('nurl' => normalise_link($data["url"]), 'uid' => $uid), array('order' => array('id'), 'limit' => 2)); + $contacts = dba::inArray($s); + if (!DBM::is_result($contacts)) { + return 0; + } + + $contact_id = $contacts[0]["id"]; + + // Update the newly created contact from data in the gcontact table + $gcontact = dba::select('gcontact', array('location', 'about', 'keywords', 'gender'), array('nurl' => normalise_link($data["url"])), array('limit' => 1)); + if (DBM::is_result($gcontact)) { + // Only use the information when the probing hadn't fetched these values + if ($data['keywords'] != '') { + unset($gcontact['keywords']); + } + if ($data['location'] != '') { + unset($gcontact['location']); + } + if ($data['about'] != '') { + unset($gcontact['about']); + } + dba::update('contact', $gcontact, array('id' => $contact_id)); + } + + if (count($contacts) > 1 && $uid == 0 && $contact_id != 0 && $data["url"] != "") { + dba::delete('contact', array("`nurl` = ? AND `uid` = 0 AND `id` != ? AND NOT `self`", + normalise_link($data["url"]), $contact_id)); + } + } + + self::updateAvatar($data["photo"], $uid, $contact_id); + + $fields = array('url', 'nurl', 'addr', 'alias', 'name', 'nick', 'keywords', 'location', 'about', 'avatar-date', 'pubkey'); + $contact = dba::select('contact', $fields, array('id' => $contact_id), array('limit' => 1)); + + // This condition should always be true + if (!DBM::is_result($contact)) { + return $contact_id; + } + + $updated = array('addr' => $data['addr'], + 'alias' => $data['alias'], + 'url' => $data['url'], + 'nurl' => normalise_link($data['url']), + 'name' => $data['name'], + 'nick' => $data['nick']); + + // Only fill the pubkey if it was empty before. We have to prevent identity theft. + if (!empty($contact['pubkey'])) { + unset($contact['pubkey']); + } else { + $updated['pubkey'] = $data['pubkey']; + } + + if ($data['keywords'] != '') { + $updated['keywords'] = $data['keywords']; + } + if ($data['location'] != '') { + $updated['location'] = $data['location']; + } + if ($data['about'] != '') { + $updated['about'] = $data['about']; + } + + if (($data["addr"] != $contact["addr"]) || ($data["alias"] != $contact["alias"])) { + $updated['uri-date'] = datetime_convert(); + } + if (($data["name"] != $contact["name"]) || ($data["nick"] != $contact["nick"])) { + $updated['name-date'] = datetime_convert(); + } + + $updated['avatar-date'] = datetime_convert(); + + dba::update('contact', $updated, array('id' => $contact_id), $contact); + + return $contact_id; + } + + /** + * @brief Checks if the contact is blocked + * + * @param int $cid contact id + * + * @return boolean Is the contact blocked? + */ + public static function isBlocked($cid) + { + if ($cid == 0) { + return false; + } + + $blocked = dba::select('contact', array('blocked'), array('id' => $cid), array('limit' => 1)); + if (!DBM::is_result($blocked)) { + return false; + } + return (bool) $blocked['blocked']; + } + + /** + * @brief Checks if the contact is hidden + * + * @param int $cid contact id + * + * @return boolean Is the contact hidden? + */ + public static function isHidden($cid) + { + if ($cid == 0) { + return false; + } + + $hidden = dba::select('contact', array('hidden'), array('id' => $cid), array('limit' => 1)); + if (!DBM::is_result($hidden)) { + return false; + } + return (bool) $hidden['hidden']; + } + + /** + * @brief Returns posts from a given contact url + * + * @param string $contact_url Contact URL + * + * @return string posts in HTML + */ + public static function getPostsFromUrl($contact_url) + { + $a = self::getApp(); + + require_once 'include/conversation.php'; + + // There are no posts with "uid = 0" with connector networks + // This speeds up the query a lot + $r = q("SELECT `network`, `id` AS `author-id`, `contact-type` FROM `contact` + WHERE `contact`.`nurl` = '%s' AND `contact`.`uid` = 0", dbesc(normalise_link($contact_url))); + + if (!DBM::is_result($r)) { + return ''; + } + + if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { + $sql = "(`item`.`uid` = 0 OR (`item`.`uid` = %d AND NOT `item`.`global`))"; + } else { + $sql = "`item`.`uid` = %d"; + } + + $author_id = intval($r[0]["author-id"]); + + $contact = ($r[0]["contact-type"] == ACCOUNT_TYPE_COMMUNITY ? 'owner-id' : 'author-id'); + + $r = q(item_query() . " AND `item`.`" . $contact . "` = %d AND " . $sql . + " ORDER BY `item`.`created` DESC LIMIT %d, %d", intval($author_id), intval(local_user()), intval($a->pager['start']), intval($a->pager['itemspage']) + ); + + + $o = conversation($a, $r, 'community', false); + + $o .= alt_pager($a, count($r)); + + return $o; + } + + /** + * @brief Returns the account type name + * + * The function can be called with either the user or the contact array + * + * @param array $contact contact or user array + * @return string + */ + public static function getAccountType(array $contact) + { + // There are several fields that indicate that the contact or user is a forum + // "page-flags" is a field in the user table, + // "forum" and "prv" are used in the contact table. They stand for PAGE_COMMUNITY and PAGE_PRVGROUP. + // "community" is used in the gcontact table and is true if the contact is PAGE_COMMUNITY or PAGE_PRVGROUP. + if ((isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_COMMUNITY)) + || (isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_PRVGROUP)) + || (isset($contact['forum']) && intval($contact['forum'])) + || (isset($contact['prv']) && intval($contact['prv'])) + || (isset($contact['community']) && intval($contact['community'])) + ) { + $type = ACCOUNT_TYPE_COMMUNITY; + } else { + $type = ACCOUNT_TYPE_PERSON; + } + + // The "contact-type" (contact table) and "account-type" (user table) are more general then the chaos from above. + if (isset($contact["contact-type"])) { + $type = $contact["contact-type"]; + } + if (isset($contact["account-type"])) { + $type = $contact["account-type"]; + } + + switch ($type) { + case ACCOUNT_TYPE_ORGANISATION: + $account_type = t("Organisation"); + break; + case ACCOUNT_TYPE_NEWS: + $account_type = t('News'); + break; + case ACCOUNT_TYPE_COMMUNITY: + $account_type = t("Forum"); + break; + default: + $account_type = ""; + break; + } + + return $account_type; + } + + /** + * @brief Blocks a contact + * + * @param int $uid + * @return bool + */ + public static function block($uid) + { + $return = dba::update('contact', ['blocked' => true], ['id' => $uid]); + + return $return; + } + + /** + * @brief Unblocks a contact + * + * @param int $uid + * @return bool + */ + public static function unblock($uid) + { + $return = dba::update('contact', ['blocked' => false], ['id' => $uid]); + + return $return; + } + + /** + * @brief Updates the avatar links in a contact only if needed + * + * @param string $avatar Link to avatar picture + * @param int $uid User id of contact owner + * @param int $cid Contact id + * @param bool $force force picture update + * + * @return array Returns array of the different avatar sizes + */ + public static function updateAvatar($avatar, $uid, $cid, $force = false) + { + // Limit = 1 returns the row so no need for dba:inArray() + $r = dba::select('contact', array('avatar', 'photo', 'thumb', 'micro', 'nurl'), array('id' => $cid), array('limit' => 1)); + if (!DBM::is_result($r)) { + return false; + } else { + $data = array($r["photo"], $r["thumb"], $r["micro"]); + } + + if (($r["avatar"] != $avatar) || $force) { + $photos = Image::importProfilePhoto($avatar, $uid, $cid, true); + + if ($photos) { + dba::update( + 'contact', + array('avatar' => $avatar, 'photo' => $photos[0], 'thumb' => $photos[1], 'micro' => $photos[2], 'avatar-date' => datetime_convert()), + array('id' => $cid) + ); + + // Update the public contact (contact id = 0) + if ($uid != 0) { + $pcontact = dba::select('contact', array('id'), array('nurl' => $r[0]['nurl']), array('limit' => 1)); + if (DBM::is_result($pcontact)) { + self::updateAvatar($avatar, 0, $pcontact['id'], $force); + } + } + + return $photos; + } + } + + return $data; + } +} diff --git a/src/Model/GlobalContact.php b/src/Model/GlobalContact.php index 6ec1101775..d0ebe85020 100644 --- a/src/Model/GlobalContact.php +++ b/src/Model/GlobalContact.php @@ -10,7 +10,7 @@ use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; use Friendica\Network\Probe; -use Friendica\Object\Contact; +use Friendica\Model\Contact; use Friendica\Object\Profile; use Friendica\Protocol\PortableContact; use dba; diff --git a/src/Model/User.php b/src/Model/User.php index 1f70bfb158..54d2d3bc60 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -11,8 +11,8 @@ use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\Photo; -use Friendica\Object\Contact; use Friendica\Object\Image; use dba; diff --git a/src/Object/Contact.php b/src/Object/Contact.php deleted file mode 100644 index f72ec025a4..0000000000 --- a/src/Object/Contact.php +++ /dev/null @@ -1,948 +0,0 @@ - intval($uid), 'self'])) { - return true; - } - - $user = dba::select('user', ['uid', 'username', 'nickname'], ['uid' => intval($uid)], ['limit' => 1]); - if (!DBM::is_result($user)) { - return false; - } - - $return = dba::insert('contact', [ - 'uid' => $user['uid'], - 'created' => datetime_convert(), - 'self' => 1, - 'name' => $user['username'], - 'nick' => $user['nickname'], - 'photo' => System::baseUrl() . '/photo/profile/' . $user['uid'] . '.jpg', - 'thumb' => System::baseUrl() . '/photo/avatar/' . $user['uid'] . '.jpg', - 'micro' => System::baseUrl() . '/photo/micro/' . $user['uid'] . '.jpg', - 'blocked' => 0, - 'pending' => 0, - 'url' => System::baseUrl() . '/profile/' . $user['nickname'], - 'nurl' => normalise_link(System::baseUrl() . '/profile/' . $user['nickname']), - 'addr' => $user['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3), - 'request' => System::baseUrl() . '/dfrn_request/' . $user['nickname'], - 'notify' => System::baseUrl() . '/dfrn_notify/' . $user['nickname'], - 'poll' => System::baseUrl() . '/dfrn_poll/' . $user['nickname'], - 'confirm' => System::baseUrl() . '/dfrn_confirm/' . $user['nickname'], - 'poco' => System::baseUrl() . '/poco/' . $user['nickname'], - 'name-date' => datetime_convert(), - 'uri-date' => datetime_convert(), - 'avatar-date' => datetime_convert(), - 'closeness' => 0 - ]); - - return $return; - } - - /** - * @brief Marks a contact for removal - * - * @param int $id contact id - * @return null - */ - public static function remove($id) - { - // We want just to make sure that we don't delete our "self" contact - $r = dba::select('contact', array('uid'), array('id' => $id, 'self' => false), array('limit' => 1)); - - if (!DBM::is_result($r) || !intval($r['uid'])) { - return; - } - - $archive = PConfig::get($r['uid'], 'system', 'archive_removed_contacts'); - if ($archive) { - dba::update('contact', array('archive' => true, 'network' => 'none', 'writable' => false), array('id' => $id)); - return; - } - - dba::delete('contact', array('id' => $id)); - - // Delete the rest in the background - Worker::add(PRIORITY_LOW, 'RemoveContact', $id); - } - - /** - * @brief Sends an unfriend message. Does not remove the contact - * - * @param array $user User unfriending - * @param array $contact Contact unfriended - * @return void - */ - public static function terminateFriendship(array $user, array $contact) - { - if ($contact['network'] === NETWORK_OSTATUS) { - // create an unfollow slap - $item = array(); - $item['verb'] = NAMESPACE_OSTATUS . "/unfollow"; - $item['follow'] = $contact["url"]; - $slap = OStatus::salmon($item, $user); - - if ((x($contact, 'notify')) && (strlen($contact['notify']))) { - Salmon::slapper($user, $contact['notify'], $slap); - } - } elseif ($contact['network'] === NETWORK_DIASPORA) { - Diaspora::sendUnshare($user, $contact); - } elseif ($contact['network'] === NETWORK_DFRN) { - DFRN::deliver($user, $contact, 'placeholder', 1); - } - } - - /** - * @brief Marks a contact for archival after a communication issue delay - * - * Contact has refused to recognise us as a friend. We will start a countdown. - * If they still don't recognise us in 32 days, the relationship is over, - * and we won't waste any more time trying to communicate with them. - * This provides for the possibility that their database is temporarily messed - * up or some other transient event and that there's a possibility we could recover from it. - * - * @param array $contact contact to mark for archival - * @return type - */ - public static function markForArchival(array $contact) - { - // Contact already archived or "self" contact? => nothing to do - if ($contact['archive'] || $contact['self']) { - return; - } - - if ($contact['term-date'] <= NULL_DATE) { - dba::update('contact', array('term-date' => datetime_convert()), array('id' => $contact['id'])); - - if ($contact['url'] != '') { - dba::update('contact', array('term-date' => datetime_convert()), array('`nurl` = ? AND `term-date` <= ? AND NOT `self`', normalise_link($contact['url']), NULL_DATE)); - } - } else { - /* @todo - * We really should send a notification to the owner after 2-3 weeks - * so they won't be surprised when the contact vanishes and can take - * remedial action if this was a serious mistake or glitch - */ - - /// @todo Check for contact vitality via probing - $expiry = $contact['term-date'] . ' + 32 days '; - if (datetime_convert() > datetime_convert('UTC', 'UTC', $expiry)) { - /* Relationship is really truly dead. archive them rather than - * delete, though if the owner tries to unarchive them we'll start - * the whole process over again. - */ - dba::update('contact', array('archive' => 1), array('id' => $contact['id'])); - - if ($contact['url'] != '') { - dba::update('contact', array('archive' => 1), array('nurl' => normalise_link($contact['url']), 'self' => false)); - } - } - } - } - - /** - * @brief Cancels the archival countdown - * - * @see Contact::markForArchival() - * - * @param array $contact contact to be unmarked for archival - * @return null - */ - public static function unmarkForArchival(array $contact) - { - $condition = array('`id` = ? AND (`term-date` > ? OR `archive`)', $contact['id'], NULL_DATE); - $exists = dba::exists('contact', $condition); - - // We don't need to update, we never marked this contact for archival - if (!$exists) { - return; - } - - // It's a miracle. Our dead contact has inexplicably come back to life. - $fields = array('term-date' => NULL_DATE, 'archive' => false); - dba::update('contact', $fields, array('id' => $contact['id'])); - - if ($contact['url'] != '') { - dba::update('contact', $fields, array('nurl' => normalise_link($contact['url']))); - } - } - - /** - * @brief Get contact data for a given profile link - * - * The function looks at several places (contact table and gcontact table) for the contact - * It caches its result for the same script execution to prevent duplicate calls - * - * @param string $url The profile link - * @param int $uid User id - * @param array $default If not data was found take this data as default value - * - * @return array Contact data - */ - public static function getDetailsByURL($url, $uid = -1, array $default = []) - { - static $cache = array(); - - if ($url == '') { - return $default; - } - - if ($uid == -1) { - $uid = local_user(); - } - - if (isset($cache[$url][$uid])) { - return $cache[$url][$uid]; - } - - $ssl_url = str_replace('http://', 'https://', $url); - - // Fetch contact data from the contact table for the given user - $s = dba::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` - FROM `contact` WHERE `nurl` = ? AND `uid` = ?", normalise_link($url), $uid); - $r = dba::inArray($s); - - // Fetch contact data from the contact table for the given user, checking with the alias - if (!DBM::is_result($r)) { - $s = dba::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` - FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ?", normalise_link($url), $url, $ssl_url, $uid); - $r = dba::inArray($s); - } - - // Fetch the data from the contact table with "uid=0" (which is filled automatically) - if (!DBM::is_result($r)) { - $s = dba::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` - FROM `contact` WHERE `nurl` = ? AND `uid` = 0", normalise_link($url)); - $r = dba::inArray($s); - } - - // Fetch the data from the contact table with "uid=0" (which is filled automatically) - checked with the alias - if (!DBM::is_result($r)) { - $s = dba::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` - FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = 0", normalise_link($url), $url, $ssl_url); - $r = dba::inArray($s); - } - - // Fetch the data from the gcontact table - if (!DBM::is_result($r)) { - $s = dba::p("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, - `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` - FROM `gcontact` WHERE `nurl` = ?", normalise_link($url)); - $r = dba::inArray($s); - } - - if (DBM::is_result($r)) { - // If there is more than one entry we filter out the connector networks - if (count($r) > 1) { - foreach ($r as $id => $result) { - if ($result["network"] == NETWORK_STATUSNET) { - unset($r[$id]); - } - } - } - - $profile = array_shift($r); - - // "bd" always contains the upcoming birthday of a contact. - // "birthday" might contain the birthday including the year of birth. - if ($profile["birthday"] > '0001-01-01') { - $bd_timestamp = strtotime($profile["birthday"]); - $month = date("m", $bd_timestamp); - $day = date("d", $bd_timestamp); - - $current_timestamp = time(); - $current_year = date("Y", $current_timestamp); - $current_month = date("m", $current_timestamp); - $current_day = date("d", $current_timestamp); - - $profile["bd"] = $current_year . "-" . $month . "-" . $day; - $current = $current_year . "-" . $current_month . "-" . $current_day; - - if ($profile["bd"] < $current) { - $profile["bd"] = ( ++$current_year) . "-" . $month . "-" . $day; - } - } else { - $profile["bd"] = '0001-01-01'; - } - } else { - $profile = $default; - } - - if (($profile["photo"] == "") && isset($default["photo"])) { - $profile["photo"] = $default["photo"]; - } - - if (($profile["name"] == "") && isset($default["name"])) { - $profile["name"] = $default["name"]; - } - - if (($profile["network"] == "") && isset($default["network"])) { - $profile["network"] = $default["network"]; - } - - if (($profile["thumb"] == "") && isset($profile["photo"])) { - $profile["thumb"] = $profile["photo"]; - } - - if (($profile["micro"] == "") && isset($profile["thumb"])) { - $profile["micro"] = $profile["thumb"]; - } - - if ((($profile["addr"] == "") || ($profile["name"] == "")) && ($profile["gid"] != 0) - && in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)) - ) { - Worker::add(PRIORITY_LOW, "UpdateGContact", $profile["gid"]); - } - - // Show contact details of Diaspora contacts only if connected - if (($profile["cid"] == 0) && ($profile["network"] == NETWORK_DIASPORA)) { - $profile["location"] = ""; - $profile["about"] = ""; - $profile["gender"] = ""; - $profile["birthday"] = '0001-01-01'; - } - - $cache[$url][$uid] = $profile; - - return $profile; - } - - /** - * @brief Get contact data for a given address - * - * The function looks at several places (contact table and gcontact table) for the contact - * - * @param string $addr The profile link - * @param int $uid User id - * - * @return array Contact data - */ - public static function getDetailsByAddr($addr, $uid = -1) - { - static $cache = array(); - - if ($addr == '') { - return array(); - } - - if ($uid == -1) { - $uid = local_user(); - } - - // Fetch contact data from the contact table for the given user - $r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` - FROM `contact` WHERE `addr` = '%s' AND `uid` = %d", dbesc($addr), intval($uid)); - - // Fetch the data from the contact table with "uid=0" (which is filled automatically) - if (!DBM::is_result($r)) - $r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` - FROM `contact` WHERE `addr` = '%s' AND `uid` = 0", dbesc($addr)); - - // Fetch the data from the gcontact table - if (!DBM::is_result($r)) - $r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, - `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` - FROM `gcontact` WHERE `addr` = '%s'", dbesc($addr)); - - if (!DBM::is_result($r)) { - $data = Probe::uri($addr); - - $profile = self::getDetailsByURL($data['url'], $uid); - } else { - $profile = $r[0]; - } - - return $profile; - } - - /** - * @brief Returns the data array for the photo menu of a given contact - * - * @param array $contact contact - * @param int $uid optional, default 0 - * @return array - */ - public static function photoMenu(array $contact, $uid = 0) - { - // @todo Unused, to be removed - $a = get_app(); - - $contact_url = ''; - $pm_url = ''; - $status_link = ''; - $photos_link = ''; - $posts_link = ''; - $contact_drop_link = ''; - $poke_link = ''; - - if ($uid == 0) { - $uid = local_user(); - } - - if ($contact['uid'] != $uid) { - if ($uid == 0) { - $profile_link = zrl($contact['url']); - $menu = array('profile' => array(t('View Profile'), $profile_link, true)); - - return $menu; - } - - $r = dba::select('contact', array(), array('nurl' => $contact['nurl'], 'network' => $contact['network'], 'uid' => $uid), array('limit' => 1)); - if ($r) { - return self::photoMenu($r, $uid); - } else { - $profile_link = zrl($contact['url']); - $connlnk = 'follow/?url=' . $contact['url']; - $menu = array( - 'profile' => array(t('View Profile'), $profile_link, true), - 'follow' => array(t('Connect/Follow'), $connlnk, true) - ); - - return $menu; - } - } - - $sparkle = false; - if ($contact['network'] === NETWORK_DFRN) { - $sparkle = true; - $profile_link = System::baseUrl() . '/redir/' . $contact['id']; - } else { - $profile_link = $contact['url']; - } - - if ($profile_link === 'mailbox') { - $profile_link = ''; - } - - if ($sparkle) { - $status_link = $profile_link . '?url=status'; - $photos_link = $profile_link . '?url=photos'; - $profile_link = $profile_link . '?url=profile'; - } - - if (in_array($contact['network'], array(NETWORK_DFRN, NETWORK_DIASPORA))) { - $pm_url = System::baseUrl() . '/message/new/' . $contact['id']; - } - - if ($contact['network'] == NETWORK_DFRN) { - $poke_link = System::baseUrl() . '/poke/?f=&c=' . $contact['id']; - } - - $contact_url = System::baseUrl() . '/contacts/' . $contact['id']; - - $posts_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/posts'; - $contact_drop_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/drop?confirm=1'; - - /** - * Menu array: - * "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ] - */ - $menu = array( - 'status' => array(t("View Status"), $status_link, true), - 'profile' => array(t("View Profile"), $profile_link, true), - 'photos' => array(t("View Photos"), $photos_link, true), - 'network' => array(t("Network Posts"), $posts_link, false), - 'edit' => array(t("View Contact"), $contact_url, false), - 'drop' => array(t("Drop Contact"), $contact_drop_link, false), - 'pm' => array(t("Send PM"), $pm_url, false), - 'poke' => array(t("Poke"), $poke_link, false), - ); - - - $args = array('contact' => $contact, 'menu' => &$menu); - - call_hooks('contact_photo_menu', $args); - - $menucondensed = array(); - - foreach ($menu as $menuname => $menuitem) { - if ($menuitem[1] != '') { - $menucondensed[$menuname] = $menuitem; - } - } - - return $menucondensed; - } - - /** - * @brief Returns ungrouped contact count or list for user - * - * Returns either the total number of ungrouped contacts for the given user - * id or a paginated list of ungrouped contacts. - * - * @param int $uid uid - * @param int $start optional, default 0 - * @param int $count optional, default 0 - * - * @return array - */ - public static function getUngroupedList($uid, $start = 0, $count = 0) - { - if (!$count) { - $r = q( - "SELECT COUNT(*) AS `total` - FROM `contact` - WHERE `uid` = %d - AND NOT `self` - AND NOT `blocked` - AND NOT `pending` - AND `id` NOT IN ( - SELECT DISTINCT(`contact-id`) - FROM `group_member` - WHERE `uid` = %d - )", intval($uid), intval($uid) - ); - - return $r; - } - - $r = q( - "SELECT * - FROM `contact` - WHERE `uid` = %d - AND NOT `self` - AND NOT `blocked` - AND NOT `pending` - AND `id` NOT IN ( - SELECT DISTINCT(`contact-id`) - FROM `group_member` WHERE `uid` = %d - ) - LIMIT %d, %d", intval($uid), intval($uid), intval($start), intval($count) - ); - return $r; - } - - /** - * @brief Fetch the contact id for a given url and user - * - * First lookup in the contact table to find a record matching either `url`, `nurl`, - * `addr` or `alias`. - * - * If there's no record and we aren't looking for a public contact, we quit. - * If there's one, we check that it isn't time to update the picture else we - * directly return the found contact id. - * - * Second, we probe the provided $url wether it's http://server.tld/profile or - * nick@server.tld. We quit if we can't get any info back. - * - * Third, we create the contact record if it doesn't exist - * - * Fourth, we update the existing record with the new data (avatar, alias, nick) - * if there's any updates - * - * @param string $url Contact URL - * @param integer $uid The user id for the contact (0 = public contact) - * @param boolean $no_update Don't update the contact - * - * @return integer Contact ID - */ - public static function getIdForURL($url, $uid = 0, $no_update = false) - { - logger("Get contact data for url " . $url . " and user " . $uid . " - " . System::callstack(), LOGGER_DEBUG); - - $contact_id = 0; - - if ($url == '') { - return 0; - } - - /// @todo Verify if we can't use Contact::getDetailsByUrl instead of the following - // We first try the nurl (http://server.tld/nick), most common case - $contact = dba::select('contact', array('id', 'avatar-date'), array('nurl' => normalise_link($url), 'uid' => $uid), array('limit' => 1)); - - // Then the addr (nick@server.tld) - if (!DBM::is_result($contact)) { - $contact = dba::select('contact', array('id', 'avatar-date'), array('addr' => $url, 'uid' => $uid), array('limit' => 1)); - } - - // Then the alias (which could be anything) - if (!DBM::is_result($contact)) { - // The link could be provided as http although we stored it as https - $ssl_url = str_replace('http://', 'https://', $url); - $r = dba::select('contact', array('id', 'avatar-date'), array('`alias` IN (?, ?, ?) AND `uid` = ?', $url, normalise_link($url), $ssl_url, $uid), array('limit' => 1)); - $contact = dba::fetch($r); - dba::close($r); - } - - if (DBM::is_result($contact)) { - $contact_id = $contact["id"]; - - // Update the contact every 7 days - $update_contact = ($contact['avatar-date'] < datetime_convert('', '', 'now -7 days')); - - // We force the update if the avatar is empty - if ($contact['avatar'] == '') { - $update_contact = true; - } - - if (!$update_contact || $no_update) { - return $contact_id; - } - } elseif ($uid != 0) { - // Non-existing user-specific contact, exiting - return 0; - } - - $data = Probe::uri($url, "", $uid); - - // Last try in gcontact for unsupported networks - if (!in_array($data["network"], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA, NETWORK_PUMPIO, NETWORK_MAIL))) { - if ($uid != 0) { - return 0; - } - - // Get data from the gcontact table - $gcontacts = dba::select('gcontact', array('name', 'nick', 'url', 'photo', 'addr', 'alias', 'network'), array('nurl' => normalise_link($url)), array('limit' => 1)); - if (!DBM::is_result($gcontacts)) { - return 0; - } - - $data = array_merge($data, $gcontacts); - } - - if (!$contact_id && ($data["alias"] != '') && ($data["alias"] != $url)) { - $contact_id = self::getIdForURL($data["alias"], $uid, true); - } - - $url = $data["url"]; - if (!$contact_id) { - dba::insert( - 'contact', array('uid' => $uid, 'created' => datetime_convert(), 'url' => $data["url"], - 'nurl' => normalise_link($data["url"]), 'addr' => $data["addr"], - 'alias' => $data["alias"], 'notify' => $data["notify"], 'poll' => $data["poll"], - 'name' => $data["name"], 'nick' => $data["nick"], 'photo' => $data["photo"], - 'keywords' => $data["keywords"], 'location' => $data["location"], 'about' => $data["about"], - 'network' => $data["network"], 'pubkey' => $data["pubkey"], - 'rel' => CONTACT_IS_SHARING, 'priority' => $data["priority"], - 'batch' => $data["batch"], 'request' => $data["request"], - 'confirm' => $data["confirm"], 'poco' => $data["poco"], - 'name-date' => datetime_convert(), 'uri-date' => datetime_convert(), - 'avatar-date' => datetime_convert(), 'writable' => 1, 'blocked' => 0, - 'readonly' => 0, 'pending' => 0) - ); - - $s = dba::select('contact', array('id'), array('nurl' => normalise_link($data["url"]), 'uid' => $uid), array('order' => array('id'), 'limit' => 2)); - $contacts = dba::inArray($s); - if (!DBM::is_result($contacts)) { - return 0; - } - - $contact_id = $contacts[0]["id"]; - - // Update the newly created contact from data in the gcontact table - $gcontact = dba::select('gcontact', array('location', 'about', 'keywords', 'gender'), array('nurl' => normalise_link($data["url"])), array('limit' => 1)); - if (DBM::is_result($gcontact)) { - // Only use the information when the probing hadn't fetched these values - if ($data['keywords'] != '') { - unset($gcontact['keywords']); - } - if ($data['location'] != '') { - unset($gcontact['location']); - } - if ($data['about'] != '') { - unset($gcontact['about']); - } - dba::update('contact', $gcontact, array('id' => $contact_id)); - } - - if (count($contacts) > 1 && $uid == 0 && $contact_id != 0 && $data["url"] != "") { - dba::delete('contact', array("`nurl` = ? AND `uid` = 0 AND `id` != ? AND NOT `self`", - normalise_link($data["url"]), $contact_id)); - } - } - - self::updateAvatar($data["photo"], $uid, $contact_id); - - $fields = array('url', 'nurl', 'addr', 'alias', 'name', 'nick', 'keywords', 'location', 'about', 'avatar-date', 'pubkey'); - $contact = dba::select('contact', $fields, array('id' => $contact_id), array('limit' => 1)); - - // This condition should always be true - if (!DBM::is_result($contact)) { - return $contact_id; - } - - $updated = array('addr' => $data['addr'], - 'alias' => $data['alias'], - 'url' => $data['url'], - 'nurl' => normalise_link($data['url']), - 'name' => $data['name'], - 'nick' => $data['nick']); - - // Only fill the pubkey if it was empty before. We have to prevent identity theft. - if (!empty($contact['pubkey'])) { - unset($contact['pubkey']); - } else { - $updated['pubkey'] = $data['pubkey']; - } - - if ($data['keywords'] != '') { - $updated['keywords'] = $data['keywords']; - } - if ($data['location'] != '') { - $updated['location'] = $data['location']; - } - if ($data['about'] != '') { - $updated['about'] = $data['about']; - } - - if (($data["addr"] != $contact["addr"]) || ($data["alias"] != $contact["alias"])) { - $updated['uri-date'] = datetime_convert(); - } - if (($data["name"] != $contact["name"]) || ($data["nick"] != $contact["nick"])) { - $updated['name-date'] = datetime_convert(); - } - - $updated['avatar-date'] = datetime_convert(); - - dba::update('contact', $updated, array('id' => $contact_id), $contact); - - return $contact_id; - } - - /** - * @brief Checks if the contact is blocked - * - * @param int $cid contact id - * - * @return boolean Is the contact blocked? - */ - public static function isBlocked($cid) - { - if ($cid == 0) { - return false; - } - - $blocked = dba::select('contact', array('blocked'), array('id' => $cid), array('limit' => 1)); - if (!DBM::is_result($blocked)) { - return false; - } - return (bool) $blocked['blocked']; - } - - /** - * @brief Checks if the contact is hidden - * - * @param int $cid contact id - * - * @return boolean Is the contact hidden? - */ - public static function isHidden($cid) - { - if ($cid == 0) { - return false; - } - - $hidden = dba::select('contact', array('hidden'), array('id' => $cid), array('limit' => 1)); - if (!DBM::is_result($hidden)) { - return false; - } - return (bool) $hidden['hidden']; - } - - /** - * @brief Returns posts from a given contact url - * - * @param string $contact_url Contact URL - * - * @return string posts in HTML - */ - public static function getPostsFromUrl($contact_url) - { - $a = self::getApp(); - - require_once 'include/conversation.php'; - - // There are no posts with "uid = 0" with connector networks - // This speeds up the query a lot - $r = q("SELECT `network`, `id` AS `author-id`, `contact-type` FROM `contact` - WHERE `contact`.`nurl` = '%s' AND `contact`.`uid` = 0", dbesc(normalise_link($contact_url))); - - if (!DBM::is_result($r)) { - return ''; - } - - if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { - $sql = "(`item`.`uid` = 0 OR (`item`.`uid` = %d AND NOT `item`.`global`))"; - } else { - $sql = "`item`.`uid` = %d"; - } - - $author_id = intval($r[0]["author-id"]); - - $contact = ($r[0]["contact-type"] == ACCOUNT_TYPE_COMMUNITY ? 'owner-id' : 'author-id'); - - $r = q(item_query() . " AND `item`.`" . $contact . "` = %d AND " . $sql . - " ORDER BY `item`.`created` DESC LIMIT %d, %d", intval($author_id), intval(local_user()), intval($a->pager['start']), intval($a->pager['itemspage']) - ); - - - $o = conversation($a, $r, 'community', false); - - $o .= alt_pager($a, count($r)); - - return $o; - } - - /** - * @brief Returns the account type name - * - * The function can be called with either the user or the contact array - * - * @param array $contact contact or user array - * @return string - */ - public static function getAccountType(array $contact) - { - // There are several fields that indicate that the contact or user is a forum - // "page-flags" is a field in the user table, - // "forum" and "prv" are used in the contact table. They stand for PAGE_COMMUNITY and PAGE_PRVGROUP. - // "community" is used in the gcontact table and is true if the contact is PAGE_COMMUNITY or PAGE_PRVGROUP. - if ((isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_COMMUNITY)) - || (isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_PRVGROUP)) - || (isset($contact['forum']) && intval($contact['forum'])) - || (isset($contact['prv']) && intval($contact['prv'])) - || (isset($contact['community']) && intval($contact['community'])) - ) { - $type = ACCOUNT_TYPE_COMMUNITY; - } else { - $type = ACCOUNT_TYPE_PERSON; - } - - // The "contact-type" (contact table) and "account-type" (user table) are more general then the chaos from above. - if (isset($contact["contact-type"])) { - $type = $contact["contact-type"]; - } - if (isset($contact["account-type"])) { - $type = $contact["account-type"]; - } - - switch ($type) { - case ACCOUNT_TYPE_ORGANISATION: - $account_type = t("Organisation"); - break; - case ACCOUNT_TYPE_NEWS: - $account_type = t('News'); - break; - case ACCOUNT_TYPE_COMMUNITY: - $account_type = t("Forum"); - break; - default: - $account_type = ""; - break; - } - - return $account_type; - } - - /** - * @brief Blocks a contact - * - * @param int $uid - * @return bool - */ - public static function block($uid) - { - $return = dba::update('contact', ['blocked' => true], ['id' => $uid]); - - return $return; - } - - /** - * @brief Unblocks a contact - * - * @param int $uid - * @return bool - */ - public static function unblock($uid) - { - $return = dba::update('contact', ['blocked' => false], ['id' => $uid]); - - return $return; - } - - /** - * @brief Updates the avatar links in a contact only if needed - * - * @param string $avatar Link to avatar picture - * @param int $uid User id of contact owner - * @param int $cid Contact id - * @param bool $force force picture update - * - * @return array Returns array of the different avatar sizes - */ - public static function updateAvatar($avatar, $uid, $cid, $force = false) - { - // Limit = 1 returns the row so no need for dba:inArray() - $r = dba::select('contact', array('avatar', 'photo', 'thumb', 'micro', 'nurl'), array('id' => $cid), array('limit' => 1)); - if (!DBM::is_result($r)) { - return false; - } else { - $data = array($r["photo"], $r["thumb"], $r["micro"]); - } - - if (($r["avatar"] != $avatar) || $force) { - $photos = Photo::importProfilePhoto($avatar, $uid, $cid, true); - - if ($photos) { - dba::update( - 'contact', - array('avatar' => $avatar, 'photo' => $photos[0], 'thumb' => $photos[1], 'micro' => $photos[2], 'avatar-date' => datetime_convert()), - array('id' => $cid) - ); - - // Update the public contact (contact id = 0) - if ($uid != 0) { - $pcontact = dba::select('contact', array('id'), array('nurl' => $r[0]['nurl']), array('limit' => 1)); - if (DBM::is_result($pcontact)) { - self::updateAvatar($avatar, 0, $pcontact['id'], $force); - } - } - - return $photos; - } - } - - return $data; - } -} diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index c1956c4571..cddbb4d7c0 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -13,9 +13,9 @@ use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; use Friendica\Model\Profile; -use Friendica\Object\Contact; use Friendica\Object\Image; use Friendica\Protocol\OStatus; use Friendica\Util\XML; diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 28989fb333..89fbb6e5f3 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -16,10 +16,10 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; use Friendica\Model\Profile; use Friendica\Network\Probe; -use Friendica\Object\Contact; use Friendica\Util\XML; use dba; diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 0f14c77c39..b96eeeb3ec 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -9,9 +9,9 @@ use Friendica\Core\Cache; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; use Friendica\Network\Probe; -use Friendica\Object\Contact; use Friendica\Object\Image; use Friendica\Util\Lock; use Friendica\Util\XML; diff --git a/src/Worker/CronJobs.php b/src/Worker/CronJobs.php index 7df7d030cb..18c1d2b531 100644 --- a/src/Worker/CronJobs.php +++ b/src/Worker/CronJobs.php @@ -10,9 +10,9 @@ use Friendica\App; use Friendica\Core\Cache; use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\GlobalContact; use Friendica\Network\Probe; -use Friendica\Object\Contact; use Friendica\Protocol\PortableContact; use dba; diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php index bb30fc3bf4..c20bb8d8f8 100644 --- a/src/Worker/Delivery.php +++ b/src/Worker/Delivery.php @@ -9,7 +9,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; use Friendica\Protocol\Diaspora; use Friendica\Protocol\DFRN; use Friendica\Protocol\Email; diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index a3a03055ec..18fff2afda 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -7,8 +7,8 @@ namespace Friendica\Worker; use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Network\Probe; -use Friendica\Object\Contact; use Friendica\Protocol\Diaspora; use Friendica\Protocol\OStatus; use Friendica\Protocol\Salmon; diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index 1190c77f5f..9024d0d4c9 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -7,7 +7,7 @@ namespace Friendica\Worker; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Database\DBM; -use Friendica\Object\Contact; +use Friendica\Model\Contact; use Friendica\Protocol\Email; use Friendica\Protocol\PortableContact; use dba; diff --git a/util/global_community_block.php b/util/global_community_block.php index ab586b6510..87044bb4e4 100755 --- a/util/global_community_block.php +++ b/util/global_community_block.php @@ -29,7 +29,7 @@ if ($argc != 2 || $argv[1] == "-h" || $argv[1] == "--help" || $argv[1] == "-?") } use Friendica\BaseObject; -use Friendica\Object\Contact; +use Friendica\Model\Contact; require_once 'boot.php'; require_once 'include/dba.php';