From: Michael Vogel Date: Fri, 8 Dec 2017 04:21:51 +0000 (+0100) Subject: Revert "Move Objects to Model" X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=5747cfc79c9ade7fb95cc95769ed06bb7ad118ef;p=friendica.git Revert "Move Objects to Model" --- diff --git a/boot.php b/boot.php index fa26028113..148ca5e6e2 100644 --- a/boot.php +++ b/boot.php @@ -27,7 +27,8 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Model\Contact; +use Friendica\Object\Contact; +use Friendica\Util\Lock; require_once 'include/network.php'; require_once 'include/plugin.php'; diff --git a/include/acl_selectors.php b/include/acl_selectors.php index d1b791136f..f971d462b2 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\GContact; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; require_once "include/contact_selectors.php"; require_once "include/contact_widgets.php"; @@ -774,7 +774,7 @@ function navbar_complete(App $a) { } if ($localsearch) { - $x = GContact::searchByName($search, $mode); + $x = GlobalContact::searchByName($search, $mode); return $x; } diff --git a/include/api.php b/include/api.php index e5963fb8fa..b5799d4786 100644 --- a/include/api.php +++ b/include/api.php @@ -12,8 +12,6 @@ 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; use Friendica\Network\HTTPException; @@ -25,7 +23,8 @@ use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\HTTPException\NotImplementedException; use Friendica\Network\HTTPException\UnauthorizedException; use Friendica\Network\HTTPException\TooManyRequestsException; -use Friendica\Object\Image; +use Friendica\Object\Contact; +use Friendica\Object\Photo; use Friendica\Protocol\Diaspora; use Friendica\Util\XML; @@ -1193,7 +1192,7 @@ function api_statuses_update($type) api_user() ); if (DBM::is_result($r)) { - $phototypes = Image::supportedTypes(); + $phototypes = Photo::supportedTypes(); $ext = $phototypes[$r[0]['type']]; $_REQUEST['body'] .= "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $r[0]['nickname'] . '/image/' . $r[0]['resource-id'] . ']'; $_REQUEST['body'] .= '[img]' . System::baseUrl() . '/photo/' . $r[0]['resource-id'] . '-' . $r[0]['scale'] . '.' . $ext . '[/img][/url]'; @@ -2378,7 +2377,7 @@ function api_get_attachments(&$body) $attachments = array(); foreach ($images[1] as $image) { - $imagedata = Image::getInfoFromURL($image); + $imagedata = Photo::getInfoFromURL($image); if ($imagedata) { $attachments[] = array("url" => $image, "mimetype" => $imagedata["mime"], "size" => $imagedata["size"]); @@ -2510,7 +2509,7 @@ function api_get_entitities(&$text, $bbcode) $start = iconv_strpos($text, $url, $offset, "UTF-8"); if (!($start === false)) { - $image = Image::getInfoFromURL($url); + $image = Photo::getInfoFromURL($url); if ($image) { // If image cache is activated, then use the following sizes: // thumb (150), small (340), medium (600) and large (1024) @@ -2518,19 +2517,19 @@ function api_get_entitities(&$text, $bbcode) $media_url = proxy_url($url); $sizes = array(); - $scale = Image::getScalingDimensions($image[0], $image[1], 150); + $scale = Photo::scaleImageTo($image[0], $image[1], 150); $sizes["thumb"] = array("w" => $scale["width"], "h" => $scale["height"], "resize" => "fit"); if (($image[0] > 150) || ($image[1] > 150)) { - $scale = Image::getScalingDimensions($image[0], $image[1], 340); + $scale = Photo::scaleImageTo($image[0], $image[1], 340); $sizes["small"] = array("w" => $scale["width"], "h" => $scale["height"], "resize" => "fit"); } - $scale = Image::getScalingDimensions($image[0], $image[1], 600); + $scale = Photo::scaleImageTo($image[0], $image[1], 600); $sizes["medium"] = array("w" => $scale["width"], "h" => $scale["height"], "resize" => "fit"); if (($image[0] > 600) || ($image[1] > 600)) { - $scale = Image::getScalingDimensions($image[0], $image[1], 1024); + $scale = Photo::scaleImageTo($image[0], $image[1], 1024); $sizes["large"] = array("w" => $scale["width"], "h" => $scale["height"], "resize" => "fit"); } } else { @@ -3947,7 +3946,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $ } if ($filetype == "") { - $filetype=Image::guessType($filename); + $filetype=Photo::guessImageType($filename); } $imagedata = getimagesize($src); if ($imagedata) { @@ -3971,13 +3970,13 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $ // create Photo instance with the data of the image $imagedata = @file_get_contents($src); - $Image = new Image($imagedata, $filetype); - if (! $Image->isValid()) { + $ph = new Photo($imagedata, $filetype); + if (! $ph->isValid()) { throw new InternalServerErrorException("unable to process image data"); } // check orientation of image - $Image->orient($src); + $ph->orient($src); @unlink($src); // check max length of images on server @@ -3986,11 +3985,11 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $ $max_length = MAX_IMAGE_LENGTH; } if ($max_length > 0) { - $Image->scaleDown($max_length); + $ph->scaleImage($max_length); logger("File upload: Scaling picture to new size " . $max_length, LOGGER_DEBUG); } - $width = $Image->getWidth(); - $height = $Image->getHeight(); + $width = $ph->getWidth(); + $height = $ph->getHeight(); // create a new resource-id if not already provided $hash = ($photo_id == null) ? photo_new_resource() : $photo_id; @@ -3999,21 +3998,21 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $ // upload normal image (scales 0, 1, 2) logger("photo upload: starting new photo upload", LOGGER_DEBUG); - $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 0, 0, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); + $r =$ph->store(local_user(), $visitor, $hash, $filename, $album, 0, 0, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); if (! $r) { logger("photo upload: image upload with scale 0 (original size) failed"); } if ($width > 640 || $height > 640) { - $Image->scaleDown(640); - $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 1, 0, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); + $ph->scaleImage(640); + $r = $ph->store(local_user(), $visitor, $hash, $filename, $album, 1, 0, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); if (! $r) { logger("photo upload: image upload with scale 1 (640x640) failed"); } } if ($width > 320 || $height > 320) { - $Image->scaleDown(320); - $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 2, 0, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); + $ph->scaleImage(320); + $r = $ph->store(local_user(), $visitor, $hash, $filename, $album, 2, 0, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); if (! $r) { logger("photo upload: image upload with scale 2 (320x320) failed"); } @@ -4024,29 +4023,29 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $ logger("photo upload: starting new profile image upload", LOGGER_DEBUG); if ($width > 175 || $height > 175) { - $Image->scaleDown(175); - $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 4, $profile, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); + $ph->scaleImage(175); + $r = $ph->store(local_user(), $visitor, $hash, $filename, $album, 4, $profile, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); if (! $r) { logger("photo upload: profile image upload with scale 4 (175x175) failed"); } } if ($width > 80 || $height > 80) { - $Image->scaleDown(80); - $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 5, $profile, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); + $ph->scaleImage(80); + $r = $ph->store(local_user(), $visitor, $hash, $filename, $album, 5, $profile, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); if (! $r) { logger("photo upload: profile image upload with scale 5 (80x80) failed"); } } if ($width > 48 || $height > 48) { - $Image->scaleDown(48); - $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 6, $profile, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); + $ph->scaleImage(48); + $r = $ph->store(local_user(), $visitor, $hash, $filename, $album, 6, $profile, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); if (! $r) { logger("photo upload: profile image upload with scale 6 (48x48) failed"); } } - $Image->__destruct(); + $ph->__destruct(); logger("photo upload: new profile image upload ended", LOGGER_DEBUG); } diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php index e1a67d432d..3b1540473a 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 b445fd01b0..196c3ca3c1 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\Model\Contact; +use Friendica\Object\Contact; require_once 'include/oembed.php'; require_once 'include/event.php'; diff --git a/include/contact_widgets.php b/include/contact_widgets.php index 9c44f4d156..31e57ea839 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -7,7 +7,7 @@ use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Database\DBM; -use Friendica\Model\GContact; +use Friendica\Model\GlobalContact; require_once 'include/contact_selectors.php'; @@ -250,18 +250,18 @@ function common_friends_visitor_widget($profile_uid) { } if ($cid) { - $t = GContact::countCommonFriends($profile_uid, $cid); + $t = GlobalContact::countCommonFriends($profile_uid, $cid); } else { - $t = GContact::countCommonFriendsZcid($profile_uid, $zcid); + $t = GlobalContact::countCommonFriendsZcid($profile_uid, $zcid); } if (! $t) { return; } if ($cid) { - $r = GContact::commonFriends($profile_uid, $cid, 0, 5, true); + $r = GlobalContact::commonFriends($profile_uid, $cid, 0, 5, true); } else { - $r = GContact::commonFriendsZcid($profile_uid, $zcid, 0, 5, true); + $r = GlobalContact::commonFriendsZcid($profile_uid, $zcid, 0, 5, true); } return replace_macros(get_markup_template('remote_friends_common.tpl'), array( diff --git a/include/conversation.php b/include/conversation.php index ce937a7a71..2543a5170e 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -8,8 +8,8 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Model\Contact; -use Friendica\Object\Thread; +use Friendica\Object\Contact; +use Friendica\Object\Conversation; use Friendica\Object\Item; require_once "include/bbcode.php"; @@ -840,7 +840,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { // Normal View $page_template = get_markup_template("threaded_conversation.tpl"); - $conv = new Thread($mode, $preview); + $conv = new Conversation($mode, $preview); /* * get all the topmost parents @@ -881,7 +881,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { if ($item['id'] == $item['parent']) { $item_object = new Item($item); - $conv->addParent($item_object); + $conv->addThread($item_object); } } diff --git a/include/follow.php b/include/follow.php index e08136cab1..14b9c68ed5 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 9a0900dc1f..a3a007cc18 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\Model\Contact; +use Friendica\Object\Contact; require_once 'include/bbcode.php'; require_once 'mod/proxy.php'; diff --git a/include/items.php b/include/items.php index 0779ed91e1..61a9c7a1fa 100644 --- a/include/items.php +++ b/include/items.php @@ -10,11 +10,11 @@ use Friendica\Core\PConfig; use Friendica\Core\Worker; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Model\Contact; -use Friendica\Model\GContact; -use Friendica\Object\Image; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; use Friendica\Protocol\DFRN; use Friendica\Protocol\OStatus; +use Friendica\Util\Lock; require_once 'include/bbcode.php'; require_once 'include/oembed.php'; @@ -742,10 +742,10 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f * On comments the author is the better choice. */ if ($arr['parent-uri'] === $arr['uri']) { - $arr["gcontact-id"] = GContact::getId(array("url" => $arr['owner-link'], "network" => $arr['network'], + $arr["gcontact-id"] = GlobalContact::getId(array("url" => $arr['owner-link'], "network" => $arr['network'], "photo" => $arr['owner-avatar'], "name" => $arr['owner-name'])); } else { - $arr["gcontact-id"] = GContact::getId(array("url" => $arr['author-link'], "network" => $arr['network'], + $arr["gcontact-id"] = GlobalContact::getId(array("url" => $arr['author-link'], "network" => $arr['network'], "photo" => $arr['author-avatar'], "name" => $arr['author-name'])); } } @@ -1887,11 +1887,11 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { $width = intval($match[1]); $height = intval($match[2]); - $Image = new Image($data, $type); - if ($Image->isValid()) { - $Image->scaleDown(max($width, $height)); - $data = $Image->asString(); - $type = $Image->getType(); + $ph = new Photo($data, $type); + if ($ph->isValid()) { + $ph->scaleImage(max($width, $height)); + $data = $ph->imageString(); + $type = $ph->getType(); } } diff --git a/include/like.php b/include/like.php index 9a8b9b957b..1dcadde705 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\Model\Contact; +use Friendica\Object\Contact; use Friendica\Protocol\Diaspora; /** diff --git a/include/network.php b/include/network.php index 16c8185e1a..45f5d4e79a 100644 --- a/include/network.php +++ b/include/network.php @@ -6,7 +6,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Network\Probe; -use Friendica\Object\Image; +use Friendica\Object\Photo; use Friendica\Util\XML; /** @@ -710,18 +710,18 @@ function scale_external_images($srctext, $include_link = true, $scale_replace = } // guess mimetype from headers or filename - $type = Image::guessType($mtch[1], true); + $type = Photo::guessImageType($mtch[1], true); if ($i) { - $Image = new Image($i, $type); - if ($Image->isValid()) { - $orig_width = $Image->getWidth(); - $orig_height = $Image->getHeight(); + $ph = new Photo($i, $type); + if ($ph->isValid()) { + $orig_width = $ph->getWidth(); + $orig_height = $ph->getHeight(); if ($orig_width > 640 || $orig_height > 640) { - $Image->scaleDown(640); - $new_width = $Image->getWidth(); - $new_height = $Image->getHeight(); + $ph->scaleImage(640); + $new_width = $ph->getWidth(); + $new_height = $ph->getHeight(); logger('scale_external_images: ' . $orig_width . '->' . $new_width . 'w ' . $orig_height . '->' . $new_height . 'h' . ' match: ' . $mtch[0], LOGGER_DEBUG); $s = str_replace( $mtch[0], diff --git a/include/plaintext.php b/include/plaintext.php index 39dcc9ecdb..221d1471b1 100644 --- a/include/plaintext.php +++ b/include/plaintext.php @@ -5,7 +5,7 @@ use Friendica\App; use Friendica\ParseUrl; use Friendica\Core\PConfig; -use Friendica\Object\Image; +use Friendica\Object\Photo; require_once "include/bbcode.php"; require_once "include/html2plain.php"; @@ -51,7 +51,7 @@ function get_old_attachment_data($body) { if (preg_match("/\[img\]([$URLSearchString]*)\[\/img\]/ism", $attacheddata, $matches)) { - $picturedata = Image::getInfoFromURL($matches[1]); + $picturedata = Photo::getInfoFromURL($matches[1]); if (($picturedata[0] >= 500) && ($picturedata[0] >= $picturedata[1])) $post["image"] = $matches[1]; @@ -221,7 +221,7 @@ function get_attached_data($body, $item = array()) { $post["preview"] = $pictures[0][2]; $post["text"] = str_replace($pictures[0][0], "", $body); } else { - $imgdata = Image::getInfoFromURL($pictures[0][1]); + $imgdata = Photo::getInfoFromURL($pictures[0][1]); if (substr($imgdata["mime"], 0, 6) == "image/") { $post["type"] = "photo"; $post["image"] = $pictures[0][1]; diff --git a/include/post_update.php b/include/post_update.php index 0d223709e2..f67c064daf 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\GContact; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; /** * @brief Calls the post update functions @@ -74,7 +74,7 @@ function post_update_1192() { // Set the "gcontact-id" in the item table and add a new gcontact entry if needed foreach ($item_arr AS $item) { - $gcontact_id = GContact::getId(array("url" => $item['author-link'], "network" => $item['network'], + $gcontact_id = GlobalContact::getId(array("url" => $item['author-link'], "network" => $item['network'], "photo" => $item['author-avatar'], "name" => $item['author-name'])); q("UPDATE `item` SET `gcontact-id` = %d WHERE `uid` = %d AND `author-link` = '%s' AND `gcontact-id` = 0", intval($gcontact_id), intval($item["uid"]), dbesc($item["author-link"])); diff --git a/include/tags.php b/include/tags.php index 8d8fb76559..45a17f9c96 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\Model\Contact; +use Friendica\Object\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 494fbe1ce3..00848ccc6e 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\Model\Contact; +use Friendica\Object\Contact; function add_thread($itemid, $onlyshadow = false) { $items = q("SELECT `uid`, `created`, `edited`, `commented`, `received`, `changed`, `wall`, `private`, `pubmail`, diff --git a/include/uimport.php b/include/uimport.php index e3c2f4e6c1..7effcd62dd 100644 --- a/include/uimport.php +++ b/include/uimport.php @@ -7,8 +7,7 @@ use Friendica\Core\System; use Friendica\Core\PConfig; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Model\Photo; -use Friendica\Object\Image; +use Friendica\Object\Photo; define("IMPORT_DEBUG", False); @@ -261,9 +260,8 @@ function import_account(App $a, $file) { $photo['uid'] = $newuid; $photo['data'] = hex2bin($photo['data']); - $Image = new Image($photo['data'], $photo['type']); - $r = Photo::store( - $Image, + $p = new Photo($photo['data'], $photo['type']); + $r = $p->store( $photo['uid'], $photo['contact-id'], //0 $photo['resource-id'], $photo['filename'], $photo['album'], $photo['scale'], $photo['profile'], //1 $photo['allow_cid'], $photo['allow_gid'], $photo['deny_cid'], $photo['deny_gid'] diff --git a/mod/admin.php b/mod/admin.php index 321e7b6172..29e10bda83 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 1456661253..3cfe6c0f9e 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\GContact; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; require_once 'include/contact_selectors.php'; require_once 'mod/contacts.php'; @@ -41,12 +41,12 @@ function allfriends_content(App $a) { $a->page['aside'] = ""; profile_load($a, "", 0, Contact::getDetailsByURL($c[0]["url"])); - $total = GContact::countAllFriends(local_user(), $cid); + $total = GlobalContact::countAllFriends(local_user(), $cid); if(count($total)) $a->set_pager_total($total); - $r = GContact::allFriends(local_user(), $cid, $a->pager['start'], $a->pager['itemspage']); + $r = GlobalContact::allFriends(local_user(), $cid, $a->pager['start'], $a->pager['itemspage']); if (! DBM::is_result($r)) { $o .= t('No friends to display.'); diff --git a/mod/cal.php b/mod/cal.php index cef9857ea9..7eb31905b8 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\Model\Contact; +use Friendica\Object\Contact; require_once 'include/event.php'; require_once 'include/redir.php'; diff --git a/mod/common.php b/mod/common.php index 74b4dec7c6..9933c3f51f 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\GContact; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; require_once 'include/contact_selectors.php'; require_once 'mod/contacts.php'; @@ -85,9 +85,9 @@ function common_content(App $a) { } if ($cid) { - $t = GContact::countCommonFriends($uid, $cid); + $t = GlobalContact::countCommonFriends($uid, $cid); } else { - $t = GContact::countCommonFriendsZcid($uid, $zcid); + $t = GlobalContact::countCommonFriendsZcid($uid, $zcid); } if (count($t)) { @@ -99,9 +99,9 @@ function common_content(App $a) { if ($cid) { - $r = GContact::commonFriends($uid, $cid, $a->pager['start'], $a->pager['itemspage']); + $r = GlobalContact::commonFriends($uid, $cid, $a->pager['start'], $a->pager['itemspage']); } else { - $r = GContact::commonFriendsZcid($uid, $zcid, $a->pager['start'], $a->pager['itemspage']); + $r = GlobalContact::commonFriendsZcid($uid, $zcid, $a->pager['start'], $a->pager['itemspage']); } diff --git a/mod/contacts.php b/mod/contacts.php index 71ffcc2d66..9feacaf5e3 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\GContact; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; +use Friendica\Object\Contact; require_once 'include/contact_selectors.php'; require_once 'mod/proxy.php'; @@ -313,7 +313,7 @@ function _contact_update_profile($contact_id) { Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); // Update the entry in the gcontact table - GContact::updateFromProbe($data["url"]); + GlobalContact::updateFromProbe($data["url"]); } function _contact_block($contact_id, $orig_record) { @@ -887,7 +887,7 @@ function contacts_tab($a, $contact_id, $active_tab) { ); // Show this tab only if there is visible friend list - $x = GContact::countAllFriends(local_user(), $contact_id); + $x = GlobalContact::countAllFriends(local_user(), $contact_id); if ($x) $tabs[] = array('label'=>t('Contacts'), 'url' => "allfriends/".$contact_id, @@ -897,7 +897,7 @@ function contacts_tab($a, $contact_id, $active_tab) { 'accesskey' => 't'); // Show this tab only if there is visible common friend list - $common = GContact::countCommonFriends(local_user(), $contact_id); + $common = GlobalContact::countCommonFriends(local_user(), $contact_id); if ($common) $tabs[] = array('label'=>t('Common Friends'), 'url' => "common/loc/".local_user()."/".$contact_id, diff --git a/mod/crepair.php b/mod/crepair.php index 32db9be92c..7e1921f304 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\Model\Contact; +use Friendica\Object\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 c999013eff..18d9f25bf5 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 b81f26db9d..61be7966e0 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\Model\Contact; +use Friendica\Object\Contact; use Friendica\Protocol\DFRN; require_once 'include/items.php'; diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php index bff1464ae4..67395a9fcc 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 f29e3eb69b..d8ad6aeaba 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\Model\Contact; +use Friendica\Object\Contact; function directory_init(App $a) { $a->set_pager_itemspage(60); diff --git a/mod/dirfind.php b/mod/dirfind.php index bef89a4794..4ba122b566 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\GContact; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; +use Friendica\Object\Contact; use Friendica\Protocol\PortableContact; require_once 'include/contact_widgets.php'; @@ -82,7 +82,7 @@ function dirfind_content(App $a, $prefix = "") { // Add the contact to the global contacts if it isn't already in our system if (($contact["cid"] == 0) && ($contact["zid"] == 0) && ($contact["gid"] == 0)) { - GContact::update($user_data); + GlobalContact::update($user_data); } } elseif ($local) { diff --git a/mod/display.php b/mod/display.php index 2d22637ece..e81e654acb 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\Model\Contact; +use Friendica\Object\Contact; use Friendica\Protocol\DFRN; function display_init(App $a) { diff --git a/mod/fbrowser.php b/mod/fbrowser.php index 3297dd918b..516be52987 100644 --- a/mod/fbrowser.php +++ b/mod/fbrowser.php @@ -7,7 +7,7 @@ use Friendica\App; use Friendica\Core\System; -use Friendica\Object\Image; +use Friendica\Object\Photo; /** * @param App $a @@ -66,7 +66,7 @@ function fbrowser_content(App $a) { function _map_files1($rr){ $a = get_app(); - $types = Image::supportedTypes(); + $types = Photo::supportedTypes(); $ext = $types[$rr['type']]; $filename_e = $rr['filename']; diff --git a/mod/follow.php b/mod/follow.php index f0cffff4a1..b5e73ca9a4 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 8ad5cd0ebe..5542fe5b98 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\GContact; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; function hovercard_init(App $a) { // Just for testing purposes @@ -47,7 +47,7 @@ function hovercard_content() { } // if it's the url containing https it should be converted to http - $nurl = normalise_link(GContact::cleanContactUrl($profileurl)); + $nurl = normalise_link(GlobalContact::cleanContactUrl($profileurl)); if($nurl) { // Search for contact data $contact = Contact::getDetailsByURL($nurl); diff --git a/mod/install.php b/mod/install.php index 8df5d09352..0da8ec040f 100644 --- a/mod/install.php +++ b/mod/install.php @@ -5,7 +5,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Image; +use Friendica\Object\Photo; $install_wizard_pass = 1; @@ -503,7 +503,7 @@ function check_imagik(&$checks) { if (class_exists('Imagick')) { $imagick = true; - $supported = Image::supportedTypes(); + $supported = Photo::supportedTypes(); if (array_key_exists('image/gif', $supported)) { $gif = true; } diff --git a/mod/item.php b/mod/item.php index c35a48b7e7..ffac1c8e44 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\GContact; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; +use Friendica\Object\Contact; use Friendica\Protocol\Diaspora; use Friendica\Protocol\Email; use Friendica\Util\Emailer; @@ -743,7 +743,7 @@ function item_post(App $a) { $datarray['postopts'] = $postopts; $datarray['origin'] = $origin; $datarray['moderated'] = $allow_moderated; - $datarray['gcontact-id'] = GContact::getId(array("url" => $datarray['author-link'], "network" => $datarray['network'], + $datarray['gcontact-id'] = GlobalContact::getId(array("url" => $datarray['author-link'], "network" => $datarray['network'], "photo" => $datarray['author-avatar'], "name" => $datarray['author-name'])); $datarray['object'] = $object; @@ -1244,7 +1244,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n if (!DBM::is_result($r)) { $probed = Probe::uri($name); if ($result['network'] != NETWORK_PHANTOM) { - GContact::update($probed); + GlobalContact::update($probed); $r = q("SELECT `url`, `name`, `nick`, `network`, `alias`, `notify` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", dbesc(normalise_link($probed["url"]))); } diff --git a/mod/match.php b/mod/match.php index 563ce5bedc..3a0d10c319 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\Model\Contact; +use Friendica\Object\Contact; require_once 'include/text.php'; require_once 'include/contact_widgets.php'; diff --git a/mod/message.php b/mod/message.php index 7bb17f3906..cefc44356f 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\Model\Contact; +use Friendica\Object\Contact; require_once 'include/acl_selectors.php'; require_once 'include/message.php'; diff --git a/mod/network.php b/mod/network.php index 3ac13b24e0..7e61d083f6 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\Model\Contact; +use Friendica\Object\Contact; require_once 'include/conversation.php'; require_once 'include/group.php'; diff --git a/mod/nogroup.php b/mod/nogroup.php index d7df8cb187..5fb9afc2ac 100644 --- a/mod/nogroup.php +++ b/mod/nogroup.php @@ -4,7 +4,7 @@ */ use Friendica\App; use Friendica\Database\DBM; -use Friendica\Model\Contact; +use Friendica\Object\Contact; require_once 'include/contact_selectors.php'; diff --git a/mod/photo.php b/mod/photo.php index 243dfda029..8368b99a6b 100644 --- a/mod/photo.php +++ b/mod/photo.php @@ -4,7 +4,7 @@ */ use Friendica\App; use Friendica\Database\DBM; -use Friendica\Object\Image; +use Friendica\Object\Photo; require_once 'include/security.php'; @@ -75,7 +75,7 @@ function photo_init(App $a) { $uid = str_replace(array('.jpg', '.png', '.gif'), array('', '', ''), $person); - foreach (Image::supportedTypes() AS $m => $e) { + foreach (Photo::supportedTypes() AS $m => $e) { $uid = str_replace('.'.$e, '', $uid); } @@ -100,7 +100,7 @@ function photo_init(App $a) { $resolution = 0; $photo = str_replace(array('.jpg', '.png', '.gif'), array('', '', ''), $photo); - foreach (Image::supportedTypes() AS $m => $e) { + foreach (Photo::supportedTypes() AS $m => $e) { $photo = str_replace('.'.$e, '', $photo); } @@ -167,14 +167,14 @@ function photo_init(App $a) { } // Resize only if its not a GIF and it is supported by the library - if (($mimetype != "image/gif") && in_array($mimetype, Image::supportedTypes())) { - $Image = new Image($data, $mimetype); - if ($Image->isValid()) { + if (($mimetype != "image/gif") && in_array($mimetype, Photo::supportedTypes())) { + $ph = new Photo($data, $mimetype); + if ($ph->isValid()) { if (isset($customres) && $customres > 0 && $customres < 500) { - $Image->scaleToSquare($customres); + $ph->scaleImageSquare($customres); } - $data = $Image->asString(); - $mimetype = $Image->getType(); + $data = $ph->imageString(); + $mimetype = $ph->getType(); } } diff --git a/mod/photos.php b/mod/photos.php index cc3ec71a65..3e2c44e3cd 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -8,10 +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\Image; +use Friendica\Object\Contact; +use Friendica\Object\Photo; require_once 'include/photos.php'; require_once 'include/items.php'; @@ -137,7 +136,7 @@ function photos_post(App $a) { logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA); logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA); - $phototypes = Image::supportedTypes(); + $phototypes = Photo::supportedTypes(); $can_post = false; $visitor = 0; @@ -425,16 +424,16 @@ function photos_post(App $a) { intval($page_owner_uid) ); if (DBM::is_result($r)) { - $Image = new Image($r[0]['data'], $r[0]['type']); - if ($Image->isValid()) { + $ph = new Photo($r[0]['data'], $r[0]['type']); + if ($ph->isValid()) { $rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 ); - $Image->rotate($rotate_deg); + $ph->rotate($rotate_deg); - $width = $Image->getWidth(); - $height = $Image->getHeight(); + $width = $ph->getWidth(); + $height = $ph->getHeight(); $x = q("UPDATE `photo` SET `data` = '%s', `height` = %d, `width` = %d WHERE `resource-id` = '%s' AND `uid` = %d AND `scale` = 0", - dbesc($Image->asString()), + dbesc($ph->imageString()), intval($height), intval($width), dbesc($resource_id), @@ -442,12 +441,12 @@ function photos_post(App $a) { ); if ($width > 640 || $height > 640) { - $Image->scaleDown(640); - $width = $Image->getWidth(); - $height = $Image->getHeight(); + $ph->scaleImage(640); + $width = $ph->getWidth(); + $height = $ph->getHeight(); $x = q("UPDATE `photo` SET `data` = '%s', `height` = %d, `width` = %d WHERE `resource-id` = '%s' AND `uid` = %d AND `scale` = 1", - dbesc($Image->asString()), + dbesc($ph->imageString()), intval($height), intval($width), dbesc($resource_id), @@ -456,12 +455,12 @@ function photos_post(App $a) { } if ($width > 320 || $height > 320) { - $Image->scaleDown(320); - $width = $Image->getWidth(); - $height = $Image->getHeight(); + $ph->scaleImage(320); + $width = $ph->getWidth(); + $height = $ph->getHeight(); $x = q("UPDATE `photo` SET `data` = '%s', `height` = %d, `width` = %d WHERE `resource-id` = '%s' AND `uid` = %d AND `scale` = 2", - dbesc($Image->asString()), + dbesc($ph->imageString()), intval($height), intval($width), dbesc($resource_id), @@ -812,7 +811,7 @@ function photos_post(App $a) { $type = $_FILES['userfile']['type']; } if ($type == "") { - $type = Image::guessType($filename); + $type = Photo::guessImageType($filename); } logger('photos: upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG); @@ -839,9 +838,9 @@ function photos_post(App $a) { $imagedata = @file_get_contents($src); - $Image = new Image($imagedata, $type); + $ph = new Photo($imagedata, $type); - if (! $Image->isValid()) { + if (! $ph->isValid()) { logger('mod/photos.php: photos_post(): unable to process image' , LOGGER_DEBUG); notice( t('Unable to process image.') . EOL ); @unlink($src); @@ -850,7 +849,7 @@ function photos_post(App $a) { killme(); } - $exif = $Image->orient($src); + $exif = $ph->orient($src); @unlink($src); $max_length = Config::get('system', 'max_image_length'); @@ -858,17 +857,17 @@ function photos_post(App $a) { $max_length = MAX_IMAGE_LENGTH; } if ($max_length > 0) { - $Image->scaleDown($max_length); + $ph->scaleImage($max_length); } - $width = $Image->getWidth(); - $height = $Image->getHeight(); + $width = $ph->getWidth(); + $height = $ph->getHeight(); $smallest = 0; $photo_hash = photo_new_resource(); - $r = Photo::store($Image, $page_owner_uid, $visitor, $photo_hash, $filename, $album, 0 , 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); + $r = $ph->store($page_owner_uid, $visitor, $photo_hash, $filename, $album, 0 , 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); if (! $r) { logger('mod/photos.php: photos_post(): image store failed' , LOGGER_DEBUG); @@ -877,14 +876,14 @@ function photos_post(App $a) { } if ($width > 640 || $height > 640) { - $Image->scaleDown(640); - Photo::store($Image, $page_owner_uid, $visitor, $photo_hash, $filename, $album, 1, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); + $ph->scaleImage(640); + $ph->store($page_owner_uid, $visitor, $photo_hash, $filename, $album, 1, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); $smallest = 1; } if ($width > 320 || $height > 320) { - $Image->scaleDown(320); - Photo::store($Image, $page_owner_uid, $visitor, $photo_hash, $filename, $album, 2, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); + $ph->scaleImage(320); + $ph->store($page_owner_uid, $visitor, $photo_hash, $filename, $album, 2, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); $smallest = 2; } @@ -933,7 +932,7 @@ function photos_post(App $a) { $arr['origin'] = 1; $arr['body'] = '[url=' . System::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $photo_hash . ']' - . '[img]' . System::baseUrl() . "/photo/{$photo_hash}-{$smallest}.".$Image->getExt() . '[/img]' + . '[img]' . System::baseUrl() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/img]' . '[/url]'; $item_id = item_store($arr); @@ -981,7 +980,7 @@ function photos_content(App $a) { return; } - $phototypes = Image::supportedTypes(); + $phototypes = Photo::supportedTypes(); $_SESSION['photo_return'] = $a->cmd; diff --git a/mod/ping.php b/mod/ping.php index 883129d14f..0f2a9584b8 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\Model\Contact; +use Friendica\Object\Contact; use Friendica\Util\XML; require_once 'include/datetime.php'; diff --git a/mod/profile_photo.php b/mod/profile_photo.php index e12c6e5c64..f667359b51 100644 --- a/mod/profile_photo.php +++ b/mod/profile_photo.php @@ -7,8 +7,7 @@ use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Model\Photo; -use Friendica\Object\Image; +use Friendica\Object\Photo; function profile_photo_init(App $a) { @@ -73,27 +72,27 @@ function profile_photo_post(App $a) { $base_image = $r[0]; - $Image = new Image($base_image['data'], $base_image['type']); - if ($Image->isValid()) { - $Image->crop(175,$srcX,$srcY,$srcW,$srcH); + $im = new Photo($base_image['data'], $base_image['type']); + if ($im->isValid()) { + $im->cropImage(175,$srcX,$srcY,$srcW,$srcH); - $r = Photo::store($Image, local_user(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 4, $is_default_profile); + $r = $im->store(local_user(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 4, $is_default_profile); if ($r === false) { notice ( sprintf(t('Image size reduction [%s] failed.'),"175") . EOL ); } - $Image->scaleDown(80); + $im->scaleImage(80); - $r = Photo::store($Image, local_user(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 5, $is_default_profile); + $r = $im->store(local_user(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 5, $is_default_profile); if ($r === false) { notice( sprintf(t('Image size reduction [%s] failed.'),"80") . EOL ); } - $Image->scaleDown(48); + $im->scaleImage(48); - $r = Photo::store($Image, local_user(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 6, $is_default_profile); + $r = $im->store(local_user(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 6, $is_default_profile); if ($r === false) { notice( sprintf(t('Image size reduction [%s] failed.'),"48") . EOL ); @@ -108,15 +107,15 @@ function profile_photo_post(App $a) { ); $r = q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s' WHERE `self` AND `uid` = %d", - dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-4.' . $Image->getExt()), - dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-5.' . $Image->getExt()), - dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-6.' . $Image->getExt()), + dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-4.' . $im->getExt()), + dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-5.' . $im->getExt()), + dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-6.' . $im->getExt()), intval(local_user()) ); } else { $r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d", - dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-4.' . $Image->getExt()), - dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-5.' . $Image->getExt()), + dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-4.' . $im->getExt()), + dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-5.' . $im->getExt()), intval($_REQUEST['profile']), intval(local_user()) ); @@ -152,7 +151,7 @@ function profile_photo_post(App $a) { $filesize = intval($_FILES['userfile']['size']); $filetype = $_FILES['userfile']['type']; if ($filetype == "") { - $filetype = Image::guessType($filename); + $filetype = Photo::guessImageType($filename); } $maximagesize = Config::get('system', 'maximagesize'); @@ -164,7 +163,7 @@ function profile_photo_post(App $a) { } $imagedata = @file_get_contents($src); - $ph = new Image($imagedata, $filetype); + $ph = new Photo($imagedata, $filetype); if (! $ph->isValid()) { notice(t('Unable to process image.') . EOL); @@ -240,7 +239,7 @@ function profile_photo_content(App $a) { goaway(System::baseUrl() . '/profiles'); return; // NOTREACHED } - $ph = new Image($r[0]['data'], $r[0]['type']); + $ph = new Photo($r[0]['data'], $r[0]['type']); profile_photo_crop_ui_head($a, $ph); // go ahead as we have jus uploaded a new photo to crop } @@ -289,22 +288,22 @@ function profile_photo_content(App $a) { if(! function_exists('profile_photo_crop_ui_head')) { -function profile_photo_crop_ui_head(App $a, Image $Image) { +function profile_photo_crop_ui_head(App $a, $ph) { $max_length = Config::get('system','max_image_length'); if (! $max_length) { $max_length = MAX_IMAGE_LENGTH; } if ($max_length > 0) { - $Image->scaleDown($max_length); + $ph->scaleImage($max_length); } - $width = $Image->getWidth(); - $height = $Image->getHeight(); + $width = $ph->getWidth(); + $height = $ph->getHeight(); if ($width < 175 || $height < 175) { - $Image->scaleUp(200); - $width = $Image->getWidth(); - $height = $Image->getHeight(); + $ph->scaleImageUp(200); + $width = $ph->getWidth(); + $height = $ph->getHeight(); } $hash = photo_new_resource(); @@ -312,7 +311,7 @@ function profile_photo_crop_ui_head(App $a, Image $Image) { $smallest = 0; - $r = Photo::store($Image, local_user(), 0 , $hash, $filename, t('Profile Photos'), 0 ); + $r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 0 ); if ($r) { info( t('Image uploaded successfully.') . EOL ); @@ -321,8 +320,8 @@ function profile_photo_crop_ui_head(App $a, Image $Image) { } if ($width > 640 || $height > 640) { - $Image->scaleDown(640); - $r = Photo::store($Image, local_user(), 0 , $hash, $filename, t('Profile Photos'), 1 ); + $ph->scaleImage(640); + $r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 1 ); if ($r === false) { notice( sprintf(t('Image size reduction [%s] failed.'),"640") . EOL ); @@ -333,7 +332,7 @@ function profile_photo_crop_ui_head(App $a, Image $Image) { $a->config['imagecrop'] = $hash; $a->config['imagecrop_resolution'] = $smallest; - $a->config['imagecrop_ext'] = $Image->getExt(); + $a->config['imagecrop_ext'] = $ph->getExt(); $a->page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array()); $a->page['end'] .= replace_macros(get_markup_template("cropend.tpl"), array()); return; diff --git a/mod/profiles.php b/mod/profiles.php index 893f0d51e3..eca13bf10c 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -9,9 +9,9 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Model\GContact; -use Friendica\Model\Profile; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; +use Friendica\Object\Profile; function profiles_init(App $a) { @@ -509,7 +509,7 @@ function profiles_post(App $a) { Worker::add(PRIORITY_LOW, 'ProfileUpdate', local_user()); // Update the global contact for the user - GContact::updateForUser(local_user()); + GlobalContact::updateForUser(local_user()); } } } diff --git a/mod/proxy.php b/mod/proxy.php index e134565ce0..790309c627 100644 --- a/mod/proxy.php +++ b/mod/proxy.php @@ -8,8 +8,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Model\Photo; -use Friendica\Object\Image; +use Friendica\Object\Photo; define('PROXY_DEFAULT_TIME', 86400); // 1 Day @@ -131,9 +130,9 @@ function proxy_init(App $a) { // reduce quality - if it isn't a GIF if ($mime != 'image/gif') { - $Image = new Image($img_str, $mime); - if ($Image->isValid()) { - $img_str = $Image->asString(); + $img = new Photo($img_str, $mime); + if ($img->isValid()) { + $img_str = $img->imageString(); } } @@ -175,10 +174,10 @@ function proxy_init(App $a) { $mime = 'image/png'; $cachefile = ''; // Clear the cachefile so that the dummy isn't stored $valid = false; - $Image = new Image($img_str, 'image/png'); - if ($Image->isValid()) { - $Image->scaleDown(10); - $img_str = $Image->asString(); + $img = new Photo($img_str, 'image/png'); + if ($img->isValid()) { + $img->scaleImage(10); + $img_str = $img->imageString(); } } elseif ($mime != 'image/jpeg' && !$direct_cache && $cachefile == '') { $image = @imagecreatefromstring($img_str); @@ -193,9 +192,9 @@ function proxy_init(App $a) { 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '', 'desc' => $mime); dba::insert('photo', $fields); } else { - $Image = new Image($img_str, $mime); - if ($Image->isValid() && !$direct_cache && ($cachefile == '')) { - Photo::store($Image, 0, 0, $urlhash, $_REQUEST['url'], '', 100); + $img = new Photo($img_str, $mime); + if ($img->isValid() && !$direct_cache && ($cachefile == '')) { + $img->store(0, 0, $urlhash, $_REQUEST['url'], '', 100); } } } @@ -204,10 +203,10 @@ function proxy_init(App $a) { // reduce quality - if it isn't a GIF if ($mime != 'image/gif') { - $Image = new Image($img_str, $mime); - if ($Image->isValid()) { - $Image->scaleDown($size); - $img_str = $Image->asString(); + $img = new Photo($img_str, $mime); + if ($img->isValid()) { + $img->scaleImage($size); + $img_str = $img->imageString(); } } diff --git a/mod/randprof.php b/mod/randprof.php index 40ad09271d..38d05c53e4 100644 --- a/mod/randprof.php +++ b/mod/randprof.php @@ -2,10 +2,10 @@ use Friendica\App; use Friendica\Core\System; -use Friendica\Model\GContact; +use Friendica\Model\GlobalContact; function randprof_init(App $a) { - $x = GContact::getRandomUrl(); + $x = GlobalContact::getRandomUrl(); if ($x) { goaway(zrl($x)); diff --git a/mod/settings.php b/mod/settings.php index 5f14c82835..778a1d8a77 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -9,7 +9,7 @@ use Friendica\Core\Worker; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Database\DBM; -use Friendica\Model\GContact; +use Friendica\Model\GlobalContact; use Friendica\Model\User; use Friendica\Protocol\Email; @@ -650,7 +650,7 @@ function settings_post(App $a) { Worker::add(PRIORITY_LOW, 'ProfileUpdate', local_user()); // Update the global contact for the user - GContact::updateForUser(local_user()); + GlobalContact::updateForUser(local_user()); //$_SESSION['theme'] = $theme; if ($email_changed && $a->config['register_policy'] == REGISTER_VERIFY) { diff --git a/mod/suggest.php b/mod/suggest.php index deda2b2c6c..f05c76ceda 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\GContact; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; require_once 'include/contact_widgets.php'; @@ -69,7 +69,7 @@ function suggest_content(App $a) { $a->page['aside'] .= follow_widget(); - $r = GContact::suggestionQuery(local_user()); + $r = GlobalContact::suggestionQuery(local_user()); if (! DBM::is_result($r)) { $o .= t('No suggestions available. If this is a new site, please try again in 24 hours.'); diff --git a/mod/unfollow.php b/mod/unfollow.php index 907982cd8a..3f94fb5760 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\Model\Contact; +use Friendica\Object\Contact; require_once 'include/follow.php'; require_once 'include/contact_selectors.php'; diff --git a/mod/videos.php b/mod/videos.php index bb0e0c237f..412966f862 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\Model\Contact; +use Friendica\Object\Contact; require_once('include/items.php'); require_once('include/acl_selectors.php'); diff --git a/mod/viewcontacts.php b/mod/viewcontacts.php index 1b4ff69c00..30ae92f8e3 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\Model\Contact; +use Friendica\Object\Contact; require_once('include/contact_selectors.php'); diff --git a/mod/wall_upload.php b/mod/wall_upload.php index a608743d07..ce73f85151 100644 --- a/mod/wall_upload.php +++ b/mod/wall_upload.php @@ -13,8 +13,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Database\DBM; -use Friendica\Model\Photo; -use Friendica\Object\Image; +use Friendica\Object\Photo; function wall_upload_post(App $a, $desktopmode = true) { @@ -162,8 +161,8 @@ function wall_upload_post(App $a, $desktopmode = true) { $filetype = ""; } - if ($filetype == "") { - $filetype = Image::guessType($filename); + if ($filetype=="") { + $filetype=Photo::guessImageType($filename); } // If there is a temp name, then do a manual check @@ -191,9 +190,9 @@ function wall_upload_post(App $a, $desktopmode = true) { } $imagedata = @file_get_contents($src); - $Image = new Image($imagedata, $filetype); + $ph = new Photo($imagedata, $filetype); - if (! $Image->isValid()) { + if (! $ph->isValid()) { $msg = t('Unable to process image.'); if ($r_json) { echo json_encode(array('error'=>$msg)); @@ -204,7 +203,7 @@ function wall_upload_post(App $a, $desktopmode = true) { killme(); } - $Image->orient($src); + $ph->orient($src); @unlink($src); $max_length = Config::get('system', 'max_image_length'); @@ -212,12 +211,12 @@ function wall_upload_post(App $a, $desktopmode = true) { $max_length = MAX_IMAGE_LENGTH; } if ($max_length > 0) { - $Image->scaleDown($max_length); + $ph->scaleImage($max_length); logger("File upload: Scaling picture to new size " . $max_length, LOGGER_DEBUG); } - $width = $Image->getWidth(); - $height = $Image->getHeight(); + $width = $ph->getWidth(); + $height = $ph->getHeight(); $hash = photo_new_resource(); @@ -230,7 +229,7 @@ function wall_upload_post(App $a, $desktopmode = true) { $defperm = '<' . $default_cid . '>'; - $r = Photo::store($Image, $page_owner_uid, $visitor, $hash, $filename, $album, 0, 0, $defperm); + $r = $ph->store($page_owner_uid, $visitor, $hash, $filename, $album, 0, 0, $defperm); if (! $r) { $msg = t('Image upload failed.'); @@ -243,16 +242,16 @@ function wall_upload_post(App $a, $desktopmode = true) { } if ($width > 640 || $height > 640) { - $Image->scaleDown(640); - $r = Photo::store($Image, $page_owner_uid, $visitor, $hash, $filename, $album, 1, 0, $defperm); + $ph->scaleImage(640); + $r = $ph->store($page_owner_uid, $visitor, $hash, $filename, $album, 1, 0, $defperm); if ($r) { $smallest = 1; } } if ($width > 320 || $height > 320) { - $Image->scaleDown(320); - $r = Photo::store($Image, $page_owner_uid, $visitor, $hash, $filename, $album, 2, 0, $defperm); + $ph->scaleImage(320); + $r = $ph->store($page_owner_uid, $visitor, $hash, $filename, $album, 2, 0, $defperm); if ($r && ($smallest == 0)) { $smallest = 2; } @@ -281,8 +280,8 @@ function wall_upload_post(App $a, $desktopmode = true) { $picture["height"] = $r[0]["height"]; $picture["type"] = $r[0]["type"]; $picture["albumpage"] = System::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $hash; - $picture["picture"] = System::baseUrl() . "/photo/{$hash}-0." . $Image->getExt(); - $picture["preview"] = System::baseUrl() . "/photo/{$hash}-{$smallest}." . $Image->getExt(); + $picture["picture"] = System::baseUrl() . "/photo/{$hash}-0." . $ph->getExt(); + $picture["preview"] = System::baseUrl() . "/photo/{$hash}-{$smallest}." . $ph->getExt(); if ($r_json) { echo json_encode(array('picture'=>$picture)); @@ -300,9 +299,9 @@ function wall_upload_post(App $a, $desktopmode = true) { /* mod Waitman Gobble NO WARRANTY */ // if we get the signal then return the image url info in BBCODE if ($_REQUEST['hush']!='yeah') { - echo "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $hash . '][img]' . System::baseUrl() . "/photo/{$hash}-{$smallest}.".$Image->getExt()."[/img][/url]\n\n"; + echo "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $hash . '][img]' . System::baseUrl() . "/photo/{$hash}-{$smallest}.".$ph->getExt()."[/img][/url]\n\n"; } else { - $m = '[url='.System::baseUrl().'/photos/'.$page_owner_nick.'/image/'.$hash.'][img]'.System::baseUrl()."/photo/{$hash}-{$smallest}.".$Image->getExt()."[/img][/url]"; + $m = '[url='.System::baseUrl().'/photos/'.$page_owner_nick.'/image/'.$hash.'][img]'.System::baseUrl()."/photo/{$hash}-{$smallest}.".$ph->getExt()."[/img][/url]"; return($m); } /* mod Waitman Gobble NO WARRANTY */ diff --git a/src/Core/NotificationsManager.php b/src/Core/NotificationsManager.php index 9adac10c92..42d514e618 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\Model\Contact; +use Friendica\Object\Contact; require_once 'include/html2plain.php'; require_once 'include/datetime.php'; diff --git a/src/Model/Contact.php b/src/Model/Contact.php deleted file mode 100644 index 3708603ba3..0000000000 --- a/src/Model/Contact.php +++ /dev/null @@ -1,947 +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 = 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/GContact.php b/src/Model/GContact.php deleted file mode 100644 index 1b846b3171..0000000000 --- a/src/Model/GContact.php +++ /dev/null @@ -1,1076 +0,0 @@ - 0 OR (NOT `gcontact`.`hide` AND `gcontact`.`network` IN ('%s', '%s', '%s') AND - ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR - (`gcontact`.`updated` >= `gcontact`.`last_failure`)))) AND - (`gcontact`.`addr` LIKE '%s' OR `gcontact`.`name` LIKE '%s' OR `gcontact`.`nick` LIKE '%s') $extra_sql - GROUP BY `gcontact`.`nurl` - ORDER BY `gcontact`.`nurl` DESC - LIMIT 1000", - intval(local_user()), - dbesc(CONTACT_IS_SHARING), - dbesc(CONTACT_IS_FRIEND), - dbesc(NETWORK_DFRN), - dbesc($ostatus), - dbesc($diaspora), - dbesc(escape_tags($search)), - dbesc(escape_tags($search)), - dbesc(escape_tags($search)) - ); - - return $results; - } - } - - /** - * @brief Link the gcontact entry with user, contact and global contact - * - * @param integer $gcid Global contact ID - * @param integer $uid User ID - * @param integer $cid Contact ID - * @param integer $zcid Global Contact ID - * @return void - */ - public static function link($gcid, $uid = 0, $cid = 0, $zcid = 0) - { - if ($gcid <= 0) { - return; - } - - $r = q( - "SELECT * FROM `glink` WHERE `cid` = %d AND `uid` = %d AND `gcid` = %d AND `zcid` = %d LIMIT 1", - intval($cid), - intval($uid), - intval($gcid), - intval($zcid) - ); - - if (!DBM::is_result($r)) { - q( - "INSERT INTO `glink` (`cid`, `uid`, `gcid`, `zcid`, `updated`) VALUES (%d, %d, %d, %d, '%s') ", - intval($cid), - intval($uid), - intval($gcid), - intval($zcid), - dbesc(datetime_convert()) - ); - } else { - q( - "UPDATE `glink` SET `updated` = '%s' WHERE `cid` = %d AND `uid` = %d AND `gcid` = %d AND `zcid` = %d", - dbesc(datetime_convert()), - intval($cid), - intval($uid), - intval($gcid), - intval($zcid) - ); - } - } - - /** - * @brief Sanitize the given gcontact data - * - * @param array $gcontact array with gcontact data - * @throw Exception - * - * Generation: - * 0: No definition - * 1: Profiles on this server - * 2: Contacts of profiles on this server - * 3: Contacts of contacts of profiles on this server - * 4: ... - * @return array $gcontact - */ - public static function sanitize($gcontact) - { - if ($gcontact['url'] == "") { - throw new Exception('URL is empty'); - } - - $urlparts = parse_url($gcontact['url']); - if (!isset($urlparts["scheme"])) { - throw new Exception("This (".$gcontact['url'].") doesn't seem to be an url."); - } - - if (in_array($urlparts["host"], array("www.facebook.com", "facebook.com", "twitter.com", "identi.ca", "alpha.app.net"))) { - throw new Exception('Contact from a non federated network ignored. ('.$gcontact['url'].')'); - } - - // Don't store the statusnet connector as network - // We can't simply set this to NETWORK_OSTATUS since the connector could have fetched posts from friendica as well - if ($gcontact['network'] == NETWORK_STATUSNET) { - $gcontact['network'] = ""; - } - - // Assure that there are no parameter fragments in the profile url - if (in_array($gcontact['network'], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { - $gcontact['url'] = self::cleanContactUrl($gcontact['url']); - } - - $alternate = PortableContact::alternateOStatusUrl($gcontact['url']); - - // The global contacts should contain the original picture, not the cached one - if (($gcontact['generation'] != 1) && stristr(normalise_link($gcontact['photo']), normalise_link(System::baseUrl()."/photo/"))) { - $gcontact['photo'] = ""; - } - - if (!isset($gcontact['network'])) { - $r = q( - "SELECT `network` FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s' AND `network` != '' AND `network` != '%s' LIMIT 1", - dbesc(normalise_link($gcontact['url'])), - dbesc(NETWORK_STATUSNET) - ); - if (DBM::is_result($r)) { - $gcontact['network'] = $r[0]["network"]; - } - - if (($gcontact['network'] == "") || ($gcontact['network'] == NETWORK_OSTATUS)) { - $r = q( - "SELECT `network`, `url` FROM `contact` WHERE `uid` = 0 AND `alias` IN ('%s', '%s') AND `network` != '' AND `network` != '%s' LIMIT 1", - dbesc($gcontact['url']), - dbesc(normalise_link($gcontact['url'])), - dbesc(NETWORK_STATUSNET) - ); - if (DBM::is_result($r)) { - $gcontact['network'] = $r[0]["network"]; - } - } - } - - $gcontact['server_url'] = ''; - $gcontact['network'] = ''; - - $x = q( - "SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", - dbesc(normalise_link($gcontact['url'])) - ); - - if (DBM::is_result($x)) { - if (!isset($gcontact['network']) && ($x[0]["network"] != NETWORK_STATUSNET)) { - $gcontact['network'] = $x[0]["network"]; - } - if ($gcontact['updated'] <= NULL_DATE) { - $gcontact['updated'] = $x[0]["updated"]; - } - if (!isset($gcontact['server_url']) && (normalise_link($x[0]["server_url"]) != normalise_link($x[0]["url"]))) { - $gcontact['server_url'] = $x[0]["server_url"]; - } - if (!isset($gcontact['addr'])) { - $gcontact['addr'] = $x[0]["addr"]; - } - } - - if ((!isset($gcontact['network']) || !isset($gcontact['name']) || !isset($gcontact['addr']) || !isset($gcontact['photo']) || !isset($gcontact['server_url']) || $alternate) - && PortableContact::reachable($gcontact['url'], $gcontact['server_url'], $gcontact['network'], false) - ) { - $data = Probe::uri($gcontact['url']); - - if ($data["network"] == NETWORK_PHANTOM) { - throw new Exception('Probing for URL '.$gcontact['url'].' failed'); - } - - $orig_profile = $gcontact['url']; - - $gcontact["server_url"] = $data["baseurl"]; - - $gcontact = array_merge($gcontact, $data); - - if ($alternate && ($gcontact['network'] == NETWORK_OSTATUS)) { - // Delete the old entry - if it exists - $r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile))); - if (DBM::is_result($r)) { - q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile))); - q("DELETE FROM `glink` WHERE `gcid` = %d", intval($r[0]["id"])); - } - } - } - - if (!isset($gcontact['name']) || !isset($gcontact['photo'])) { - throw new Exception('No name and photo for URL '.$gcontact['url']); - } - - if (!in_array($gcontact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA))) { - throw new Exception('No federated network ('.$gcontact['network'].') detected for URL '.$gcontact['url']); - } - - if (!isset($gcontact['server_url'])) { - // We check the server url to be sure that it is a real one - $server_url = PortableContact::detectServer($gcontact['url']); - - // We are now sure that it is a correct URL. So we use it in the future - if ($server_url != "") { - $gcontact['server_url'] = $server_url; - } - } - - // The server URL doesn't seem to be valid, so we don't store it. - if (!PortableContact::checkServer($gcontact['server_url'], $gcontact['network'])) { - $gcontact['server_url'] = ""; - } - - return $gcontact; - } - - /** - * @param integer $uid id - * @param integer $cid id - * @return integer - */ - public static function countCommonFriends($uid, $cid) - { - $r = q( - "SELECT count(*) as `total` - FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND - ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR - (`gcontact`.`updated` >= `gcontact`.`last_failure`)) - AND `gcontact`.`nurl` IN (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 and id != %d ) ", - intval($cid), - intval($uid), - intval($uid), - intval($cid) - ); - - // logger("countCommonFriends: $uid $cid {$r[0]['total']}"); - if (DBM::is_result($r)) { - return $r[0]['total']; - } - return 0; - } - - /** - * @param integer $uid id - * @param integer $zcid zcid - * @return integer - */ - public static function countCommonFriendsZcid($uid, $zcid) - { - $r = q( - "SELECT count(*) as `total` - FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - where `glink`.`zcid` = %d - and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 ) ", - intval($zcid), - intval($uid) - ); - - if (DBM::is_result($r)) { - return $r[0]['total']; - } - - return 0; - } - - /** - * @param object $uid user - * @param object $cid cid - * @param integer $start optional, default 0 - * @param integer $limit optional, default 9999 - * @param boolean $shuffle optional, default false - * @return object - */ - public static function commonFriends($uid, $cid, $start = 0, $limit = 9999, $shuffle = false) - { - if ($shuffle) { - $sql_extra = " order by rand() "; - } else { - $sql_extra = " order by `gcontact`.`name` asc "; - } - - $r = q( - "SELECT `gcontact`.*, `contact`.`id` AS `cid` - FROM `glink` - INNER JOIN `gcontact` ON `glink`.`gcid` = `gcontact`.`id` - INNER JOIN `contact` ON `gcontact`.`nurl` = `contact`.`nurl` - WHERE `glink`.`cid` = %d and `glink`.`uid` = %d - AND `contact`.`uid` = %d AND `contact`.`self` = 0 AND `contact`.`blocked` = 0 - AND `contact`.`hidden` = 0 AND `contact`.`id` != %d - AND ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)) - $sql_extra LIMIT %d, %d", - intval($cid), - intval($uid), - intval($uid), - intval($cid), - intval($start), - intval($limit) - ); - - /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() - return $r; - } - - /** - * @param object $uid user - * @param object $zcid zcid - * @param integer $start optional, default 0 - * @param integer $limit optional, default 9999 - * @param boolean $shuffle optional, default false - * @return object - */ - public static function commonFriendsZcid($uid, $zcid, $start = 0, $limit = 9999, $shuffle = false) - { - if ($shuffle) { - $sql_extra = " order by rand() "; - } else { - $sql_extra = " order by `gcontact`.`name` asc "; - } - - $r = q( - "SELECT `gcontact`.* - FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - where `glink`.`zcid` = %d - and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 ) - $sql_extra limit %d, %d", - intval($zcid), - intval($uid), - intval($start), - intval($limit) - ); - - /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() - return $r; - } - - /** - * @param object $uid user - * @param object $cid cid - * @return integer - */ - public static function countAllFriends($uid, $cid) - { - $r = q( - "SELECT count(*) as `total` - FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - where `glink`.`cid` = %d and `glink`.`uid` = %d AND - ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))", - intval($cid), - intval($uid) - ); - - if (DBM::is_result($r)) { - return $r[0]['total']; - } - - return 0; - } - - /** - * @param object $uid user - * @param object $cid cid - * @param integer $start optional, default 0 - * @param integer $limit optional, default 80 - * @return object - */ - public static function allFriends($uid, $cid, $start = 0, $limit = 80) - { - $r = q( - "SELECT `gcontact`.*, `contact`.`id` AS `cid` - FROM `glink` - INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl` AND `contact`.`uid` = %d - WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND - ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)) - ORDER BY `gcontact`.`name` ASC LIMIT %d, %d ", - intval($uid), - intval($cid), - intval($uid), - intval($start), - intval($limit) - ); - - /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() - return $r; - } - - /** - * @param object $uid user - * @param integer $start optional, default 0 - * @param integer $limit optional, default 80 - * @return array - */ - public static function suggestionQuery($uid, $start = 0, $limit = 80) - { - if (!$uid) { - return array(); - } - - /* - * Uncommented because the result of the queries are to big to store it in the cache. - * We need to decide if we want to change the db column type or if we want to delete it. - */ - //$list = Cache::get("suggestion_query:".$uid.":".$start.":".$limit); - //if (!is_null($list)) { - // return $list; - //} - - $network = array(NETWORK_DFRN); - - if (Config::get('system', 'diaspora_enabled')) { - $network[] = NETWORK_DIASPORA; - } - - if (!Config::get('system', 'ostatus_disabled')) { - $network[] = NETWORK_OSTATUS; - } - - $sql_network = implode("', '", $network); - $sql_network = "'".$sql_network."'"; - - /// @todo This query is really slow - // By now we cache the data for five minutes - $r = q( - "SELECT count(glink.gcid) as `total`, gcontact.* from gcontact - INNER JOIN `glink` ON `glink`.`gcid` = `gcontact`.`id` - where uid = %d and not gcontact.nurl in ( select nurl from contact where uid = %d ) - AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d) - AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d) - AND `gcontact`.`updated` >= '%s' - AND `gcontact`.`last_contact` >= `gcontact`.`last_failure` - AND `gcontact`.`network` IN (%s) - GROUP BY `glink`.`gcid` ORDER BY `gcontact`.`updated` DESC,`total` DESC LIMIT %d, %d", - intval($uid), - intval($uid), - intval($uid), - intval($uid), - dbesc(NULL_DATE), - $sql_network, - intval($start), - intval($limit) - ); - - if (DBM::is_result($r) && count($r) >= ($limit -1)) { - /* - * Uncommented because the result of the queries are to big to store it in the cache. - * We need to decide if we want to change the db column type or if we want to delete it. - */ - //Cache::set("suggestion_query:".$uid.":".$start.":".$limit, $r, CACHE_FIVE_MINUTES); - - return $r; - } - - $r2 = q( - "SELECT gcontact.* FROM gcontact - INNER JOIN `glink` ON `glink`.`gcid` = `gcontact`.`id` - WHERE `glink`.`uid` = 0 AND `glink`.`cid` = 0 AND `glink`.`zcid` = 0 AND NOT `gcontact`.`nurl` IN (SELECT `nurl` FROM `contact` WHERE `uid` = %d) - AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d) - AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d) - AND `gcontact`.`updated` >= '%s' - AND `gcontact`.`last_contact` >= `gcontact`.`last_failure` - AND `gcontact`.`network` IN (%s) - ORDER BY rand() LIMIT %d, %d", - intval($uid), - intval($uid), - intval($uid), - dbesc(NULL_DATE), - $sql_network, - intval($start), - intval($limit) - ); - - $list = array(); - foreach ($r2 as $suggestion) { - $list[$suggestion["nurl"]] = $suggestion; - } - - foreach ($r as $suggestion) { - $list[$suggestion["nurl"]] = $suggestion; - } - - while (sizeof($list) > ($limit)) { - array_pop($list); - } - - /* - * Uncommented because the result of the queries are to big to store it in the cache. - * We need to decide if we want to change the db column type or if we want to delete it. - */ - //Cache::set("suggestion_query:".$uid.":".$start.":".$limit, $list, CACHE_FIVE_MINUTES); - return $list; - } - - /** - * @return void - */ - public static function updateSuggestions() - { - $a = get_app(); - - $done = array(); - - /// @TODO Check if it is really neccessary to poll the own server - PortableContact::loadWorker(0, 0, 0, System::baseUrl() . '/poco'); - - $done[] = System::baseUrl() . '/poco'; - - if (strlen(Config::get('system', 'directory'))) { - $x = fetch_url(get_server()."/pubsites"); - if ($x) { - $j = json_decode($x); - if ($j->entries) { - foreach ($j->entries as $entry) { - PortableContact::checkServer($entry->url); - - $url = $entry->url . '/poco'; - if (! in_array($url, $done)) { - PortableContact::loadWorker(0, 0, 0, $entry->url . '/poco'); - } - } - } - } - } - - // Query your contacts from Friendica and Redmatrix/Hubzilla for their contacts - $r = q( - "SELECT DISTINCT(`poco`) AS `poco` FROM `contact` WHERE `network` IN ('%s', '%s')", - dbesc(NETWORK_DFRN), - dbesc(NETWORK_DIASPORA) - ); - - if (DBM::is_result($r)) { - foreach ($r as $rr) { - $base = substr($rr['poco'], 0, strrpos($rr['poco'], '/')); - if (! in_array($base, $done)) { - PortableContact::loadWorker(0, 0, 0, $base); - } - } - } - } - - /** - * @brief Removes unwanted parts from a contact url - * - * @param string $url Contact url - * - * @return string Contact url with the wanted parts - */ - public static function cleanContactUrl($url) - { - $parts = parse_url($url); - - if (!isset($parts["scheme"]) || !isset($parts["host"])) { - return $url; - } - - $new_url = $parts["scheme"]."://".$parts["host"]; - - if (isset($parts["port"])) { - $new_url .= ":".$parts["port"]; - } - - if (isset($parts["path"])) { - $new_url .= $parts["path"]; - } - - if ($new_url != $url) { - logger("Cleaned contact url ".$url." to ".$new_url." - Called by: ".System::callstack(), LOGGER_DEBUG); - } - - return $new_url; - } - - /** - * @brief Replace alternate OStatus user format with the primary one - * - * @param arr $contact contact array (called by reference) - * @return void - */ - public static function fixAlternateContactAddress(&$contact) - { - if (($contact["network"] == NETWORK_OSTATUS) && PortableContact::alternateOStatusUrl($contact["url"])) { - $data = Probe::uri($contact["url"]); - if ($contact["network"] == NETWORK_OSTATUS) { - logger("Fix primary url from ".$contact["url"]." to ".$data["url"]." - Called by: ".System::callstack(), LOGGER_DEBUG); - $contact["url"] = $data["url"]; - $contact["addr"] = $data["addr"]; - $contact["alias"] = $data["alias"]; - $contact["server_url"] = $data["baseurl"]; - } - } - } - - /** - * @brief Fetch the gcontact id, add an entry if not existed - * - * @param arr $contact contact array - * - * @return bool|int Returns false if not found, integer if contact was found - */ - public static function getId($contact) - { - $gcontact_id = 0; - $doprobing = false; - - if (in_array($contact["network"], array(NETWORK_PHANTOM))) { - logger("Invalid network for contact url ".$contact["url"]." - Called by: ".System::callstack(), LOGGER_DEBUG); - return false; - } - - if ($contact["network"] == NETWORK_STATUSNET) { - $contact["network"] = NETWORK_OSTATUS; - } - - // All new contacts are hidden by default - if (!isset($contact["hide"])) { - $contact["hide"] = true; - } - - // Replace alternate OStatus user format with the primary one - self::fixAlternateContactAddress($contact); - - // Remove unwanted parts from the contact url (e.g. "?zrl=...") - if (in_array($contact["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { - $contact["url"] = self::cleanContactUrl($contact["url"]); - } - - dba::lock('gcontact'); - $r = q( - "SELECT `id`, `last_contact`, `last_failure`, `network` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", - dbesc(normalise_link($contact["url"])) - ); - - if (DBM::is_result($r)) { - $gcontact_id = $r[0]["id"]; - - // Update every 90 days - if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { - $last_failure_str = $r[0]["last_failure"]; - $last_failure = strtotime($r[0]["last_failure"]); - $last_contact_str = $r[0]["last_contact"]; - $last_contact = strtotime($r[0]["last_contact"]); - $doprobing = (((time() - $last_contact) > (90 * 86400)) && ((time() - $last_failure) > (90 * 86400))); - } - } else { - q( - "INSERT INTO `gcontact` (`name`, `nick`, `addr` , `network`, `url`, `nurl`, `photo`, `created`, `updated`, `location`, `about`, `hide`, `generation`) - VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)", - dbesc($contact["name"]), - dbesc($contact["nick"]), - dbesc($contact["addr"]), - dbesc($contact["network"]), - dbesc($contact["url"]), - dbesc(normalise_link($contact["url"])), - dbesc($contact["photo"]), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($contact["location"]), - dbesc($contact["about"]), - intval($contact["hide"]), - intval($contact["generation"]) - ); - - $r = q( - "SELECT `id`, `network` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 2", - dbesc(normalise_link($contact["url"])) - ); - - if (DBM::is_result($r)) { - $gcontact_id = $r[0]["id"]; - - $doprobing = in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, "")); - } - } - dba::unlock(); - - if ($doprobing) { - logger("Last Contact: ". $last_contact_str." - Last Failure: ".$last_failure_str." - Checking: ".$contact["url"], LOGGER_DEBUG); - Worker::add(PRIORITY_LOW, 'GProbe', $contact["url"]); - } - - return $gcontact_id; - } - - /** - * @brief Updates the gcontact table from a given array - * - * @param arr $contact contact array - * - * @return bool|int Returns false if not found, integer if contact was found - */ - public static function update($contact) - { - // Check for invalid "contact-type" value - if (isset($contact['contact-type']) && (intval($contact['contact-type']) < 0)) { - $contact['contact-type'] = 0; - } - - /// @todo update contact table as well - - $gcontact_id = self::getId($contact); - - if (!$gcontact_id) { - return false; - } - - $r = q( - "SELECT `name`, `nick`, `photo`, `location`, `about`, `addr`, `generation`, `birthday`, `gender`, `keywords`, - `contact-type`, `hide`, `nsfw`, `network`, `alias`, `notify`, `server_url`, `connect`, `updated`, `url` - FROM `gcontact` WHERE `id` = %d LIMIT 1", - intval($gcontact_id) - ); - - // Get all field names - $fields = array(); - foreach ($r[0] as $field => $data) { - $fields[$field] = $data; - } - - unset($fields["url"]); - unset($fields["updated"]); - unset($fields["hide"]); - - // Bugfix: We had an error in the storing of keywords which lead to the "0" - // This value is still transmitted via poco. - if ($contact["keywords"] == "0") { - unset($contact["keywords"]); - } - - if ($r[0]["keywords"] == "0") { - $r[0]["keywords"] = ""; - } - - // assign all unassigned fields from the database entry - foreach ($fields as $field => $data) { - if (!isset($contact[$field]) || ($contact[$field] == "")) { - $contact[$field] = $r[0][$field]; - } - } - - if (!isset($contact["hide"])) { - $contact["hide"] = $r[0]["hide"]; - } - - $fields["hide"] = $r[0]["hide"]; - - if ($contact["network"] == NETWORK_STATUSNET) { - $contact["network"] = NETWORK_OSTATUS; - } - - // Replace alternate OStatus user format with the primary one - self::fixAlternateContactAddress($contact); - - if (!isset($contact["updated"])) { - $contact["updated"] = DBM::date(); - } - - if ($contact["network"] == NETWORK_TWITTER) { - $contact["server_url"] = 'http://twitter.com'; - } - - if ($contact["server_url"] == "") { - $data = Probe::uri($contact["url"]); - if ($data["network"] != NETWORK_PHANTOM) { - $contact["server_url"] = $data['baseurl']; - } - } else { - $contact["server_url"] = normalise_link($contact["server_url"]); - } - - if (($contact["addr"] == "") && ($contact["server_url"] != "") && ($contact["nick"] != "")) { - $hostname = str_replace("http://", "", $contact["server_url"]); - $contact["addr"] = $contact["nick"]."@".$hostname; - } - - // Check if any field changed - $update = false; - unset($fields["generation"]); - - if ((($contact["generation"] > 0) && ($contact["generation"] <= $r[0]["generation"])) || ($r[0]["generation"] == 0)) { - foreach ($fields as $field => $data) { - if ($contact[$field] != $r[0][$field]) { - logger("Difference for contact ".$contact["url"]." in field '".$field."'. New value: '".$contact[$field]."', old value '".$r[0][$field]."'", LOGGER_DEBUG); - $update = true; - } - } - - if ($contact["generation"] < $r[0]["generation"]) { - logger("Difference for contact ".$contact["url"]." in field 'generation'. new value: '".$contact["generation"]."', old value '".$r[0]["generation"]."'", LOGGER_DEBUG); - $update = true; - } - } - - if ($update) { - logger("Update gcontact for ".$contact["url"], LOGGER_DEBUG); - $condition = array('`nurl` = ? AND (`generation` = 0 OR `generation` >= ?)', - normalise_link($contact["url"]), $contact["generation"]); - $contact["updated"] = DBM::date($contact["updated"]); - - $updated = array('photo' => $contact['photo'], 'name' => $contact['name'], - 'nick' => $contact['nick'], 'addr' => $contact['addr'], - 'network' => $contact['network'], 'birthday' => $contact['birthday'], - 'gender' => $contact['gender'], 'keywords' => $contact['keywords'], - 'hide' => $contact['hide'], 'nsfw' => $contact['nsfw'], - 'contact-type' => $contact['contact-type'], 'alias' => $contact['alias'], - 'notify' => $contact['notify'], 'url' => $contact['url'], - 'location' => $contact['location'], 'about' => $contact['about'], - 'generation' => $contact['generation'], 'updated' => $contact['updated'], - 'server_url' => $contact['server_url'], 'connect' => $contact['connect']); - - dba::update('gcontact', $updated, $condition, $fields); - - // Now update the contact entry with the user id "0" as well. - // This is used for the shadow copies of public items. - $r = q( - "SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0 ORDER BY `id` LIMIT 1", - dbesc(normalise_link($contact["url"])) - ); - - if (DBM::is_result($r)) { - logger("Update public contact ".$r[0]["id"], LOGGER_DEBUG); - - Contact::updateAvatar($contact["photo"], 0, $r[0]["id"]); - - $fields = array('name', 'nick', 'addr', - 'network', 'bd', 'gender', - 'keywords', 'alias', 'contact-type', - 'url', 'location', 'about'); - $old_contact = dba::select('contact', $fields, array('id' => $r[0]["id"]), array('limit' => 1)); - - // Update it with the current values - $fields = array('name' => $contact['name'], 'nick' => $contact['nick'], - 'addr' => $contact['addr'], 'network' => $contact['network'], - 'bd' => $contact['birthday'], 'gender' => $contact['gender'], - 'keywords' => $contact['keywords'], 'alias' => $contact['alias'], - 'contact-type' => $contact['contact-type'], 'url' => $contact['url'], - 'location' => $contact['location'], 'about' => $contact['about']); - - dba::update('contact', $fields, array('id' => $r[0]["id"]), $old_contact); - } - } - - return $gcontact_id; - } - - /** - * @brief Updates the gcontact entry from probe - * - * @param str $url profile link - * @return void - */ - public static function updateFromProbe($url) - { - $data = Probe::uri($url); - - if (in_array($data["network"], array(NETWORK_PHANTOM))) { - logger("Invalid network for contact url ".$data["url"]." - Called by: ".System::callstack(), LOGGER_DEBUG); - return; - } - - $data["server_url"] = $data["baseurl"]; - - self::update($data); - } - - /** - * @brief Update the gcontact entry for a given user id - * - * @param int $uid User ID - * @return void - */ - public static function updateForUser($uid) - { - $r = q( - "SELECT `profile`.`locality`, `profile`.`region`, `profile`.`country-name`, - `profile`.`name`, `profile`.`about`, `profile`.`gender`, - `profile`.`pub_keywords`, `profile`.`dob`, `profile`.`photo`, - `profile`.`net-publish`, `user`.`nickname`, `user`.`hidewall`, - `contact`.`notify`, `contact`.`url`, `contact`.`addr` - FROM `profile` - INNER JOIN `user` ON `user`.`uid` = `profile`.`uid` - INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid` - WHERE `profile`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self`", - intval($uid) - ); - - $location = Profile::formatLocation( - array("locality" => $r[0]["locality"], "region" => $r[0]["region"], "country-name" => $r[0]["country-name"]) - ); - - // The "addr" field was added in 3.4.3 so it can be empty for older users - if ($r[0]["addr"] != "") { - $addr = $r[0]["nickname"].'@'.str_replace(array("http://", "https://"), "", System::baseUrl()); - } else { - $addr = $r[0]["addr"]; - } - - $gcontact = array("name" => $r[0]["name"], "location" => $location, "about" => $r[0]["about"], - "gender" => $r[0]["gender"], "keywords" => $r[0]["pub_keywords"], - "birthday" => $r[0]["dob"], "photo" => $r[0]["photo"], - "notify" => $r[0]["notify"], "url" => $r[0]["url"], - "hide" => ($r[0]["hidewall"] || !$r[0]["net-publish"]), - "nick" => $r[0]["nickname"], "addr" => $addr, - "connect" => $addr, "server_url" => System::baseUrl(), - "generation" => 1, "network" => NETWORK_DFRN); - - self::update($gcontact); - } - - /** - * @brief Fetches users of given GNU Social server - * - * If the "Statistics" plugin is enabled (See http://gstools.org/ for details) we query user data with this. - * - * @param str $server Server address - * @return void - */ - public static function fetchGsUsers($server) - { - logger("Fetching users from GNU Social server ".$server, LOGGER_DEBUG); - - $url = $server."/main/statistics"; - - $result = z_fetch_url($url); - if (!$result["success"]) { - return false; - } - - $statistics = json_decode($result["body"]); - - if (is_object($statistics->config)) { - if ($statistics->config->instance_with_ssl) { - $server = "https://"; - } else { - $server = "http://"; - } - - $server .= $statistics->config->instance_address; - - $hostname = $statistics->config->instance_address; - } else { - /// @TODO is_object() above means here no object, still $statistics is being used as object - if ($statistics->instance_with_ssl) { - $server = "https://"; - } else { - $server = "http://"; - } - - $server .= $statistics->instance_address; - - $hostname = $statistics->instance_address; - } - - if (is_object($statistics->users)) { - foreach ($statistics->users as $nick => $user) { - $profile_url = $server."/".$user->nickname; - - $contact = array("url" => $profile_url, - "name" => $user->fullname, - "addr" => $user->nickname."@".$hostname, - "nick" => $user->nickname, - "about" => $user->bio, - "network" => NETWORK_OSTATUS, - "photo" => System::baseUrl()."/images/person-175.jpg"); - self::getId($contact); - } - } - } - - /** - * @brief Asking GNU Social server on a regular base for their user data - * @return void - */ - public static function discoverGsUsers() - { - $requery_days = intval(Config::get("system", "poco_requery_days")); - - $last_update = date("c", time() - (60 * 60 * 24 * $requery_days)); - - $r = q( - "SELECT `nurl`, `url` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `network` = '%s' AND `last_poco_query` < '%s' ORDER BY RAND() LIMIT 5", - dbesc(NETWORK_OSTATUS), - dbesc($last_update) - ); - - if (!DBM::is_result($r)) { - return; - } - - foreach ($r as $server) { - self::fetchGsUsers($server["url"]); - q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"])); - } - } - - /** - * @return string - */ - public static function getRandomUrl() - { - $r = q( - "SELECT `url` FROM `gcontact` WHERE `network` = '%s' - AND `last_contact` >= `last_failure` - AND `updated` > UTC_TIMESTAMP - INTERVAL 1 MONTH - ORDER BY rand() LIMIT 1", - dbesc(NETWORK_DFRN) - ); - - if (DBM::is_result($r)) { - return dirname($r[0]['url']); - } - - return ''; - } -} diff --git a/src/Model/GlobalContact.php b/src/Model/GlobalContact.php new file mode 100644 index 0000000000..6ec1101775 --- /dev/null +++ b/src/Model/GlobalContact.php @@ -0,0 +1,1076 @@ + 0 OR (NOT `gcontact`.`hide` AND `gcontact`.`network` IN ('%s', '%s', '%s') AND + ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR + (`gcontact`.`updated` >= `gcontact`.`last_failure`)))) AND + (`gcontact`.`addr` LIKE '%s' OR `gcontact`.`name` LIKE '%s' OR `gcontact`.`nick` LIKE '%s') $extra_sql + GROUP BY `gcontact`.`nurl` + ORDER BY `gcontact`.`nurl` DESC + LIMIT 1000", + intval(local_user()), + dbesc(CONTACT_IS_SHARING), + dbesc(CONTACT_IS_FRIEND), + dbesc(NETWORK_DFRN), + dbesc($ostatus), + dbesc($diaspora), + dbesc(escape_tags($search)), + dbesc(escape_tags($search)), + dbesc(escape_tags($search)) + ); + + return $results; + } + } + + /** + * @brief Link the gcontact entry with user, contact and global contact + * + * @param integer $gcid Global contact ID + * @param integer $uid User ID + * @param integer $cid Contact ID + * @param integer $zcid Global Contact ID + * @return void + */ + public static function link($gcid, $uid = 0, $cid = 0, $zcid = 0) + { + if ($gcid <= 0) { + return; + } + + $r = q( + "SELECT * FROM `glink` WHERE `cid` = %d AND `uid` = %d AND `gcid` = %d AND `zcid` = %d LIMIT 1", + intval($cid), + intval($uid), + intval($gcid), + intval($zcid) + ); + + if (!DBM::is_result($r)) { + q( + "INSERT INTO `glink` (`cid`, `uid`, `gcid`, `zcid`, `updated`) VALUES (%d, %d, %d, %d, '%s') ", + intval($cid), + intval($uid), + intval($gcid), + intval($zcid), + dbesc(datetime_convert()) + ); + } else { + q( + "UPDATE `glink` SET `updated` = '%s' WHERE `cid` = %d AND `uid` = %d AND `gcid` = %d AND `zcid` = %d", + dbesc(datetime_convert()), + intval($cid), + intval($uid), + intval($gcid), + intval($zcid) + ); + } + } + + /** + * @brief Sanitize the given gcontact data + * + * @param array $gcontact array with gcontact data + * @throw Exception + * + * Generation: + * 0: No definition + * 1: Profiles on this server + * 2: Contacts of profiles on this server + * 3: Contacts of contacts of profiles on this server + * 4: ... + * @return array $gcontact + */ + public static function sanitize($gcontact) + { + if ($gcontact['url'] == "") { + throw new Exception('URL is empty'); + } + + $urlparts = parse_url($gcontact['url']); + if (!isset($urlparts["scheme"])) { + throw new Exception("This (".$gcontact['url'].") doesn't seem to be an url."); + } + + if (in_array($urlparts["host"], array("www.facebook.com", "facebook.com", "twitter.com", "identi.ca", "alpha.app.net"))) { + throw new Exception('Contact from a non federated network ignored. ('.$gcontact['url'].')'); + } + + // Don't store the statusnet connector as network + // We can't simply set this to NETWORK_OSTATUS since the connector could have fetched posts from friendica as well + if ($gcontact['network'] == NETWORK_STATUSNET) { + $gcontact['network'] = ""; + } + + // Assure that there are no parameter fragments in the profile url + if (in_array($gcontact['network'], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { + $gcontact['url'] = self::cleanContactUrl($gcontact['url']); + } + + $alternate = PortableContact::alternateOStatusUrl($gcontact['url']); + + // The global contacts should contain the original picture, not the cached one + if (($gcontact['generation'] != 1) && stristr(normalise_link($gcontact['photo']), normalise_link(System::baseUrl()."/photo/"))) { + $gcontact['photo'] = ""; + } + + if (!isset($gcontact['network'])) { + $r = q( + "SELECT `network` FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s' AND `network` != '' AND `network` != '%s' LIMIT 1", + dbesc(normalise_link($gcontact['url'])), + dbesc(NETWORK_STATUSNET) + ); + if (DBM::is_result($r)) { + $gcontact['network'] = $r[0]["network"]; + } + + if (($gcontact['network'] == "") || ($gcontact['network'] == NETWORK_OSTATUS)) { + $r = q( + "SELECT `network`, `url` FROM `contact` WHERE `uid` = 0 AND `alias` IN ('%s', '%s') AND `network` != '' AND `network` != '%s' LIMIT 1", + dbesc($gcontact['url']), + dbesc(normalise_link($gcontact['url'])), + dbesc(NETWORK_STATUSNET) + ); + if (DBM::is_result($r)) { + $gcontact['network'] = $r[0]["network"]; + } + } + } + + $gcontact['server_url'] = ''; + $gcontact['network'] = ''; + + $x = q( + "SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", + dbesc(normalise_link($gcontact['url'])) + ); + + if (DBM::is_result($x)) { + if (!isset($gcontact['network']) && ($x[0]["network"] != NETWORK_STATUSNET)) { + $gcontact['network'] = $x[0]["network"]; + } + if ($gcontact['updated'] <= NULL_DATE) { + $gcontact['updated'] = $x[0]["updated"]; + } + if (!isset($gcontact['server_url']) && (normalise_link($x[0]["server_url"]) != normalise_link($x[0]["url"]))) { + $gcontact['server_url'] = $x[0]["server_url"]; + } + if (!isset($gcontact['addr'])) { + $gcontact['addr'] = $x[0]["addr"]; + } + } + + if ((!isset($gcontact['network']) || !isset($gcontact['name']) || !isset($gcontact['addr']) || !isset($gcontact['photo']) || !isset($gcontact['server_url']) || $alternate) + && PortableContact::reachable($gcontact['url'], $gcontact['server_url'], $gcontact['network'], false) + ) { + $data = Probe::uri($gcontact['url']); + + if ($data["network"] == NETWORK_PHANTOM) { + throw new Exception('Probing for URL '.$gcontact['url'].' failed'); + } + + $orig_profile = $gcontact['url']; + + $gcontact["server_url"] = $data["baseurl"]; + + $gcontact = array_merge($gcontact, $data); + + if ($alternate && ($gcontact['network'] == NETWORK_OSTATUS)) { + // Delete the old entry - if it exists + $r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile))); + if (DBM::is_result($r)) { + q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile))); + q("DELETE FROM `glink` WHERE `gcid` = %d", intval($r[0]["id"])); + } + } + } + + if (!isset($gcontact['name']) || !isset($gcontact['photo'])) { + throw new Exception('No name and photo for URL '.$gcontact['url']); + } + + if (!in_array($gcontact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA))) { + throw new Exception('No federated network ('.$gcontact['network'].') detected for URL '.$gcontact['url']); + } + + if (!isset($gcontact['server_url'])) { + // We check the server url to be sure that it is a real one + $server_url = PortableContact::detectServer($gcontact['url']); + + // We are now sure that it is a correct URL. So we use it in the future + if ($server_url != "") { + $gcontact['server_url'] = $server_url; + } + } + + // The server URL doesn't seem to be valid, so we don't store it. + if (!PortableContact::checkServer($gcontact['server_url'], $gcontact['network'])) { + $gcontact['server_url'] = ""; + } + + return $gcontact; + } + + /** + * @param integer $uid id + * @param integer $cid id + * @return integer + */ + public static function countCommonFriends($uid, $cid) + { + $r = q( + "SELECT count(*) as `total` + FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` + WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND + ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR + (`gcontact`.`updated` >= `gcontact`.`last_failure`)) + AND `gcontact`.`nurl` IN (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 and id != %d ) ", + intval($cid), + intval($uid), + intval($uid), + intval($cid) + ); + + // logger("countCommonFriends: $uid $cid {$r[0]['total']}"); + if (DBM::is_result($r)) { + return $r[0]['total']; + } + return 0; + } + + /** + * @param integer $uid id + * @param integer $zcid zcid + * @return integer + */ + public static function countCommonFriendsZcid($uid, $zcid) + { + $r = q( + "SELECT count(*) as `total` + FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` + where `glink`.`zcid` = %d + and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 ) ", + intval($zcid), + intval($uid) + ); + + if (DBM::is_result($r)) { + return $r[0]['total']; + } + + return 0; + } + + /** + * @param object $uid user + * @param object $cid cid + * @param integer $start optional, default 0 + * @param integer $limit optional, default 9999 + * @param boolean $shuffle optional, default false + * @return object + */ + public static function commonFriends($uid, $cid, $start = 0, $limit = 9999, $shuffle = false) + { + if ($shuffle) { + $sql_extra = " order by rand() "; + } else { + $sql_extra = " order by `gcontact`.`name` asc "; + } + + $r = q( + "SELECT `gcontact`.*, `contact`.`id` AS `cid` + FROM `glink` + INNER JOIN `gcontact` ON `glink`.`gcid` = `gcontact`.`id` + INNER JOIN `contact` ON `gcontact`.`nurl` = `contact`.`nurl` + WHERE `glink`.`cid` = %d and `glink`.`uid` = %d + AND `contact`.`uid` = %d AND `contact`.`self` = 0 AND `contact`.`blocked` = 0 + AND `contact`.`hidden` = 0 AND `contact`.`id` != %d + AND ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)) + $sql_extra LIMIT %d, %d", + intval($cid), + intval($uid), + intval($uid), + intval($cid), + intval($start), + intval($limit) + ); + + /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() + return $r; + } + + /** + * @param object $uid user + * @param object $zcid zcid + * @param integer $start optional, default 0 + * @param integer $limit optional, default 9999 + * @param boolean $shuffle optional, default false + * @return object + */ + public static function commonFriendsZcid($uid, $zcid, $start = 0, $limit = 9999, $shuffle = false) + { + if ($shuffle) { + $sql_extra = " order by rand() "; + } else { + $sql_extra = " order by `gcontact`.`name` asc "; + } + + $r = q( + "SELECT `gcontact`.* + FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` + where `glink`.`zcid` = %d + and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 ) + $sql_extra limit %d, %d", + intval($zcid), + intval($uid), + intval($start), + intval($limit) + ); + + /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() + return $r; + } + + /** + * @param object $uid user + * @param object $cid cid + * @return integer + */ + public static function countAllFriends($uid, $cid) + { + $r = q( + "SELECT count(*) as `total` + FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` + where `glink`.`cid` = %d and `glink`.`uid` = %d AND + ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))", + intval($cid), + intval($uid) + ); + + if (DBM::is_result($r)) { + return $r[0]['total']; + } + + return 0; + } + + /** + * @param object $uid user + * @param object $cid cid + * @param integer $start optional, default 0 + * @param integer $limit optional, default 80 + * @return object + */ + public static function allFriends($uid, $cid, $start = 0, $limit = 80) + { + $r = q( + "SELECT `gcontact`.*, `contact`.`id` AS `cid` + FROM `glink` + INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` + LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl` AND `contact`.`uid` = %d + WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND + ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)) + ORDER BY `gcontact`.`name` ASC LIMIT %d, %d ", + intval($uid), + intval($cid), + intval($uid), + intval($start), + intval($limit) + ); + + /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() + return $r; + } + + /** + * @param object $uid user + * @param integer $start optional, default 0 + * @param integer $limit optional, default 80 + * @return array + */ + public static function suggestionQuery($uid, $start = 0, $limit = 80) + { + if (!$uid) { + return array(); + } + + /* + * Uncommented because the result of the queries are to big to store it in the cache. + * We need to decide if we want to change the db column type or if we want to delete it. + */ + //$list = Cache::get("suggestion_query:".$uid.":".$start.":".$limit); + //if (!is_null($list)) { + // return $list; + //} + + $network = array(NETWORK_DFRN); + + if (Config::get('system', 'diaspora_enabled')) { + $network[] = NETWORK_DIASPORA; + } + + if (!Config::get('system', 'ostatus_disabled')) { + $network[] = NETWORK_OSTATUS; + } + + $sql_network = implode("', '", $network); + $sql_network = "'".$sql_network."'"; + + /// @todo This query is really slow + // By now we cache the data for five minutes + $r = q( + "SELECT count(glink.gcid) as `total`, gcontact.* from gcontact + INNER JOIN `glink` ON `glink`.`gcid` = `gcontact`.`id` + where uid = %d and not gcontact.nurl in ( select nurl from contact where uid = %d ) + AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d) + AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d) + AND `gcontact`.`updated` >= '%s' + AND `gcontact`.`last_contact` >= `gcontact`.`last_failure` + AND `gcontact`.`network` IN (%s) + GROUP BY `glink`.`gcid` ORDER BY `gcontact`.`updated` DESC,`total` DESC LIMIT %d, %d", + intval($uid), + intval($uid), + intval($uid), + intval($uid), + dbesc(NULL_DATE), + $sql_network, + intval($start), + intval($limit) + ); + + if (DBM::is_result($r) && count($r) >= ($limit -1)) { + /* + * Uncommented because the result of the queries are to big to store it in the cache. + * We need to decide if we want to change the db column type or if we want to delete it. + */ + //Cache::set("suggestion_query:".$uid.":".$start.":".$limit, $r, CACHE_FIVE_MINUTES); + + return $r; + } + + $r2 = q( + "SELECT gcontact.* FROM gcontact + INNER JOIN `glink` ON `glink`.`gcid` = `gcontact`.`id` + WHERE `glink`.`uid` = 0 AND `glink`.`cid` = 0 AND `glink`.`zcid` = 0 AND NOT `gcontact`.`nurl` IN (SELECT `nurl` FROM `contact` WHERE `uid` = %d) + AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d) + AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d) + AND `gcontact`.`updated` >= '%s' + AND `gcontact`.`last_contact` >= `gcontact`.`last_failure` + AND `gcontact`.`network` IN (%s) + ORDER BY rand() LIMIT %d, %d", + intval($uid), + intval($uid), + intval($uid), + dbesc(NULL_DATE), + $sql_network, + intval($start), + intval($limit) + ); + + $list = array(); + foreach ($r2 as $suggestion) { + $list[$suggestion["nurl"]] = $suggestion; + } + + foreach ($r as $suggestion) { + $list[$suggestion["nurl"]] = $suggestion; + } + + while (sizeof($list) > ($limit)) { + array_pop($list); + } + + /* + * Uncommented because the result of the queries are to big to store it in the cache. + * We need to decide if we want to change the db column type or if we want to delete it. + */ + //Cache::set("suggestion_query:".$uid.":".$start.":".$limit, $list, CACHE_FIVE_MINUTES); + return $list; + } + + /** + * @return void + */ + public static function updateSuggestions() + { + $a = get_app(); + + $done = array(); + + /// @TODO Check if it is really neccessary to poll the own server + PortableContact::loadWorker(0, 0, 0, System::baseUrl() . '/poco'); + + $done[] = System::baseUrl() . '/poco'; + + if (strlen(Config::get('system', 'directory'))) { + $x = fetch_url(get_server()."/pubsites"); + if ($x) { + $j = json_decode($x); + if ($j->entries) { + foreach ($j->entries as $entry) { + PortableContact::checkServer($entry->url); + + $url = $entry->url . '/poco'; + if (! in_array($url, $done)) { + PortableContact::loadWorker(0, 0, 0, $entry->url . '/poco'); + } + } + } + } + } + + // Query your contacts from Friendica and Redmatrix/Hubzilla for their contacts + $r = q( + "SELECT DISTINCT(`poco`) AS `poco` FROM `contact` WHERE `network` IN ('%s', '%s')", + dbesc(NETWORK_DFRN), + dbesc(NETWORK_DIASPORA) + ); + + if (DBM::is_result($r)) { + foreach ($r as $rr) { + $base = substr($rr['poco'], 0, strrpos($rr['poco'], '/')); + if (! in_array($base, $done)) { + PortableContact::loadWorker(0, 0, 0, $base); + } + } + } + } + + /** + * @brief Removes unwanted parts from a contact url + * + * @param string $url Contact url + * + * @return string Contact url with the wanted parts + */ + public static function cleanContactUrl($url) + { + $parts = parse_url($url); + + if (!isset($parts["scheme"]) || !isset($parts["host"])) { + return $url; + } + + $new_url = $parts["scheme"]."://".$parts["host"]; + + if (isset($parts["port"])) { + $new_url .= ":".$parts["port"]; + } + + if (isset($parts["path"])) { + $new_url .= $parts["path"]; + } + + if ($new_url != $url) { + logger("Cleaned contact url ".$url." to ".$new_url." - Called by: ".System::callstack(), LOGGER_DEBUG); + } + + return $new_url; + } + + /** + * @brief Replace alternate OStatus user format with the primary one + * + * @param arr $contact contact array (called by reference) + * @return void + */ + public static function fixAlternateContactAddress(&$contact) + { + if (($contact["network"] == NETWORK_OSTATUS) && PortableContact::alternateOStatusUrl($contact["url"])) { + $data = Probe::uri($contact["url"]); + if ($contact["network"] == NETWORK_OSTATUS) { + logger("Fix primary url from ".$contact["url"]." to ".$data["url"]." - Called by: ".System::callstack(), LOGGER_DEBUG); + $contact["url"] = $data["url"]; + $contact["addr"] = $data["addr"]; + $contact["alias"] = $data["alias"]; + $contact["server_url"] = $data["baseurl"]; + } + } + } + + /** + * @brief Fetch the gcontact id, add an entry if not existed + * + * @param arr $contact contact array + * + * @return bool|int Returns false if not found, integer if contact was found + */ + public static function getId($contact) + { + $gcontact_id = 0; + $doprobing = false; + + if (in_array($contact["network"], array(NETWORK_PHANTOM))) { + logger("Invalid network for contact url ".$contact["url"]." - Called by: ".System::callstack(), LOGGER_DEBUG); + return false; + } + + if ($contact["network"] == NETWORK_STATUSNET) { + $contact["network"] = NETWORK_OSTATUS; + } + + // All new contacts are hidden by default + if (!isset($contact["hide"])) { + $contact["hide"] = true; + } + + // Replace alternate OStatus user format with the primary one + self::fixAlternateContactAddress($contact); + + // Remove unwanted parts from the contact url (e.g. "?zrl=...") + if (in_array($contact["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { + $contact["url"] = self::cleanContactUrl($contact["url"]); + } + + dba::lock('gcontact'); + $r = q( + "SELECT `id`, `last_contact`, `last_failure`, `network` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", + dbesc(normalise_link($contact["url"])) + ); + + if (DBM::is_result($r)) { + $gcontact_id = $r[0]["id"]; + + // Update every 90 days + if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { + $last_failure_str = $r[0]["last_failure"]; + $last_failure = strtotime($r[0]["last_failure"]); + $last_contact_str = $r[0]["last_contact"]; + $last_contact = strtotime($r[0]["last_contact"]); + $doprobing = (((time() - $last_contact) > (90 * 86400)) && ((time() - $last_failure) > (90 * 86400))); + } + } else { + q( + "INSERT INTO `gcontact` (`name`, `nick`, `addr` , `network`, `url`, `nurl`, `photo`, `created`, `updated`, `location`, `about`, `hide`, `generation`) + VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)", + dbesc($contact["name"]), + dbesc($contact["nick"]), + dbesc($contact["addr"]), + dbesc($contact["network"]), + dbesc($contact["url"]), + dbesc(normalise_link($contact["url"])), + dbesc($contact["photo"]), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc($contact["location"]), + dbesc($contact["about"]), + intval($contact["hide"]), + intval($contact["generation"]) + ); + + $r = q( + "SELECT `id`, `network` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 2", + dbesc(normalise_link($contact["url"])) + ); + + if (DBM::is_result($r)) { + $gcontact_id = $r[0]["id"]; + + $doprobing = in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, "")); + } + } + dba::unlock(); + + if ($doprobing) { + logger("Last Contact: ". $last_contact_str." - Last Failure: ".$last_failure_str." - Checking: ".$contact["url"], LOGGER_DEBUG); + Worker::add(PRIORITY_LOW, 'GProbe', $contact["url"]); + } + + return $gcontact_id; + } + + /** + * @brief Updates the gcontact table from a given array + * + * @param arr $contact contact array + * + * @return bool|int Returns false if not found, integer if contact was found + */ + public static function update($contact) + { + // Check for invalid "contact-type" value + if (isset($contact['contact-type']) && (intval($contact['contact-type']) < 0)) { + $contact['contact-type'] = 0; + } + + /// @todo update contact table as well + + $gcontact_id = self::getId($contact); + + if (!$gcontact_id) { + return false; + } + + $r = q( + "SELECT `name`, `nick`, `photo`, `location`, `about`, `addr`, `generation`, `birthday`, `gender`, `keywords`, + `contact-type`, `hide`, `nsfw`, `network`, `alias`, `notify`, `server_url`, `connect`, `updated`, `url` + FROM `gcontact` WHERE `id` = %d LIMIT 1", + intval($gcontact_id) + ); + + // Get all field names + $fields = array(); + foreach ($r[0] as $field => $data) { + $fields[$field] = $data; + } + + unset($fields["url"]); + unset($fields["updated"]); + unset($fields["hide"]); + + // Bugfix: We had an error in the storing of keywords which lead to the "0" + // This value is still transmitted via poco. + if ($contact["keywords"] == "0") { + unset($contact["keywords"]); + } + + if ($r[0]["keywords"] == "0") { + $r[0]["keywords"] = ""; + } + + // assign all unassigned fields from the database entry + foreach ($fields as $field => $data) { + if (!isset($contact[$field]) || ($contact[$field] == "")) { + $contact[$field] = $r[0][$field]; + } + } + + if (!isset($contact["hide"])) { + $contact["hide"] = $r[0]["hide"]; + } + + $fields["hide"] = $r[0]["hide"]; + + if ($contact["network"] == NETWORK_STATUSNET) { + $contact["network"] = NETWORK_OSTATUS; + } + + // Replace alternate OStatus user format with the primary one + self::fixAlternateContactAddress($contact); + + if (!isset($contact["updated"])) { + $contact["updated"] = DBM::date(); + } + + if ($contact["network"] == NETWORK_TWITTER) { + $contact["server_url"] = 'http://twitter.com'; + } + + if ($contact["server_url"] == "") { + $data = Probe::uri($contact["url"]); + if ($data["network"] != NETWORK_PHANTOM) { + $contact["server_url"] = $data['baseurl']; + } + } else { + $contact["server_url"] = normalise_link($contact["server_url"]); + } + + if (($contact["addr"] == "") && ($contact["server_url"] != "") && ($contact["nick"] != "")) { + $hostname = str_replace("http://", "", $contact["server_url"]); + $contact["addr"] = $contact["nick"]."@".$hostname; + } + + // Check if any field changed + $update = false; + unset($fields["generation"]); + + if ((($contact["generation"] > 0) && ($contact["generation"] <= $r[0]["generation"])) || ($r[0]["generation"] == 0)) { + foreach ($fields as $field => $data) { + if ($contact[$field] != $r[0][$field]) { + logger("Difference for contact ".$contact["url"]." in field '".$field."'. New value: '".$contact[$field]."', old value '".$r[0][$field]."'", LOGGER_DEBUG); + $update = true; + } + } + + if ($contact["generation"] < $r[0]["generation"]) { + logger("Difference for contact ".$contact["url"]." in field 'generation'. new value: '".$contact["generation"]."', old value '".$r[0]["generation"]."'", LOGGER_DEBUG); + $update = true; + } + } + + if ($update) { + logger("Update gcontact for ".$contact["url"], LOGGER_DEBUG); + $condition = array('`nurl` = ? AND (`generation` = 0 OR `generation` >= ?)', + normalise_link($contact["url"]), $contact["generation"]); + $contact["updated"] = DBM::date($contact["updated"]); + + $updated = array('photo' => $contact['photo'], 'name' => $contact['name'], + 'nick' => $contact['nick'], 'addr' => $contact['addr'], + 'network' => $contact['network'], 'birthday' => $contact['birthday'], + 'gender' => $contact['gender'], 'keywords' => $contact['keywords'], + 'hide' => $contact['hide'], 'nsfw' => $contact['nsfw'], + 'contact-type' => $contact['contact-type'], 'alias' => $contact['alias'], + 'notify' => $contact['notify'], 'url' => $contact['url'], + 'location' => $contact['location'], 'about' => $contact['about'], + 'generation' => $contact['generation'], 'updated' => $contact['updated'], + 'server_url' => $contact['server_url'], 'connect' => $contact['connect']); + + dba::update('gcontact', $updated, $condition, $fields); + + // Now update the contact entry with the user id "0" as well. + // This is used for the shadow copies of public items. + $r = q( + "SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0 ORDER BY `id` LIMIT 1", + dbesc(normalise_link($contact["url"])) + ); + + if (DBM::is_result($r)) { + logger("Update public contact ".$r[0]["id"], LOGGER_DEBUG); + + Contact::updateAvatar($contact["photo"], 0, $r[0]["id"]); + + $fields = array('name', 'nick', 'addr', + 'network', 'bd', 'gender', + 'keywords', 'alias', 'contact-type', + 'url', 'location', 'about'); + $old_contact = dba::select('contact', $fields, array('id' => $r[0]["id"]), array('limit' => 1)); + + // Update it with the current values + $fields = array('name' => $contact['name'], 'nick' => $contact['nick'], + 'addr' => $contact['addr'], 'network' => $contact['network'], + 'bd' => $contact['birthday'], 'gender' => $contact['gender'], + 'keywords' => $contact['keywords'], 'alias' => $contact['alias'], + 'contact-type' => $contact['contact-type'], 'url' => $contact['url'], + 'location' => $contact['location'], 'about' => $contact['about']); + + dba::update('contact', $fields, array('id' => $r[0]["id"]), $old_contact); + } + } + + return $gcontact_id; + } + + /** + * @brief Updates the gcontact entry from probe + * + * @param str $url profile link + * @return void + */ + public static function updateFromProbe($url) + { + $data = Probe::uri($url); + + if (in_array($data["network"], array(NETWORK_PHANTOM))) { + logger("Invalid network for contact url ".$data["url"]." - Called by: ".System::callstack(), LOGGER_DEBUG); + return; + } + + $data["server_url"] = $data["baseurl"]; + + self::update($data); + } + + /** + * @brief Update the gcontact entry for a given user id + * + * @param int $uid User ID + * @return void + */ + public static function updateForUser($uid) + { + $r = q( + "SELECT `profile`.`locality`, `profile`.`region`, `profile`.`country-name`, + `profile`.`name`, `profile`.`about`, `profile`.`gender`, + `profile`.`pub_keywords`, `profile`.`dob`, `profile`.`photo`, + `profile`.`net-publish`, `user`.`nickname`, `user`.`hidewall`, + `contact`.`notify`, `contact`.`url`, `contact`.`addr` + FROM `profile` + INNER JOIN `user` ON `user`.`uid` = `profile`.`uid` + INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid` + WHERE `profile`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self`", + intval($uid) + ); + + $location = Profile::formatLocation( + array("locality" => $r[0]["locality"], "region" => $r[0]["region"], "country-name" => $r[0]["country-name"]) + ); + + // The "addr" field was added in 3.4.3 so it can be empty for older users + if ($r[0]["addr"] != "") { + $addr = $r[0]["nickname"].'@'.str_replace(array("http://", "https://"), "", System::baseUrl()); + } else { + $addr = $r[0]["addr"]; + } + + $gcontact = array("name" => $r[0]["name"], "location" => $location, "about" => $r[0]["about"], + "gender" => $r[0]["gender"], "keywords" => $r[0]["pub_keywords"], + "birthday" => $r[0]["dob"], "photo" => $r[0]["photo"], + "notify" => $r[0]["notify"], "url" => $r[0]["url"], + "hide" => ($r[0]["hidewall"] || !$r[0]["net-publish"]), + "nick" => $r[0]["nickname"], "addr" => $addr, + "connect" => $addr, "server_url" => System::baseUrl(), + "generation" => 1, "network" => NETWORK_DFRN); + + self::update($gcontact); + } + + /** + * @brief Fetches users of given GNU Social server + * + * If the "Statistics" plugin is enabled (See http://gstools.org/ for details) we query user data with this. + * + * @param str $server Server address + * @return void + */ + public static function fetchGsUsers($server) + { + logger("Fetching users from GNU Social server ".$server, LOGGER_DEBUG); + + $url = $server."/main/statistics"; + + $result = z_fetch_url($url); + if (!$result["success"]) { + return false; + } + + $statistics = json_decode($result["body"]); + + if (is_object($statistics->config)) { + if ($statistics->config->instance_with_ssl) { + $server = "https://"; + } else { + $server = "http://"; + } + + $server .= $statistics->config->instance_address; + + $hostname = $statistics->config->instance_address; + } else { + /// @TODO is_object() above means here no object, still $statistics is being used as object + if ($statistics->instance_with_ssl) { + $server = "https://"; + } else { + $server = "http://"; + } + + $server .= $statistics->instance_address; + + $hostname = $statistics->instance_address; + } + + if (is_object($statistics->users)) { + foreach ($statistics->users as $nick => $user) { + $profile_url = $server."/".$user->nickname; + + $contact = array("url" => $profile_url, + "name" => $user->fullname, + "addr" => $user->nickname."@".$hostname, + "nick" => $user->nickname, + "about" => $user->bio, + "network" => NETWORK_OSTATUS, + "photo" => System::baseUrl()."/images/person-175.jpg"); + self::getId($contact); + } + } + } + + /** + * @brief Asking GNU Social server on a regular base for their user data + * @return void + */ + public static function discoverGsUsers() + { + $requery_days = intval(Config::get("system", "poco_requery_days")); + + $last_update = date("c", time() - (60 * 60 * 24 * $requery_days)); + + $r = q( + "SELECT `nurl`, `url` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `network` = '%s' AND `last_poco_query` < '%s' ORDER BY RAND() LIMIT 5", + dbesc(NETWORK_OSTATUS), + dbesc($last_update) + ); + + if (!DBM::is_result($r)) { + return; + } + + foreach ($r as $server) { + self::fetchGsUsers($server["url"]); + q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"])); + } + } + + /** + * @return string + */ + public static function getRandomUrl() + { + $r = q( + "SELECT `url` FROM `gcontact` WHERE `network` = '%s' + AND `last_contact` >= `last_failure` + AND `updated` > UTC_TIMESTAMP - INTERVAL 1 MONTH + ORDER BY rand() LIMIT 1", + dbesc(NETWORK_DFRN) + ); + + if (DBM::is_result($r)) { + return dirname($r[0]['url']); + } + + return ''; + } +} diff --git a/src/Model/Photo.php b/src/Model/Photo.php deleted file mode 100644 index 229f221077..0000000000 --- a/src/Model/Photo.php +++ /dev/null @@ -1,174 +0,0 @@ - 1)); - if (DBM::is_result($r)) { - $guid = $r['guid']; - } else { - $guid = get_guid(); - } - - $x = dba::select('photo', array('id'), array('resource-id' => $rid, 'uid' => $uid, 'contact-id' => $cid, 'scale' => $scale), array('limit' => 1)); - - $fields = array( - 'uid' => $uid, - 'contact-id' => $cid, - 'guid' => $guid, - 'resource-id' => $rid, - 'created' => datetime_convert(), - 'edited' => datetime_convert(), - 'filename' => basename($filename), - 'type' => $Image->getType(), - 'album' => $album, - 'height' => $Image->getHeight(), - 'width' => $Image->getWidth(), - 'datasize' => strlen($Image->asString()), - 'data' => $Image->asString(), - 'scale' => $scale, - 'profile' => $profile, - 'allow_cid' => $allow_cid, - 'allow_gid' => $allow_gid, - 'deny_cid' => $deny_cid, - 'deny_gid' => $deny_gid, - 'desc' => $desc - ); - - if (DBM::is_result($x)) { - $r = dba::update('photo', $fields, array('id' => $x['id'])); - } else { - $r = dba::insert('photo', $fields); - } - - return $r; - } - - /** - * @param string $photo photo - * @param integer $uid user id - * @param integer $cid contact id - * @param boolean $quit_on_error optional, default false - * @return array - */ - public static function importProfilePhoto($photo, $uid, $cid, $quit_on_error = false) - { - $r = dba::select( - 'photo', array('resource-id'), array('uid' => $uid, 'contact-id' => $cid, 'scale' => 4, 'album' => 'Contact Photos'), array('limit' => 1) - ); - - if (DBM::is_result($r) && strlen($r['resource-id'])) { - $hash = $r['resource-id']; - } else { - $hash = photo_new_resource(); - } - - $photo_failure = false; - - $filename = basename($photo); - $img_str = fetch_url($photo, true); - - if ($quit_on_error && ($img_str == "")) { - return false; - } - - $type = Image::guessType($photo, true); - $Image = new Image($img_str, $type); - if ($Image->isValid()) { - $Image->scaleToSquare(175); - - $r = self::store($Image, $uid, $cid, $hash, $filename, 'Contact Photos', 4); - - if ($r === false) { - $photo_failure = true; - } - - $Image->scaleDown(80); - - $r = self::store($Image, $uid, $cid, $hash, $filename, 'Contact Photos', 5); - - if ($r === false) { - $photo_failure = true; - } - - $Image->scaleDown(48); - - $r = self::store($Image, $uid, $cid, $hash, $filename, 'Contact Photos', 6); - - if ($r === false) { - $photo_failure = true; - } - - $suffix = '?ts=' . time(); - - $photo = System::baseUrl() . '/photo/' . $hash . '-4.' . $Image->getExt() . $suffix; - $thumb = System::baseUrl() . '/photo/' . $hash . '-5.' . $Image->getExt() . $suffix; - $micro = System::baseUrl() . '/photo/' . $hash . '-6.' . $Image->getExt() . $suffix; - - // Remove the cached photo - $a = get_app(); - $basepath = $a->get_basepath(); - - if (is_dir($basepath . "/photo")) { - $filename = $basepath . '/photo/' . $hash . '-4.' . $Image->getExt(); - if (file_exists($filename)) { - unlink($filename); - } - $filename = $basepath . '/photo/' . $hash . '-5.' . $Image->getExt(); - if (file_exists($filename)) { - unlink($filename); - } - $filename = $basepath . '/photo/' . $hash . '-6.' . $Image->getExt(); - if (file_exists($filename)) { - unlink($filename); - } - } - } else { - $photo_failure = true; - } - - if ($photo_failure && $quit_on_error) { - return false; - } - - if ($photo_failure) { - $photo = System::baseUrl() . '/images/person-175.jpg'; - $thumb = System::baseUrl() . '/images/person-80.jpg'; - $micro = System::baseUrl() . '/images/person-48.jpg'; - } - - return array($photo, $thumb, $micro); - } -} diff --git a/src/Model/Profile.php b/src/Model/Profile.php deleted file mode 100644 index 0916e66c8d..0000000000 --- a/src/Model/Profile.php +++ /dev/null @@ -1,44 +0,0 @@ -isValid()) { - $Image->scaleToSquare(175); + $img = new Photo($img_str, $type); + if ($img->isValid()) { + $img->scaleImageSquare(175); $hash = photo_new_resource(); - $r = Photo::store($Image, $newuid, 0, $hash, $filename, t('Profile Photos'), 4); + $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4); if ($r === false) { $photo_failure = true; } - $Image->scaleDown(80); + $img->scaleImage(80); - $r = Photo::store($Image, $newuid, 0, $hash, $filename, t('Profile Photos'), 5); + $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5); if ($r === false) { $photo_failure = true; } - $Image->scaleDown(48); + $img->scaleImage(48); - $r = Photo::store($Image, $newuid, 0, $hash, $filename, t('Profile Photos'), 6); + $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6); if ($r === false) { $photo_failure = true; diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 320bb43cc1..500aa7323f 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -14,7 +14,7 @@ use Friendica\Core\System; use Friendica\Core\Cache; use Friendica\Core\Config; use Friendica\Database\DBM; -use Friendica\Model\Profile; +use Friendica\Object\Profile; use Friendica\Protocol\Email; use Friendica\Util\XML; diff --git a/src/Object/Contact.php b/src/Object/Contact.php new file mode 100644 index 0000000000..f72ec025a4 --- /dev/null +++ b/src/Object/Contact.php @@ -0,0 +1,948 @@ + 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/Object/Conversation.php b/src/Object/Conversation.php new file mode 100644 index 0000000000..3721086f96 --- /dev/null +++ b/src/Object/Conversation.php @@ -0,0 +1,207 @@ +setMode($mode); + $this->preview = $preview; + } + + /** + * Set the mode we'll be displayed on + * + * @param string $mode The mode to set + * + * @return void + */ + private function setMode($mode) + { + if ($this->getMode() == $mode) { + return; + } + + $a = self::getApp(); + + switch ($mode) { + case 'network': + case 'notes': + $this->profile_owner = local_user(); + $this->writable = true; + break; + case 'profile': + $this->profile_owner = $a->profile['profile_uid']; + $this->writable = can_write_wall($a, $this->profile_owner); + break; + case 'display': + $this->profile_owner = $a->profile['uid']; + $this->writable = can_write_wall($a, $this->profile_owner); + break; + default: + logger('[ERROR] Conversation::setMode : Unhandled mode ('. $mode .').', LOGGER_DEBUG); + return false; + break; + } + $this->mode = $mode; + } + + /** + * Get mode + * + * @return string + */ + public function getMode() + { + return $this->mode; + } + + /** + * Check if page is writable + * + * @return boolean + */ + public function isWritable() + { + return $this->writable; + } + + /** + * Check if page is a preview + * + * @return boolean + */ + public function isPreview() + { + return $this->preview; + } + + /** + * Get profile owner + * + * @return integer + */ + public function getProfileOwner() + { + return $this->profile_owner; + } + + /** + * Add a thread to the conversation + * + * @param object $item The item to insert + * + * @return mixed The inserted item on success + * false on failure + */ + public function addThread($item) + { + $item_id = $item->getId(); + + if (!$item_id) { + logger('[ERROR] Conversation::addThread : Item has no ID!!', LOGGER_DEBUG); + return false; + } + + if ($this->getThread($item->getId())) { + logger('[WARN] Conversation::addThread : Thread already exists ('. $item->getId() .').', LOGGER_DEBUG); + return false; + } + + /* + * Only add will be displayed + */ + if ($item->getDataValue('network') === NETWORK_MAIL && local_user() != $item->getDataValue('uid')) { + logger('[WARN] Conversation::addThread : Thread is a mail ('. $item->getId() .').', LOGGER_DEBUG); + return false; + } + + if ($item->getDataValue('verb') === ACTIVITY_LIKE || $item->getDataValue('verb') === ACTIVITY_DISLIKE) { + logger('[WARN] Conversation::addThread : Thread is a (dis)like ('. $item->getId() .').', LOGGER_DEBUG); + return false; + } + + $item->setConversation($this); + $this->threads[] = $item; + + return end($this->threads); + } + + /** + * Get data in a form usable by a conversation template + * + * We should find a way to avoid using those arguments (at least most of them) + * + * @param object $conv_responses data + * + * @return mixed The data requested on success + * false on failure + */ + public function getTemplateData($conv_responses) + { + $a = self::getApp(); + $result = array(); + $i = 0; + + foreach ($this->threads as $item) { + if ($item->getDataValue('network') === NETWORK_MAIL && local_user() != $item->getDataValue('uid')) { + continue; + } + + $item_data = $item->getTemplateData($conv_responses); + + if (!$item_data) { + logger('[ERROR] Conversation::getTemplateData : Failed to get item template data ('. $item->getId() .').', LOGGER_DEBUG); + return false; + } + $result[] = $item_data; + } + + return $result; + } + + /** + * Get a thread based on its item id + * + * @param integer $id Item id + * + * @return mixed The found item on success + * false on failure + */ + private function getThread($id) + { + foreach ($this->threads as $item) { + if ($item->getId() == $id) { + return $item; + } + } + + return false; + } +} diff --git a/src/Object/Image.php b/src/Object/Image.php deleted file mode 100644 index 79fbf3a990..0000000000 --- a/src/Object/Image.php +++ /dev/null @@ -1,1040 +0,0 @@ - 'jpg', - 'image/png' => 'png', - 'image/gif' => 'gif' - ); - } else { - $t = array(); - $t['image/jpeg'] ='jpg'; - if (imagetypes() & IMG_PNG) { - $t['image/png'] = 'png'; - } - } - - return $t; - } - - /** - * @brief Constructor - * @param object $data data - * @param boolean $type optional, default null - * @return object - */ - public function __construct($data, $type = null) - { - $this->imagick = class_exists('Imagick'); - $this->types = static::supportedTypes(); - if (!array_key_exists($type, $this->types)) { - $type='image/jpeg'; - } - $this->type = $type; - - if ($this->isImagick() && $this->loadData($data)) { - return true; - } else { - // Failed to load with Imagick, fallback - $this->imagick = false; - } - return $this->loadData($data); - } - - /** - * @brief Destructor - * @return void - */ - public function __destruct() - { - if ($this->image) { - if ($this->isImagick()) { - $this->image->clear(); - $this->image->destroy(); - return; - } - if (is_resource($this->image)) { - imagedestroy($this->image); - } - } - } - - /** - * @return boolean - */ - public function isImagick() - { - return $this->imagick; - } - - /** - * @brief Maps Mime types to Imagick formats - * @return arr With with image formats (mime type as key) - */ - public static function getFormatsMap() - { - $m = array( - 'image/jpeg' => 'JPG', - 'image/png' => 'PNG', - 'image/gif' => 'GIF' - ); - return $m; - } - - /** - * @param object $data data - * @return boolean - */ - private function loadData($data) - { - if ($this->isImagick()) { - $this->image = new Imagick(); - try { - $this->image->readImageBlob($data); - } catch (Exception $e) { - // Imagick couldn't use the data - return false; - } - - /* - * Setup the image to the format it will be saved to - */ - $map = self::getFormatsMap(); - $format = $map[$type]; - $this->image->setFormat($format); - - // Always coalesce, if it is not a multi-frame image it won't hurt anyway - $this->image = $this->image->coalesceImages(); - - /* - * setup the compression here, so we'll do it only once - */ - switch ($this->getType()) { - case "image/png": - $quality = Config::get('system', 'png_quality'); - if ((! $quality) || ($quality > 9)) { - $quality = PNG_QUALITY; - } - /* - * From http://www.imagemagick.org/script/command-line-options.php#quality: - * - * 'For the MNG and PNG image formats, the quality value sets - * the zlib compression level (quality / 10) and filter-type (quality % 10). - * The default PNG "quality" is 75, which means compression level 7 with adaptive PNG filtering, - * unless the image has a color map, in which case it means compression level 7 with no PNG filtering' - */ - $quality = $quality * 10; - $this->image->setCompressionQuality($quality); - break; - case "image/jpeg": - $quality = Config::get('system', 'jpeg_quality'); - if ((! $quality) || ($quality > 100)) { - $quality = JPEG_QUALITY; - } - $this->image->setCompressionQuality($quality); - } - - // The 'width' and 'height' properties are only used by non-Imagick routines. - $this->width = $this->image->getImageWidth(); - $this->height = $this->image->getImageHeight(); - $this->valid = true; - - return true; - } - - $this->valid = false; - $this->image = @imagecreatefromstring($data); - if ($this->image !== false) { - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - $this->valid = true; - imagealphablending($this->image, false); - imagesavealpha($this->image, true); - - return true; - } - - return false; - } - - /** - * @return boolean - */ - public function isValid() - { - if ($this->isImagick()) { - return ($this->image !== false); - } - return $this->valid; - } - - /** - * @return mixed - */ - public function getWidth() - { - if (!$this->isValid()) { - return false; - } - - if ($this->isImagick()) { - return $this->image->getImageWidth(); - } - return $this->width; - } - - /** - * @return mixed - */ - public function getHeight() - { - if (!$this->isValid()) { - return false; - } - - if ($this->isImagick()) { - return $this->image->getImageHeight(); - } - return $this->height; - } - - /** - * @return mixed - */ - public function getImage() - { - if (!$this->isValid()) { - return false; - } - - if ($this->isImagick()) { - /* Clean it */ - $this->image = $this->image->deconstructImages(); - return $this->image; - } - return $this->image; - } - - /** - * @return mixed - */ - public function getType() - { - if (!$this->isValid()) { - return false; - } - - return $this->type; - } - - /** - * @return mixed - */ - public function getExt() - { - if (!$this->isValid()) { - return false; - } - - return $this->types[$this->getType()]; - } - - /** - * @param integer $max max dimension - * @return mixed - */ - public function scaleDown($max) - { - if (!$this->isValid()) { - return false; - } - - $width = $this->getWidth(); - $height = $this->getHeight(); - - $dest_width = $dest_height = 0; - - if ((! $width)|| (! $height)) { - return false; - } - - if ($width > $max && $height > $max) { - // very tall image (greater than 16:9) - // constrain the width - let the height float. - - if ((($height * 9) / 16) > $width) { - $dest_width = $max; - $dest_height = intval(($height * $max) / $width); - } elseif ($width > $height) { - // else constrain both dimensions - $dest_width = $max; - $dest_height = intval(($height * $max) / $width); - } else { - $dest_width = intval(($width * $max) / $height); - $dest_height = $max; - } - } else { - if ($width > $max) { - $dest_width = $max; - $dest_height = intval(($height * $max) / $width); - } else { - if ($height > $max) { - // very tall image (greater than 16:9) - // but width is OK - don't do anything - - if ((($height * 9) / 16) > $width) { - $dest_width = $width; - $dest_height = $height; - } else { - $dest_width = intval(($width * $max) / $height); - $dest_height = $max; - } - } else { - $dest_width = $width; - $dest_height = $height; - } - } - } - - - if ($this->isImagick()) { - /* - * If it is not animated, there will be only one iteration here, - * so don't bother checking - */ - // Don't forget to go back to the first frame - $this->image->setFirstIterator(); - do { - // FIXME - implement horizantal bias for scaling as in followin GD functions - // to allow very tall images to be constrained only horizontally. - - $this->image->scaleDown($dest_width, $dest_height); - } while ($this->image->nextImage()); - - // These may not be necessary any more - $this->width = $this->image->getImageWidth(); - $this->height = $this->image->getImageHeight(); - - return; - } - - - $dest = imagecreatetruecolor($dest_width, $dest_height); - imagealphablending($dest, false); - imagesavealpha($dest, true); - if ($this->type=='image/png') { - imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha - } - imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); - if ($this->image) { - imagedestroy($this->image); - } - $this->image = $dest; - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } - - /** - * @param integer $degrees degrees to rotate image - * @return mixed - */ - public function rotate($degrees) - { - if (!$this->isValid()) { - return false; - } - - if ($this->isImagick()) { - $this->image->setFirstIterator(); - do { - $this->image->rotateImage(new ImagickPixel(), -$degrees); // ImageMagick rotates in the opposite direction of imagerotate() - } while ($this->image->nextImage()); - return; - } - - // if script dies at this point check memory_limit setting in php.ini - $this->image = imagerotate($this->image, $degrees, 0); - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } - - /** - * @param boolean $horiz optional, default true - * @param boolean $vert optional, default false - * @return mixed - */ - public function flip($horiz = true, $vert = false) - { - if (!$this->isValid()) { - return false; - } - - if ($this->isImagick()) { - $this->image->setFirstIterator(); - do { - if ($horiz) { - $this->image->flipImage(); - } - if ($vert) { - $this->image->flopImage(); - } - } while ($this->image->nextImage()); - return; - } - - $w = imagesx($this->image); - $h = imagesy($this->image); - $flipped = imagecreate($w, $h); - if ($horiz) { - for ($x = 0; $x < $w; $x++) { - imagecopy($flipped, $this->image, $x, 0, $w - $x - 1, 0, 1, $h); - } - } - if ($vert) { - for ($y = 0; $y < $h; $y++) { - imagecopy($flipped, $this->image, 0, $y, 0, $h - $y - 1, $w, 1); - } - } - $this->image = $flipped; - } - - /** - * @param string $filename filename - * @return mixed - */ - public function orient($filename) - { - if ($this->isImagick()) { - // based off comment on http://php.net/manual/en/imagick.getimageorientation.php - $orientation = $this->image->getImageOrientation(); - switch ($orientation) { - case Imagick::ORIENTATION_BOTTOMRIGHT: - $this->image->rotateimage("#000", 180); - break; - case Imagick::ORIENTATION_RIGHTTOP: - $this->image->rotateimage("#000", 90); - break; - case Imagick::ORIENTATION_LEFTBOTTOM: - $this->image->rotateimage("#000", -90); - break; - } - - $this->image->setImageOrientation(Imagick::ORIENTATION_TOPLEFT); - return true; - } - // based off comment on http://php.net/manual/en/function.imagerotate.php - - if (!$this->isValid()) { - return false; - } - - if ((!function_exists('exif_read_data')) || ($this->getType() !== 'image/jpeg')) { - return; - } - - $exif = @exif_read_data($filename, null, true); - if (!$exif) { - return; - } - - $ort = $exif['IFD0']['Orientation']; - - switch ($ort) { - case 1: // nothing - break; - - case 2: // horizontal flip - $this->flip(); - break; - - case 3: // 180 rotate left - $this->rotate(180); - break; - - case 4: // vertical flip - $this->flip(false, true); - break; - - case 5: // vertical flip + 90 rotate right - $this->flip(false, true); - $this->rotate(-90); - break; - - case 6: // 90 rotate right - $this->rotate(-90); - break; - - case 7: // horizontal flip + 90 rotate right - $this->flip(); - $this->rotate(-90); - break; - - case 8: // 90 rotate left - $this->rotate(90); - break; - } - - // logger('exif: ' . print_r($exif,true)); - return $exif; - } - - /** - * @param integer $min minimum dimension - * @return mixed - */ - public function scaleUp($min) - { - if (!$this->isValid()) { - return false; - } - - $width = $this->getWidth(); - $height = $this->getHeight(); - - $dest_width = $dest_height = 0; - - if ((!$width)|| (!$height)) { - return false; - } - - if ($width < $min && $height < $min) { - if ($width > $height) { - $dest_width = $min; - $dest_height = intval(($height * $min) / $width); - } else { - $dest_width = intval(($width * $min) / $height); - $dest_height = $min; - } - } else { - if ($width < $min) { - $dest_width = $min; - $dest_height = intval(($height * $min) / $width); - } else { - if ($height < $min) { - $dest_width = intval(($width * $min) / $height); - $dest_height = $min; - } else { - $dest_width = $width; - $dest_height = $height; - } - } - } - - if ($this->isImagick()) { - return $this->scaleDown($dest_width, $dest_height); - } - - $dest = imagecreatetruecolor($dest_width, $dest_height); - imagealphablending($dest, false); - imagesavealpha($dest, true); - if ($this->type=='image/png') { - imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha - } - imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); - if ($this->image) { - imagedestroy($this->image); - } - $this->image = $dest; - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } - - /** - * @param integer $dim dimension - * @return mixed - */ - public function scaleToSquare($dim) - { - if (!$this->isValid()) { - return false; - } - - if ($this->isImagick()) { - $this->image->setFirstIterator(); - do { - $this->image->scaleDown($dim, $dim); - } while ($this->image->nextImage()); - return; - } - - $dest = imagecreatetruecolor($dim, $dim); - imagealphablending($dest, false); - imagesavealpha($dest, true); - if ($this->type=='image/png') { - imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha - } - imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dim, $dim, $this->width, $this->height); - if ($this->image) { - imagedestroy($this->image); - } - $this->image = $dest; - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } - - /** - * @param integer $max maximum - * @param integer $x x coordinate - * @param integer $y y coordinate - * @param integer $w width - * @param integer $h height - * @return mixed - */ - public function crop($max, $x, $y, $w, $h) - { - if (!$this->isValid()) { - return false; - } - - if ($this->isImagick()) { - $this->image->setFirstIterator(); - do { - $this->image->cropImage($w, $h, $x, $y); - /* - * We need to remove the canva, - * or the image is not resized to the crop: - * http://php.net/manual/en/imagick.cropimage.php#97232 - */ - $this->image->setImagePage(0, 0, 0, 0); - } while ($this->image->nextImage()); - return $this->scaleDown($max); - } - - $dest = imagecreatetruecolor($max, $max); - imagealphablending($dest, false); - imagesavealpha($dest, true); - if ($this->type=='image/png') { - imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha - } - imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $max, $max, $w, $h); - if ($this->image) { - imagedestroy($this->image); - } - $this->image = $dest; - $this->width = imagesx($this->image); - $this->height = imagesy($this->image); - } - - /** - * @param string $path file path - * @return mixed - */ - public function saveToFilePath($path) - { - if (!$this->isValid()) { - return false; - } - - $string = $this->asString(); - - $a = get_app(); - - $stamp1 = microtime(true); - file_put_contents($path, $string); - $a->save_timestamp($stamp1, "file"); - } - - /** - * @brief Magic method allowing string casting of an Image object - * - * Ex: $data = $Image->asString(); - * can be replaced by - * $data = (string) $Image; - * - * @return string - */ - public function __toString() { - return $this->asString(); - } - - /** - * @return mixed - */ - public function asString() - { - if (!$this->isValid()) { - return false; - } - - if ($this->isImagick()) { - /* Clean it */ - $this->image = $this->image->deconstructImages(); - $string = $this->image->getImagesBlob(); - return $string; - } - - $quality = false; - - ob_start(); - - // Enable interlacing - imageinterlace($this->image, true); - - switch ($this->getType()) { - case "image/png": - $quality = Config::get('system', 'png_quality'); - if ((!$quality) || ($quality > 9)) { - $quality = PNG_QUALITY; - } - imagepng($this->image, null, $quality); - break; - case "image/jpeg": - $quality = Config::get('system', 'jpeg_quality'); - if ((!$quality) || ($quality > 100)) { - $quality = JPEG_QUALITY; - } - imagejpeg($this->image, null, $quality); - } - $string = ob_get_contents(); - ob_end_clean(); - - return $string; - } - - /** - * Guess image mimetype from filename or from Content-Type header - * - * @param string $filename Image filename - * @param boolean $fromcurl Check Content-Type header from curl request - * - * @return object - */ - public static function guessType($filename, $fromcurl = false) - { - logger('Image: guessType: '.$filename . ($fromcurl?' from curl headers':''), LOGGER_DEBUG); - $type = null; - if ($fromcurl) { - $a = get_app(); - $headers=array(); - $h = explode("\n", $a->get_curl_headers()); - foreach ($h as $l) { - list($k,$v) = array_map("trim", explode(":", trim($l), 2)); - $headers[$k] = $v; - } - if (array_key_exists('Content-Type', $headers)) - $type = $headers['Content-Type']; - } - if (is_null($type)) { - // Guessing from extension? Isn't that... dangerous? - if (class_exists('Imagick') && file_exists($filename) && is_readable($filename)) { - /** - * Well, this not much better, - * but at least it comes from the data inside the image, - * we won't be tricked by a manipulated extension - */ - $image = new Imagick($filename); - $type = $image->getImageMimeType(); - $image->setInterlaceScheme(Imagick::INTERLACE_PLANE); - } else { - $ext = pathinfo($filename, PATHINFO_EXTENSION); - $types = self::supportedTypes(); - $type = "image/jpeg"; - foreach ($types as $m => $e) { - if ($ext == $e) { - $type = $m; - } - } - } - } - logger('Image: guessType: type='.$type, LOGGER_DEBUG); - return $type; - } - - /** - * @param string $url url - * @return object - */ - public static function getInfoFromURL($url) - { - $data = array(); - - $data = Cache::get($url); - - if (is_null($data) || !$data || !is_array($data)) { - $img_str = fetch_url($url, true, $redirects, 4); - $filesize = strlen($img_str); - - if (function_exists("getimagesizefromstring")) { - $data = getimagesizefromstring($img_str); - } else { - $tempfile = tempnam(get_temppath(), "cache"); - - $a = get_app(); - $stamp1 = microtime(true); - file_put_contents($tempfile, $img_str); - $a->save_timestamp($stamp1, "file"); - - $data = getimagesize($tempfile); - unlink($tempfile); - } - - if ($data) { - $data["size"] = $filesize; - } - - Cache::set($url, $data); - } - - return $data; - } - - /** - * @param integer $width width - * @param integer $height height - * @param integer $max max - * @return array - */ - public static function getScalingDimensions($width, $height, $max) - { - $dest_width = $dest_height = 0; - - if ((!$width) || (!$height)) { - return false; - } - - if ($width > $max && $height > $max) { - // very tall image (greater than 16:9) - // constrain the width - let the height float. - - if ((($height * 9) / 16) > $width) { - $dest_width = $max; - $dest_height = intval(($height * $max) / $width); - } elseif ($width > $height) { - // else constrain both dimensions - $dest_width = $max; - $dest_height = intval(($height * $max) / $width); - } else { - $dest_width = intval(($width * $max) / $height); - $dest_height = $max; - } - } else { - if ($width > $max) { - $dest_width = $max; - $dest_height = intval(($height * $max) / $width); - } else { - if ($height > $max) { - // very tall image (greater than 16:9) - // but width is OK - don't do anything - - if ((($height * 9) / 16) > $width) { - $dest_width = $width; - $dest_height = $height; - } else { - $dest_width = intval(($width * $max) / $height); - $dest_height = $max; - } - } else { - $dest_width = $width; - $dest_height = $height; - } - } - } - return array("width" => $dest_width, "height" => $dest_height); - } - - /** - * @brief This function is used by the fromgplus addon - * @param object $a App - * @param integer $uid user id - * @param string $imagedata optional, default empty - * @param string $url optional, default empty - * @return array - */ - public static function storePhoto(App $a, $uid, $imagedata = "", $url = "") - { - $r = q( - "SELECT `user`.`nickname`, `user`.`page-flags`, `contact`.`id` FROM `user` INNER JOIN `contact` on `user`.`uid` = `contact`.`uid` - WHERE `user`.`uid` = %d AND `user`.`blocked` = 0 AND `contact`.`self` = 1 LIMIT 1", - intval($uid) - ); - - if (!DBM::is_result($r)) { - logger("Can't detect user data for uid ".$uid, LOGGER_DEBUG); - return(array()); - } - - $page_owner_nick = $r[0]['nickname']; - - /// @TODO - /// $default_cid = $r[0]['id']; - /// $community_page = (($r[0]['page-flags'] == PAGE_COMMUNITY) ? true : false); - - if ((strlen($imagedata) == 0) && ($url == "")) { - logger("No image data and no url provided", LOGGER_DEBUG); - return(array()); - } elseif (strlen($imagedata) == 0) { - logger("Uploading picture from ".$url, LOGGER_DEBUG); - - $stamp1 = microtime(true); - $imagedata = @file_get_contents($url); - $a->save_timestamp($stamp1, "file"); - } - - $maximagesize = Config::get('system', 'maximagesize'); - - if (($maximagesize) && (strlen($imagedata) > $maximagesize)) { - logger("Image exceeds size limit of ".$maximagesize, LOGGER_DEBUG); - return(array()); - } - - $tempfile = tempnam(get_temppath(), "cache"); - - $stamp1 = microtime(true); - file_put_contents($tempfile, $imagedata); - $a->save_timestamp($stamp1, "file"); - - $data = getimagesize($tempfile); - - if (!isset($data["mime"])) { - unlink($tempfile); - logger("File is no picture", LOGGER_DEBUG); - return(array()); - } - - $Image = new Image($imagedata, $data["mime"]); - - if (!$Image->isValid()) { - unlink($tempfile); - logger("Picture is no valid picture", LOGGER_DEBUG); - return(array()); - } - - $Image->orient($tempfile); - unlink($tempfile); - - $max_length = Config::get('system', 'max_image_length'); - if (! $max_length) { - $max_length = MAX_IMAGE_LENGTH; - } - - if ($max_length > 0) { - $Image->scaleDown($max_length); - } - - $width = $Image->getWidth(); - $height = $Image->getHeight(); - - $hash = photo_new_resource(); - - $smallest = 0; - - // Pictures are always public by now - //$defperm = '<'.$default_cid.'>'; - $defperm = ""; - $visitor = 0; - - $r = Photo::store($Image, $uid, $visitor, $hash, $tempfile, t('Wall Photos'), 0, 0, $defperm); - - if (!$r) { - logger("Picture couldn't be stored", LOGGER_DEBUG); - return(array()); - } - - $image = array("page" => System::baseUrl().'/photos/'.$page_owner_nick.'/image/'.$hash, - "full" => System::baseUrl()."/photo/{$hash}-0.".$Image->getExt()); - - if ($width > 800 || $height > 800) { - $image["large"] = System::baseUrl()."/photo/{$hash}-0.".$Image->getExt(); - } - - if ($width > 640 || $height > 640) { - $Image->scaleDown(640); - $r = Photo::store($Image, $uid, $visitor, $hash, $tempfile, t('Wall Photos'), 1, 0, $defperm); - if ($r) { - $image["medium"] = System::baseUrl()."/photo/{$hash}-1.".$Image->getExt(); - } - } - - if ($width > 320 || $height > 320) { - $Image->scaleDown(320); - $r = Photo::store($Image, $uid, $visitor, $hash, $tempfile, t('Wall Photos'), 2, 0, $defperm); - if ($r) { - $image["small"] = System::baseUrl()."/photo/{$hash}-2.".$Image->getExt(); - } - } - - if ($width > 160 && $height > 160) { - $x = 0; - $y = 0; - - $min = $Image->getWidth(); - if ($min > 160) { - $x = ($min - 160) / 2; - } - - if ($Image->getHeight() < $min) { - $min = $Image->getHeight(); - if ($min > 160) { - $y = ($min - 160) / 2; - } - } - - $min = 160; - $Image->crop(160, $x, $y, $min, $min); - - $r = Photo::store($Image, $uid, $visitor, $hash, $tempfile, t('Wall Photos'), 3, 0, $defperm); - if ($r) { - $image["thumb"] = System::baseUrl()."/photo/{$hash}-3.".$Image->getExt(); - } - } - - // Set the full image as preview image. This will be overwritten, if the picture is larger than 640. - $image["preview"] = $image["full"]; - - // Deactivated, since that would result in a cropped preview, if the picture wasn't larger than 320 - //if (isset($image["thumb"])) - // $image["preview"] = $image["thumb"]; - - // Unsure, if this should be activated or deactivated - //if (isset($image["small"])) - // $image["preview"] = $image["small"]; - - if (isset($image["medium"])) { - $image["preview"] = $image["medium"]; - } - - return($image); - } -} diff --git a/src/Object/Item.php b/src/Object/Item.php new file mode 100644 index 0000000000..1533908aeb --- /dev/null +++ b/src/Object/Item.php @@ -0,0 +1,915 @@ + 'wall_thread.tpl', + 'wall2wall' => 'wallwall_thread.tpl' + ); + private $comment_box_template = 'comment_item.tpl'; + private $toplevel = false; + private $writable = false; + private $children = array(); + private $parent = null; + private $conversation = null; + private $redirect_url = null; + private $owner_url = ''; + private $owner_photo = ''; + private $owner_name = ''; + private $wall_to_wall = false; + private $threaded = false; + private $visiting = false; + + /** + * Constructor + * + * @param array $data data array + */ + public function __construct($data) + { + $a = self::getApp(); + + $this->data = $data; + $this->setTemplate('wall'); + $this->toplevel = ($this->getId() == $this->getDataValue('parent')); + + if (is_array($_SESSION['remote'])) { + foreach ($_SESSION['remote'] as $visitor) { + if ($visitor['cid'] == $this->getDataValue('contact-id')) { + $this->visiting = true; + break; + } + } + } + + $this->writable = ($this->getDataValue('writable') || $this->getDataValue('self')); + + $ssl_state = ((local_user()) ? true : false); + $this->redirect_url = 'redir/' . $this->getDataValue('cid'); + + if (!$this->isToplevel()) { + $this->threaded = true; + } + + // Prepare the children + if (count($data['children'])) { + foreach ($data['children'] as $item) { + /* + * Only add will be displayed + */ + if ($item['network'] === NETWORK_MAIL && local_user() != $item['uid']) { + continue; + } elseif (! visible_activity($item)) { + continue; + } + + // You can always comment on Diaspora items + if (($item['network'] == NETWORK_DIASPORA) && (local_user() == $item['uid'])) { + $item['writable'] = true; + } + + $item['pagedrop'] = $data['pagedrop']; + $child = new Item($item); + $this->addChild($child); + } + } + } + + /** + * Get data in a form usable by a conversation template + * + * @param object $conv_responses conversation responses + * @param integer $thread_level default = 1 + * + * @return mixed The data requested on success + * false on failure + */ + public function getTemplateData($conv_responses, $thread_level = 1) + { + require_once "mod/proxy.php"; + + $result = array(); + + $a = self::getApp(); + + $item = $this->getData(); + $edited = false; + // If the time between "created" and "edited" differs we add + // a notice that the post was edited. + // Note: In some networks reshared items seem to have (sometimes) a difference + // between creation time and edit time of a second. Thats why we add the notice + // only if the difference is more than 1 second. + if (strtotime($item['edited']) - strtotime($item['created']) > 1) { + $edited = array( + 'label' => t('This entry was edited'), + 'date' => datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r'), + 'relative' => relative_date($item['edited']) + ); + } + $commentww = ''; + $sparkle = ''; + $buttons = ''; + $dropping = false; + $star = false; + $ignore = false; + $isstarred = "unstarred"; + $indent = ''; + $shiny = ''; + $osparkle = ''; + $total_children = $this->countDescendants(); + + $conv = $this->getConversation(); + + $lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid']) + || strlen($item['deny_cid']) || strlen($item['deny_gid'])))) + ? t('Private Message') + : false); + $shareable = ((($conv->getProfileOwner() == local_user()) && ($item['private'] != 1)) ? true : false); + if (local_user() && link_compare($a->contact['url'], $item['author-link'])) { + if ($item["event-id"] != 0) { + $edpost = array("events/event/".$item['event-id'], t("Edit")); + } else { + $edpost = array("editpost/".$item['id'], t("Edit")); + } + } else { + $edpost = false; + } + + if (($this->getDataValue('uid') == local_user()) || $this->isVisiting()) { + $dropping = true; + } + + $drop = array( + 'dropping' => $dropping, + 'pagedrop' => ((Feature::isEnabled($conv->getProfileOwner(), 'multi_delete')) ? $item['pagedrop'] : ''), + 'select' => t('Select'), + 'delete' => t('Delete'), + ); + + $filer = (($conv->getProfileOwner() == local_user()) ? t("save to folder") : false); + + $diff_author = ((link_compare($item['url'], $item['author-link'])) ? false : true); + $profile_name = htmlentities(((strlen($item['author-name'])) && $diff_author) ? $item['author-name'] : $item['name']); + if ($item['author-link'] && (! $item['author-name'])) { + $profile_name = $item['author-link']; + } + + $sp = false; + $profile_link = best_link_url($item, $sp); + if ($profile_link === 'mailbox') { + $profile_link = ''; + } + + if ($sp) { + $sparkle = ' sparkle'; + } else { + $profile_link = zrl($profile_link); + } + + if (!isset($item['author-thumb']) || ($item['author-thumb'] == "")) { + $author_contact = Contact::getDetailsByURL($item['author-link'], $conv->getProfileOwner()); + if ($author_contact["thumb"]) { + $item['author-thumb'] = $author_contact["thumb"]; + } else { + $item['author-thumb'] = $item['author-avatar']; + } + } + + if (!isset($item['owner-thumb']) || ($item['owner-thumb'] == "")) { + $owner_contact = Contact::getDetailsByURL($item['owner-link'], $conv->getProfileOwner()); + if ($owner_contact["thumb"]) { + $item['owner-thumb'] = $owner_contact["thumb"]; + } else { + $item['owner-thumb'] = $item['owner-avatar']; + } + } + + $locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => ''); + call_hooks('render_location', $locate); + $location = ((strlen($locate['html'])) ? $locate['html'] : render_location_dummy($locate)); + + $tags=array(); + $hashtags = array(); + $mentions = array(); + + /*foreach(explode(',',$item['tag']) as $tag){ + $tag = trim($tag); + if ($tag!="") { + $t = bbcode($tag); + $tags[] = $t; + if($t[0] == '#') + $hashtags[] = $t; + elseif($t[0] == '@') + $mentions[] = $t; + } + }*/ + + // process action responses - e.g. like/dislike/attend/agree/whatever + $response_verbs = array('like', 'dislike'); + + if ($item['object-type'] === ACTIVITY_OBJ_EVENT) { + $response_verbs[] = 'attendyes'; + $response_verbs[] = 'attendno'; + $response_verbs[] = 'attendmaybe'; + if ($conv->isWritable()) { + $isevent = true; + $attend = array( t('I will attend'), t('I will not attend'), t('I might attend')); + } + } + + $responses = get_responses($conv_responses, $response_verbs, $this, $item); + + foreach ($response_verbs as $value => $verbs) { + $responses[$verbs]['output'] = ((x($conv_responses[$verbs], $item['uri'])) ? format_like($conv_responses[$verbs][$item['uri']], $conv_responses[$verbs][$item['uri'] . '-l'], $verbs, $item['uri']) : ''); + } + + /* + * We should avoid doing this all the time, but it depends on the conversation mode + * And the conv mode may change when we change the conv, or it changes its mode + * Maybe we should establish a way to be notified about conversation changes + */ + $this->checkWallToWall(); + + if ($this->isWallToWall() && ($this->getOwnerUrl() == $this->getRedirectUrl())) { + $osparkle = ' sparkle'; + } + + if ($this->isToplevel()) { + if ($conv->getProfileOwner() == local_user()) { + $isstarred = (($item['starred']) ? "starred" : "unstarred"); + + $star = array( + 'do' => t("add star"), + 'undo' => t("remove star"), + 'toggle' => t("toggle star status"), + 'classdo' => (($item['starred']) ? "hidden" : ""), + 'classundo' => (($item['starred']) ? "" : "hidden"), + 'starred' => t('starred'), + ); + $r = dba::select('thread', array('ignored'), array('uid' => $item['uid'], 'iid' => $item['id']), array('limit' => 1)); + if (DBM::is_result($r)) { + $ignore = array( + 'do' => t("ignore thread"), + 'undo' => t("unignore thread"), + 'toggle' => t("toggle ignore status"), + 'classdo' => (($r['ignored']) ? "hidden" : ""), + 'classundo' => (($r['ignored']) ? "" : "hidden"), + 'ignored' => t('ignored'), + ); + } + + $tagger = ''; + if (Feature::isEnabled($conv->getProfileOwner(), 'commtag')) { + $tagger = array( + 'add' => t("add tag"), + 'class' => "", + ); + } + } + } else { + $indent = 'comment'; + } + + if ($conv->isWritable()) { + $buttons = array( + 'like' => array( t("I like this \x28toggle\x29"), t("like")), + 'dislike' => ((Feature::isEnabled($conv->getProfileOwner(), 'dislike')) ? array( t("I don't like this \x28toggle\x29"), t("dislike")) : ''), + ); + if ($shareable) { + $buttons['share'] = array( t('Share this'), t('share')); + } + } + + $comment = $this->getCommentBox($indent); + + if (strcmp(datetime_convert('UTC', 'UTC', $item['created']), datetime_convert('UTC', 'UTC', 'now - 12 hours')) > 0) { + $shiny = 'shiny'; + } + + localize_item($item); + + $body = prepare_body($item, true); + + list($categories, $folders) = get_cats_and_terms($item); + + $body_e = $body; + $text_e = strip_tags($body); + $name_e = $profile_name; + $title_e = $item['title']; + $location_e = $location; + $owner_name_e = $this->getOwnerName(); + + // Disable features that aren't available in several networks + + /// @todo Add NETWORK_DIASPORA when it will pass this information + if (!in_array($item["item_network"], array(NETWORK_DFRN)) && isset($buttons["dislike"])) { + unset($buttons["dislike"], $isevent); + $tagger = ''; + } + + if (($item["item_network"] == NETWORK_FEED) && isset($buttons["like"])) { + unset($buttons["like"]); + } + + if (($item["item_network"] == NETWORK_MAIL) && isset($buttons["like"])) { + unset($buttons["like"]); + } + + $tmp_item = array( + 'template' => $this->getTemplate(), + 'type' => implode("", array_slice(explode("/", $item['verb']), -1)), + 'tags' => $item['tags'], + 'hashtags' => $item['hashtags'], + 'mentions' => $item['mentions'], + 'txt_cats' => t('Categories:'), + 'txt_folders' => t('Filed under:'), + 'has_cats' => ((count($categories)) ? 'true' : ''), + 'has_folders' => ((count($folders)) ? 'true' : ''), + 'categories' => $categories, + 'folders' => $folders, + 'body' => $body_e, + 'text' => $text_e, + 'id' => $this->getId(), + 'guid' => urlencode($item['guid']), + 'isevent' => $isevent, + 'attend' => $attend, + 'linktitle' => sprintf(t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])), + 'olinktitle' => sprintf(t('View %s\'s profile @ %s'), htmlentities($this->getOwnerName()), ((strlen($item['owner-link'])) ? $item['owner-link'] : $item['url'])), + 'to' => t('to'), + 'via' => t('via'), + 'wall' => t('Wall-to-Wall'), + 'vwall' => t('via Wall-To-Wall:'), + 'profile_url' => $profile_link, + 'item_photo_menu' => item_photo_menu($item), + 'name' => $name_e, + 'thumb' => $a->remove_baseurl(proxy_url($item['author-thumb'], false, PROXY_SIZE_THUMB)), + 'osparkle' => $osparkle, + 'sparkle' => $sparkle, + 'title' => $title_e, + 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'), + 'ago' => (($item['app']) ? sprintf(t('%s from %s'), relative_date($item['created']), $item['app']) : relative_date($item['created'])), + 'app' => $item['app'], + 'created' => relative_date($item['created']), + 'lock' => $lock, + 'location' => $location_e, + 'indent' => $indent, + 'shiny' => $shiny, + 'owner_url' => $this->getOwnerUrl(), + 'owner_photo' => $a->remove_baseurl(proxy_url($item['owner-thumb'], false, PROXY_SIZE_THUMB)), + 'owner_name' => htmlentities($owner_name_e), + 'plink' => get_plink($item), + 'edpost' => ((Feature::isEnabled($conv->getProfileOwner(), 'edit_posts')) ? $edpost : ''), + 'isstarred' => $isstarred, + 'star' => ((Feature::isEnabled($conv->getProfileOwner(), 'star_posts')) ? $star : ''), + 'ignore' => ((Feature::isEnabled($conv->getProfileOwner(), 'ignore_posts')) ? $ignore : ''), + 'tagger' => $tagger, + 'filer' => ((Feature::isEnabled($conv->getProfileOwner(), 'filing')) ? $filer : ''), + 'drop' => $drop, + 'vote' => $buttons, + 'like' => $responses['like']['output'], + 'dislike' => $responses['dislike']['output'], + 'responses' => $responses, + 'switchcomment' => t('Comment'), + 'comment' => $comment, + 'previewing' => ($conv->isPreview() ? ' preview ' : ''), + 'wait' => t('Please wait'), + 'thread_level' => $thread_level, + 'edited' => $edited, + 'network' => $item["item_network"], + 'network_name' => network_to_name($item['item_network'], $profile_link), + 'received' => $item['received'], + 'commented' => $item['commented'], + 'created_date' => $item['created'], + ); + + $arr = array('item' => $item, 'output' => $tmp_item); + call_hooks('display_item', $arr); + + $result = $arr['output']; + + $result['children'] = array(); + $children = $this->getChildren(); + $nb_children = count($children); + if ($nb_children > 0) { + foreach ($children as $child) { + $result['children'][] = $child->getTemplateData($conv_responses, $thread_level + 1); + } + // Collapse + if (($nb_children > 2) || ($thread_level > 1)) { + $result['children'][0]['comment_firstcollapsed'] = true; + $result['children'][0]['num_comments'] = sprintf(tt('%d comment', '%d comments', $total_children), $total_children); + $result['children'][0]['hidden_comments_num'] = $total_children; + $result['children'][0]['hidden_comments_text'] = tt('comment', 'comments', $total_children); + $result['children'][0]['hide_text'] = t('show more'); + if ($thread_level > 1) { + $result['children'][$nb_children - 1]['comment_lastcollapsed'] = true; + } else { + $result['children'][$nb_children - 3]['comment_lastcollapsed'] = true; + } + } + } + + if ($this->isToplevel()) { + $result['total_comments_num'] = "$total_children"; + $result['total_comments_text'] = tt('comment', 'comments', $total_children); + } + + $result['private'] = $item['private']; + $result['toplevel'] = ($this->isToplevel() ? 'toplevel_item' : ''); + + if ($this->isThreaded()) { + $result['flatten'] = false; + $result['threaded'] = true; + } else { + $result['flatten'] = true; + $result['threaded'] = false; + } + + return $result; + } + + /** + * @return integer + */ + public function getId() + { + return $this->getDataValue('id'); + } + + /** + * @return boolean + */ + public function isThreaded() + { + return $this->threaded; + } + + /** + * Add a child item + * + * @param object $item The child item to add + * + * @return mixed + */ + public function addChild(Item $item) + { + $item_id = $item->getId(); + if (!$item_id) { + logger('[ERROR] Item::addChild : Item has no ID!!', LOGGER_DEBUG); + return false; + } elseif ($this->getChild($item->getId())) { + logger('[WARN] Item::addChild : Item already exists ('. $item->getId() .').', LOGGER_DEBUG); + return false; + } + /* + * Only add what will be displayed + */ + if ($item->getDataValue('network') === NETWORK_MAIL && local_user() != $item->getDataValue('uid')) { + return false; + } elseif (activity_match($item->getDataValue('verb'), ACTIVITY_LIKE) || activity_match($item->getDataValue('verb'), ACTIVITY_DISLIKE)) { + return false; + } + + $item->setParent($this); + $this->children[] = $item; + + return end($this->children); + } + + /** + * Get a child by its ID + * + * @param integer $id The child id + * + * @return mixed + */ + public function getChild($id) + { + foreach ($this->getChildren() as $child) { + if ($child->getId() == $id) { + return $child; + } + } + + return null; + } + + /** + * Get all our children + * + * @return object + */ + public function getChildren() + { + return $this->children; + } + + /** + * Set our parent + * + * @param object $item The item to set as parent + * + * @return void + */ + protected function setParent($item) + { + $parent = $this->getParent(); + if ($parent) { + $parent->removeChild($this); + } + + $this->parent = $item; + $this->setConversation($item->getConversation()); + } + + /** + * Remove our parent + * + * @return void + */ + protected function removeParent() + { + $this->parent = null; + $this->conversation = null; + } + + /** + * Remove a child + * + * @param object $item The child to be removed + * + * @return boolean Success or failure + */ + public function removeChild($item) + { + $id = $item->getId(); + foreach ($this->getChildren() as $key => $child) { + if ($child->getId() == $id) { + $child->removeParent(); + unset($this->children[$key]); + // Reindex the array, in order to make sure there won't be any trouble on loops using count() + $this->children = array_values($this->children); + return true; + } + } + logger('[WARN] Item::removeChild : Item is not a child ('. $id .').', LOGGER_DEBUG); + return false; + } + + /** + * Get parent item + * + * @return object + */ + protected function getParent() + { + return $this->parent; + } + + /** + * Set conversation + * + * @param object $conv The conversation + * + * @return void + */ + public function setConversation($conv) + { + $previous_mode = ($this->conversation ? $this->conversation->getMode() : ''); + + $this->conversation = $conv; + + // Set it on our children too + foreach ($this->getChildren() as $child) { + $child->setConversation($conv); + } + } + + /** + * Get conversation + * + * @return object + */ + public function getConversation() + { + return $this->conversation; + } + + /** + * Get raw data + * + * We shouldn't need this + * + * @return array + */ + public function getData() + { + return $this->data; + } + + /** + * Get a data value + * + * @param object $name key + * + * @return mixed value on success + * false on failure + */ + public function getDataValue($name) + { + if (!isset($this->data[$name])) { + // logger('[ERROR] Item::getDataValue : Item has no value name "'. $name .'".', LOGGER_DEBUG); + return false; + } + + return $this->data[$name]; + } + + /** + * Set template + * + * @param object $name template name + * + * @return void + */ + private function setTemplate($name) + { + if (!x($this->available_templates, $name)) { + logger('[ERROR] Item::setTemplate : Template not available ("'. $name .'").', LOGGER_DEBUG); + return false; + } + + $this->template = $this->available_templates[$name]; + } + + /** + * Get template + * + * @return object + */ + private function getTemplate() + { + return $this->template; + } + + /** + * Check if this is a toplevel post + * + * @return boolean + */ + private function isToplevel() + { + return $this->toplevel; + } + + /** + * Check if this is writable + * + * @return boolean + */ + private function isWritable() + { + $conv = $this->getConversation(); + + if ($conv) { + // This will allow us to comment on wall-to-wall items owned by our friends + // and community forums even if somebody else wrote the post. + + // bug #517 - this fixes for conversation owner + if ($conv->getMode() == 'profile' && $conv->getProfileOwner() == local_user()) { + return true; + } + + // this fixes for visitors + return ($this->writable || ($this->isVisiting() && $conv->getMode() == 'profile')); + } + return $this->writable; + } + + /** + * Count the total of our descendants + * + * @return integer + */ + private function countDescendants() + { + $children = $this->getChildren(); + $total = count($children); + if ($total > 0) { + foreach ($children as $child) { + $total += $child->countDescendants(); + } + } + + return $total; + } + + /** + * Get the template for the comment box + * + * @return string + */ + private function getCommentBoxTemplate() + { + return $this->comment_box_template; + } + + /** + * Get the comment box + * + * @param string $indent Indent value + * + * @return mixed The comment box string (empty if no comment box) + * false on failure + */ + private function getCommentBox($indent) + { + $a = self::getApp(); + + $comment_box = ''; + $conv = $this->getConversation(); + $template = get_markup_template($this->getCommentBoxTemplate()); + $ww = ''; + if (($conv->getMode() === 'network') && $this->isWallToWall()) { + $ww = 'ww'; + } + + if ($conv->isWritable() && $this->isWritable()) { + $qc = $qcomment = null; + + /* + * Hmmm, code depending on the presence of a particular plugin? + * This should be better if done by a hook + */ + if (in_array('qcomment', $a->plugins)) { + $qc = ((local_user()) ? PConfig::get(local_user(), 'qcomment', 'words') : null); + $qcomment = (($qc) ? explode("\n", $qc) : null); + } + + $comment_box = replace_macros( + $template, + array( + '$return_path' => $a->query_string, + '$threaded' => $this->isThreaded(), + // '$jsreload' => (($conv->getMode() === 'display') ? $_SESSION['return_url'] : ''), + '$jsreload' => '', + '$type' => (($conv->getMode() === 'profile') ? 'wall-comment' : 'net-comment'), + '$id' => $this->getId(), + '$parent' => $this->getId(), + '$qcomment' => $qcomment, + '$profile_uid' => $conv->getProfileOwner(), + '$mylink' => $a->remove_baseurl($a->contact['url']), + '$mytitle' => t('This is you'), + '$myphoto' => $a->remove_baseurl($a->contact['thumb']), + '$comment' => t('Comment'), + '$submit' => t('Submit'), + '$edbold' => t('Bold'), + '$editalic' => t('Italic'), + '$eduline' => t('Underline'), + '$edquote' => t('Quote'), + '$edcode' => t('Code'), + '$edimg' => t('Image'), + '$edurl' => t('Link'), + '$edvideo' => t('Video'), + '$preview' => ((Feature::isEnabled($conv->getProfileOwner(), 'preview')) ? t('Preview') : ''), + '$indent' => $indent, + '$sourceapp' => t($a->sourcename), + '$ww' => (($conv->getMode() === 'network') ? $ww : ''), + '$rand_num' => random_digits(12)) + ); + } + + return $comment_box; + } + + /** + * @return string + */ + private function getRedirectUrl() + { + return $this->redirect_url; + } + + /** + * Check if we are a wall to wall item and set the relevant properties + * + * @return void + */ + protected function checkWallToWall() + { + $a = self::getApp(); + $conv = $this->getConversation(); + $this->wall_to_wall = false; + + if ($this->isToplevel()) { + if ($conv->getMode() !== 'profile') { + if ($this->getDataValue('wall') && !$this->getDataValue('self')) { + // On the network page, I am the owner. On the display page it will be the profile owner. + // This will have been stored in $a->page_contact by our calling page. + // Put this person as the wall owner of the wall-to-wall notice. + + $this->owner_url = zrl($a->page_contact['url']); + $this->owner_photo = $a->page_contact['thumb']; + $this->owner_name = $a->page_contact['name']; + $this->wall_to_wall = true; + } elseif ($this->getDataValue('owner-link')) { + $owner_linkmatch = (($this->getDataValue('owner-link')) && link_compare($this->getDataValue('owner-link'), $this->getDataValue('author-link'))); + $alias_linkmatch = (($this->getDataValue('alias')) && link_compare($this->getDataValue('alias'), $this->getDataValue('author-link'))); + $owner_namematch = (($this->getDataValue('owner-name')) && $this->getDataValue('owner-name') == $this->getDataValue('author-name')); + + if ((! $owner_linkmatch) && (! $alias_linkmatch) && (! $owner_namematch)) { + // The author url doesn't match the owner (typically the contact) + // and also doesn't match the contact alias. + // The name match is a hack to catch several weird cases where URLs are + // all over the park. It can be tricked, but this prevents you from + // seeing "Bob Smith to Bob Smith via Wall-to-wall" and you know darn + // well that it's the same Bob Smith. + + // But it could be somebody else with the same name. It just isn't highly likely. + + + $this->owner_photo = $this->getDataValue('owner-avatar'); + $this->owner_name = $this->getDataValue('owner-name'); + $this->wall_to_wall = true; + // If it is our contact, use a friendly redirect link + if ((link_compare($this->getDataValue('owner-link'), $this->getDataValue('url'))) + && ($this->getDataValue('network') === NETWORK_DFRN) + ) { + $this->owner_url = $this->getRedirectUrl(); + } else { + $this->owner_url = zrl($this->getDataValue('owner-link')); + } + } + } + } + } + + if (!$this->wall_to_wall) { + $this->setTemplate('wall'); + $this->owner_url = ''; + $this->owner_photo = ''; + $this->owner_name = ''; + } + } + + /** + * @return boolean + */ + private function isWallToWall() + { + return $this->wall_to_wall; + } + + /** + * @return string + */ + private function getOwnerUrl() + { + return $this->owner_url; + } + + /** + * @return string + */ + private function getOwnerPhoto() + { + return $this->owner_photo; + } + + /** + * @return string + */ + private function getOwnerName() + { + return $this->owner_name; + } + + /** + * @return boolean + */ + private function isVisiting() + { + return $this->visiting; + } +} diff --git a/src/Object/Photo.php b/src/Object/Photo.php new file mode 100644 index 0000000000..a8bb3b4ada --- /dev/null +++ b/src/Object/Photo.php @@ -0,0 +1,1166 @@ + 'jpg', + 'image/png' => 'png', + 'image/gif' => 'gif' + ); + } else { + $t = array(); + $t['image/jpeg'] ='jpg'; + if (imagetypes() & IMG_PNG) { + $t['image/png'] = 'png'; + } + } + + return $t; + } + + /** + * @brief Constructor + * @param object $data data + * @param boolean $type optional, default null + * @return object + */ + public function __construct($data, $type = null) + { + $this->imagick = class_exists('Imagick'); + $this->types = static::supportedTypes(); + if (!array_key_exists($type, $this->types)) { + $type='image/jpeg'; + } + $this->type = $type; + + if ($this->isImagick() && $this->loadData($data)) { + return true; + } else { + // Failed to load with Imagick, fallback + $this->imagick = false; + } + return $this->loadData($data); + } + + /** + * @brief Destructor + * @return void + */ + public function __destruct() + { + if ($this->image) { + if ($this->isImagick()) { + $this->image->clear(); + $this->image->destroy(); + return; + } + if (is_resource($this->image)) { + imagedestroy($this->image); + } + } + } + + /** + * @return boolean + */ + public function isImagick() + { + return $this->imagick; + } + + /** + * @brief Maps Mime types to Imagick formats + * @return arr With with image formats (mime type as key) + */ + public static function getFormatsMap() + { + $m = array( + 'image/jpeg' => 'JPG', + 'image/png' => 'PNG', + 'image/gif' => 'GIF' + ); + return $m; + } + + /** + * @param object $data data + * @return boolean + */ + private function loadData($data) + { + if ($this->isImagick()) { + $this->image = new Imagick(); + try { + $this->image->readImageBlob($data); + } catch (Exception $e) { + // Imagick couldn't use the data + return false; + } + + /* + * Setup the image to the format it will be saved to + */ + $map = self::getFormatsMap(); + $format = $map[$type]; + $this->image->setFormat($format); + + // Always coalesce, if it is not a multi-frame image it won't hurt anyway + $this->image = $this->image->coalesceImages(); + + /* + * setup the compression here, so we'll do it only once + */ + switch ($this->getType()) { + case "image/png": + $quality = Config::get('system', 'png_quality'); + if ((! $quality) || ($quality > 9)) { + $quality = PNG_QUALITY; + } + /* + * From http://www.imagemagick.org/script/command-line-options.php#quality: + * + * 'For the MNG and PNG image formats, the quality value sets + * the zlib compression level (quality / 10) and filter-type (quality % 10). + * The default PNG "quality" is 75, which means compression level 7 with adaptive PNG filtering, + * unless the image has a color map, in which case it means compression level 7 with no PNG filtering' + */ + $quality = $quality * 10; + $this->image->setCompressionQuality($quality); + break; + case "image/jpeg": + $quality = Config::get('system', 'jpeg_quality'); + if ((! $quality) || ($quality > 100)) { + $quality = JPEG_QUALITY; + } + $this->image->setCompressionQuality($quality); + } + + // The 'width' and 'height' properties are only used by non-Imagick routines. + $this->width = $this->image->getImageWidth(); + $this->height = $this->image->getImageHeight(); + $this->valid = true; + + return true; + } + + $this->valid = false; + $this->image = @imagecreatefromstring($data); + if ($this->image !== false) { + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + $this->valid = true; + imagealphablending($this->image, false); + imagesavealpha($this->image, true); + + return true; + } + + return false; + } + + /** + * @return boolean + */ + public function isValid() + { + if ($this->isImagick()) { + return ($this->image !== false); + } + return $this->valid; + } + + /** + * @return mixed + */ + public function getWidth() + { + if (!$this->isValid()) { + return false; + } + + if ($this->isImagick()) { + return $this->image->getImageWidth(); + } + return $this->width; + } + + /** + * @return mixed + */ + public function getHeight() + { + if (!$this->isValid()) { + return false; + } + + if ($this->isImagick()) { + return $this->image->getImageHeight(); + } + return $this->height; + } + + /** + * @return mixed + */ + public function getImage() + { + if (!$this->isValid()) { + return false; + } + + if ($this->isImagick()) { + /* Clean it */ + $this->image = $this->image->deconstructImages(); + return $this->image; + } + return $this->image; + } + + /** + * @return mixed + */ + public function getType() + { + if (!$this->isValid()) { + return false; + } + + return $this->type; + } + + /** + * @return mixed + */ + public function getExt() + { + if (!$this->isValid()) { + return false; + } + + return $this->types[$this->getType()]; + } + + /** + * @param integer $max max dimension + * @return mixed + */ + public function scaleImage($max) + { + if (!$this->isValid()) { + return false; + } + + $width = $this->getWidth(); + $height = $this->getHeight(); + + $dest_width = $dest_height = 0; + + if ((! $width)|| (! $height)) { + return false; + } + + if ($width > $max && $height > $max) { + // very tall image (greater than 16:9) + // constrain the width - let the height float. + + if ((($height * 9) / 16) > $width) { + $dest_width = $max; + $dest_height = intval(($height * $max) / $width); + } elseif ($width > $height) { + // else constrain both dimensions + $dest_width = $max; + $dest_height = intval(($height * $max) / $width); + } else { + $dest_width = intval(($width * $max) / $height); + $dest_height = $max; + } + } else { + if ($width > $max) { + $dest_width = $max; + $dest_height = intval(($height * $max) / $width); + } else { + if ($height > $max) { + // very tall image (greater than 16:9) + // but width is OK - don't do anything + + if ((($height * 9) / 16) > $width) { + $dest_width = $width; + $dest_height = $height; + } else { + $dest_width = intval(($width * $max) / $height); + $dest_height = $max; + } + } else { + $dest_width = $width; + $dest_height = $height; + } + } + } + + + if ($this->isImagick()) { + /* + * If it is not animated, there will be only one iteration here, + * so don't bother checking + */ + // Don't forget to go back to the first frame + $this->image->setFirstIterator(); + do { + // FIXME - implement horizantal bias for scaling as in followin GD functions + // to allow very tall images to be constrained only horizontally. + + $this->image->scaleImage($dest_width, $dest_height); + } while ($this->image->nextImage()); + + // These may not be necessary any more + $this->width = $this->image->getImageWidth(); + $this->height = $this->image->getImageHeight(); + + return; + } + + + $dest = imagecreatetruecolor($dest_width, $dest_height); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') { + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + } + imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); + if ($this->image) { + imagedestroy($this->image); + } + $this->image = $dest; + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + } + + /** + * @param integer $degrees degrees to rotate image + * @return mixed + */ + public function rotate($degrees) + { + if (!$this->isValid()) { + return false; + } + + if ($this->isImagick()) { + $this->image->setFirstIterator(); + do { + $this->image->rotateImage(new ImagickPixel(), -$degrees); // ImageMagick rotates in the opposite direction of imagerotate() + } while ($this->image->nextImage()); + return; + } + + // if script dies at this point check memory_limit setting in php.ini + $this->image = imagerotate($this->image, $degrees, 0); + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + } + + /** + * @param boolean $horiz optional, default true + * @param boolean $vert optional, default false + * @return mixed + */ + public function flip($horiz = true, $vert = false) + { + if (!$this->isValid()) { + return false; + } + + if ($this->isImagick()) { + $this->image->setFirstIterator(); + do { + if ($horiz) { + $this->image->flipImage(); + } + if ($vert) { + $this->image->flopImage(); + } + } while ($this->image->nextImage()); + return; + } + + $w = imagesx($this->image); + $h = imagesy($this->image); + $flipped = imagecreate($w, $h); + if ($horiz) { + for ($x = 0; $x < $w; $x++) { + imagecopy($flipped, $this->image, $x, 0, $w - $x - 1, 0, 1, $h); + } + } + if ($vert) { + for ($y = 0; $y < $h; $y++) { + imagecopy($flipped, $this->image, 0, $y, 0, $h - $y - 1, $w, 1); + } + } + $this->image = $flipped; + } + + /** + * @param string $filename filename + * @return mixed + */ + public function orient($filename) + { + if ($this->isImagick()) { + // based off comment on http://php.net/manual/en/imagick.getimageorientation.php + $orientation = $this->image->getImageOrientation(); + switch ($orientation) { + case Imagick::ORIENTATION_BOTTOMRIGHT: + $this->image->rotateimage("#000", 180); + break; + case Imagick::ORIENTATION_RIGHTTOP: + $this->image->rotateimage("#000", 90); + break; + case Imagick::ORIENTATION_LEFTBOTTOM: + $this->image->rotateimage("#000", -90); + break; + } + + $this->image->setImageOrientation(Imagick::ORIENTATION_TOPLEFT); + return true; + } + // based off comment on http://php.net/manual/en/function.imagerotate.php + + if (!$this->isValid()) { + return false; + } + + if ((!function_exists('exif_read_data')) || ($this->getType() !== 'image/jpeg')) { + return; + } + + $exif = @exif_read_data($filename, null, true); + if (!$exif) { + return; + } + + $ort = $exif['IFD0']['Orientation']; + + switch ($ort) { + case 1: // nothing + break; + + case 2: // horizontal flip + $this->flip(); + break; + + case 3: // 180 rotate left + $this->rotate(180); + break; + + case 4: // vertical flip + $this->flip(false, true); + break; + + case 5: // vertical flip + 90 rotate right + $this->flip(false, true); + $this->rotate(-90); + break; + + case 6: // 90 rotate right + $this->rotate(-90); + break; + + case 7: // horizontal flip + 90 rotate right + $this->flip(); + $this->rotate(-90); + break; + + case 8: // 90 rotate left + $this->rotate(90); + break; + } + + // logger('exif: ' . print_r($exif,true)); + return $exif; + } + + /** + * @param integer $min minimum dimension + * @return mixed + */ + public function scaleImageUp($min) + { + if (!$this->isValid()) { + return false; + } + + $width = $this->getWidth(); + $height = $this->getHeight(); + + $dest_width = $dest_height = 0; + + if ((!$width)|| (!$height)) { + return false; + } + + if ($width < $min && $height < $min) { + if ($width > $height) { + $dest_width = $min; + $dest_height = intval(($height * $min) / $width); + } else { + $dest_width = intval(($width * $min) / $height); + $dest_height = $min; + } + } else { + if ($width < $min) { + $dest_width = $min; + $dest_height = intval(($height * $min) / $width); + } else { + if ($height < $min) { + $dest_width = intval(($width * $min) / $height); + $dest_height = $min; + } else { + $dest_width = $width; + $dest_height = $height; + } + } + } + + if ($this->isImagick()) { + return $this->scaleImage($dest_width, $dest_height); + } + + $dest = imagecreatetruecolor($dest_width, $dest_height); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') { + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + } + imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); + if ($this->image) { + imagedestroy($this->image); + } + $this->image = $dest; + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + } + + /** + * @param integer $dim dimension + * @return mixed + */ + public function scaleImageSquare($dim) + { + if (!$this->isValid()) { + return false; + } + + if ($this->isImagick()) { + $this->image->setFirstIterator(); + do { + $this->image->scaleImage($dim, $dim); + } while ($this->image->nextImage()); + return; + } + + $dest = imagecreatetruecolor($dim, $dim); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') { + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + } + imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dim, $dim, $this->width, $this->height); + if ($this->image) { + imagedestroy($this->image); + } + $this->image = $dest; + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + } + + /** + * @param integer $max maximum + * @param integer $x x coordinate + * @param integer $y y coordinate + * @param integer $w width + * @param integer $h height + * @return mixed + */ + public function cropImage($max, $x, $y, $w, $h) + { + if (!$this->isValid()) { + return false; + } + + if ($this->isImagick()) { + $this->image->setFirstIterator(); + do { + $this->image->cropImage($w, $h, $x, $y); + /* + * We need to remove the canva, + * or the image is not resized to the crop: + * http://php.net/manual/en/imagick.cropimage.php#97232 + */ + $this->image->setImagePage(0, 0, 0, 0); + } while ($this->image->nextImage()); + return $this->scaleImage($max); + } + + $dest = imagecreatetruecolor($max, $max); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') { + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + } + imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $max, $max, $w, $h); + if ($this->image) { + imagedestroy($this->image); + } + $this->image = $dest; + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + } + + /** + * @param string $path file path + * @return mixed + */ + public function saveImage($path) + { + if (!$this->isValid()) { + return false; + } + + $string = $this->imageString(); + + $a = get_app(); + + $stamp1 = microtime(true); + file_put_contents($path, $string); + $a->save_timestamp($stamp1, "file"); + } + + /** + * @return mixed + */ + public function imageString() + { + if (!$this->isValid()) { + return false; + } + + if ($this->isImagick()) { + /* Clean it */ + $this->image = $this->image->deconstructImages(); + $string = $this->image->getImagesBlob(); + return $string; + } + + $quality = false; + + ob_start(); + + // Enable interlacing + imageinterlace($this->image, true); + + switch ($this->getType()) { + case "image/png": + $quality = Config::get('system', 'png_quality'); + if ((!$quality) || ($quality > 9)) { + $quality = PNG_QUALITY; + } + imagepng($this->image, null, $quality); + break; + case "image/jpeg": + $quality = Config::get('system', 'jpeg_quality'); + if ((!$quality) || ($quality > 100)) { + $quality = JPEG_QUALITY; + } + imagejpeg($this->image, null, $quality); + } + $string = ob_get_contents(); + ob_end_clean(); + + return $string; + } + + /** + * @param integer $uid uid + * @param integer $cid cid + * @param integer $rid rid + * @param string $filename filename + * @param string $album album name + * @param integer $scale scale + * @param integer $profile optional, default = 0 + * @param string $allow_cid optional, default = '' + * @param string $allow_gid optional, default = '' + * @param string $deny_cid optional, default = '' + * @param string $deny_gid optional, default = '' + * @param string $desc optional, default = '' + * @return object + */ + public function store($uid, $cid, $rid, $filename, $album, $scale, $profile = 0, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '', $desc = '') + { + $r = dba::select('photo', array('guid'), array("`resource-id` = ? AND `guid` != ?", $rid, ''), array('limit' => 1)); + if (DBM::is_result($r)) { + $guid = $r['guid']; + } else { + $guid = get_guid(); + } + + $x = dba::select('photo', array('id'), array('resource-id' => $rid, 'uid' => $uid, 'contact-id' => $cid, 'scale' => $scale), array('limit' => 1)); + + $fields = array('uid' => $uid, 'contact-id' => $cid, 'guid' => $guid, 'resource-id' => $rid, 'created' => datetime_convert(), 'edited' => datetime_convert(), + 'filename' => basename($filename), 'type' => $this->getType(), 'album' => $album, 'height' => $this->getHeight(), 'width' => $this->getWidth(), + 'datasize' => strlen($this->imageString()), 'data' => $this->imageString(), 'scale' => $scale, 'profile' => $profile, + 'allow_cid' => $allow_cid, 'allow_gid' => $allow_gid, 'deny_cid' => $deny_cid, 'deny_gid' => $deny_gid, 'desc' => $desc); + + if (DBM::is_result($x)) { + $r = dba::update('photo', $fields, array('id' => $x['id'])); + } else { + $r = dba::insert('photo', $fields); + } + + return $r; + } + + /** + * Guess image mimetype from filename or from Content-Type header + * + * @param string $filename Image filename + * @param boolean $fromcurl Check Content-Type header from curl request + * + * @return object + */ + public static function guessImageType($filename, $fromcurl = false) + { + logger('Photo: guessImageType: '.$filename . ($fromcurl?' from curl headers':''), LOGGER_DEBUG); + $type = null; + if ($fromcurl) { + $a = get_app(); + $headers=array(); + $h = explode("\n", $a->get_curl_headers()); + foreach ($h as $l) { + list($k,$v) = array_map("trim", explode(":", trim($l), 2)); + $headers[$k] = $v; + } + if (array_key_exists('Content-Type', $headers)) + $type = $headers['Content-Type']; + } + if (is_null($type)) { + // Guessing from extension? Isn't that... dangerous? + if (class_exists('Imagick') && file_exists($filename) && is_readable($filename)) { + /** + * Well, this not much better, + * but at least it comes from the data inside the image, + * we won't be tricked by a manipulated extension + */ + $image = new Imagick($filename); + $type = $image->getImageMimeType(); + $image->setInterlaceScheme(Imagick::INTERLACE_PLANE); + } else { + $ext = pathinfo($filename, PATHINFO_EXTENSION); + $types = self::supportedTypes(); + $type = "image/jpeg"; + foreach ($types as $m => $e) { + if ($ext == $e) { + $type = $m; + } + } + } + } + logger('Photo: guessImageType: type='.$type, LOGGER_DEBUG); + return $type; + } + + /** + * @param string $photo photo + * @param integer $uid user id + * @param integer $cid contact id + * @param boolean $quit_on_error optional, default false + * @return array + */ + public static function importProfilePhoto($photo, $uid, $cid, $quit_on_error = false) + { + $r = dba::select( + 'photo', + array('resource-id'), + array('uid' => $uid, 'contact-id' => $cid, 'scale' => 4, 'album' => 'Contact Photos'), + array('limit' => 1) + ); + + if (DBM::is_result($r) && strlen($r['resource-id'])) { + $hash = $r['resource-id']; + } else { + $hash = photo_new_resource(); + } + + $photo_failure = false; + + $filename = basename($photo); + $img_str = fetch_url($photo, true); + + if ($quit_on_error && ($img_str == "")) { + return false; + } + + $type = self::guessImageType($photo, true); + $img = new Photo($img_str, $type); + if ($img->isValid()) { + $img->scaleImageSquare(175); + + $r = $img->store($uid, $cid, $hash, $filename, 'Contact Photos', 4); + + if ($r === false) { + $photo_failure = true; + } + + $img->scaleImage(80); + + $r = $img->store($uid, $cid, $hash, $filename, 'Contact Photos', 5); + + if ($r === false) { + $photo_failure = true; + } + + $img->scaleImage(48); + + $r = $img->store($uid, $cid, $hash, $filename, 'Contact Photos', 6); + + if ($r === false) { + $photo_failure = true; + } + + $suffix = '?ts='.time(); + + $photo = System::baseUrl() . '/photo/' . $hash . '-4.' . $img->getExt() . $suffix; + $thumb = System::baseUrl() . '/photo/' . $hash . '-5.' . $img->getExt() . $suffix; + $micro = System::baseUrl() . '/photo/' . $hash . '-6.' . $img->getExt() . $suffix; + + // Remove the cached photo + $a = get_app(); + $basepath = $a->get_basepath(); + + if (is_dir($basepath."/photo")) { + $filename = $basepath.'/photo/'.$hash.'-4.'.$img->getExt(); + if (file_exists($filename)) { + unlink($filename); + } + $filename = $basepath.'/photo/'.$hash.'-5.'.$img->getExt(); + if (file_exists($filename)) { + unlink($filename); + } + $filename = $basepath.'/photo/'.$hash.'-6.'.$img->getExt(); + if (file_exists($filename)) { + unlink($filename); + } + } + } else { + $photo_failure = true; + } + + if ($photo_failure && $quit_on_error) { + return false; + } + + if ($photo_failure) { + $photo = System::baseUrl() . '/images/person-175.jpg'; + $thumb = System::baseUrl() . '/images/person-80.jpg'; + $micro = System::baseUrl() . '/images/person-48.jpg'; + } + + return array($photo, $thumb, $micro); + } + + /** + * @param string $url url + * @return object + */ + public static function getInfoFromURL($url) + { + $data = array(); + + $data = Cache::get($url); + + if (is_null($data) || !$data || !is_array($data)) { + $img_str = fetch_url($url, true, $redirects, 4); + $filesize = strlen($img_str); + + if (function_exists("getimagesizefromstring")) { + $data = getimagesizefromstring($img_str); + } else { + $tempfile = tempnam(get_temppath(), "cache"); + + $a = get_app(); + $stamp1 = microtime(true); + file_put_contents($tempfile, $img_str); + $a->save_timestamp($stamp1, "file"); + + $data = getimagesize($tempfile); + unlink($tempfile); + } + + if ($data) { + $data["size"] = $filesize; + } + + Cache::set($url, $data); + } + + return $data; + } + + /** + * @param integer $width width + * @param integer $height height + * @param integer $max max + * @return array + */ + public static function scaleImageTo($width, $height, $max) + { + $dest_width = $dest_height = 0; + + if ((!$width) || (!$height)) { + return false; + } + + if ($width > $max && $height > $max) { + // very tall image (greater than 16:9) + // constrain the width - let the height float. + + if ((($height * 9) / 16) > $width) { + $dest_width = $max; + $dest_height = intval(($height * $max) / $width); + } elseif ($width > $height) { + // else constrain both dimensions + $dest_width = $max; + $dest_height = intval(($height * $max) / $width); + } else { + $dest_width = intval(($width * $max) / $height); + $dest_height = $max; + } + } else { + if ($width > $max) { + $dest_width = $max; + $dest_height = intval(($height * $max) / $width); + } else { + if ($height > $max) { + // very tall image (greater than 16:9) + // but width is OK - don't do anything + + if ((($height * 9) / 16) > $width) { + $dest_width = $width; + $dest_height = $height; + } else { + $dest_width = intval(($width * $max) / $height); + $dest_height = $max; + } + } else { + $dest_width = $width; + $dest_height = $height; + } + } + } + return array("width" => $dest_width, "height" => $dest_height); + } + + /** + * @brief This function is used by the fromgplus addon + * @param object $a App + * @param integer $uid user id + * @param string $imagedata optional, default empty + * @param string $url optional, default empty + * @return array + */ + public static function storePhoto(App $a, $uid, $imagedata = "", $url = "") + { + $r = q( + "SELECT `user`.`nickname`, `user`.`page-flags`, `contact`.`id` FROM `user` INNER JOIN `contact` on `user`.`uid` = `contact`.`uid` + WHERE `user`.`uid` = %d AND `user`.`blocked` = 0 AND `contact`.`self` = 1 LIMIT 1", + intval($uid) + ); + + if (!DBM::is_result($r)) { + logger("Can't detect user data for uid ".$uid, LOGGER_DEBUG); + return(array()); + } + + $page_owner_nick = $r[0]['nickname']; + + /// @TODO + /// $default_cid = $r[0]['id']; + /// $community_page = (($r[0]['page-flags'] == PAGE_COMMUNITY) ? true : false); + + if ((strlen($imagedata) == 0) && ($url == "")) { + logger("No image data and no url provided", LOGGER_DEBUG); + return(array()); + } elseif (strlen($imagedata) == 0) { + logger("Uploading picture from ".$url, LOGGER_DEBUG); + + $stamp1 = microtime(true); + $imagedata = @file_get_contents($url); + $a->save_timestamp($stamp1, "file"); + } + + $maximagesize = Config::get('system', 'maximagesize'); + + if (($maximagesize) && (strlen($imagedata) > $maximagesize)) { + logger("Image exceeds size limit of ".$maximagesize, LOGGER_DEBUG); + return(array()); + } + + $tempfile = tempnam(get_temppath(), "cache"); + + $stamp1 = microtime(true); + file_put_contents($tempfile, $imagedata); + $a->save_timestamp($stamp1, "file"); + + $data = getimagesize($tempfile); + + if (!isset($data["mime"])) { + unlink($tempfile); + logger("File is no picture", LOGGER_DEBUG); + return(array()); + } + + $ph = new Photo($imagedata, $data["mime"]); + + if (!$ph->isValid()) { + unlink($tempfile); + logger("Picture is no valid picture", LOGGER_DEBUG); + return(array()); + } + + $ph->orient($tempfile); + unlink($tempfile); + + $max_length = Config::get('system', 'max_image_length'); + if (! $max_length) { + $max_length = MAX_IMAGE_LENGTH; + } + + if ($max_length > 0) { + $ph->scaleImage($max_length); + } + + $width = $ph->getWidth(); + $height = $ph->getHeight(); + + $hash = photo_new_resource(); + + $smallest = 0; + + // Pictures are always public by now + //$defperm = '<'.$default_cid.'>'; + $defperm = ""; + $visitor = 0; + + $r = $ph->store($uid, $visitor, $hash, $tempfile, t('Wall Photos'), 0, 0, $defperm); + + if (!$r) { + logger("Picture couldn't be stored", LOGGER_DEBUG); + return(array()); + } + + $image = array("page" => System::baseUrl().'/photos/'.$page_owner_nick.'/image/'.$hash, + "full" => System::baseUrl()."/photo/{$hash}-0.".$ph->getExt()); + + if ($width > 800 || $height > 800) { + $image["large"] = System::baseUrl()."/photo/{$hash}-0.".$ph->getExt(); + } + + if ($width > 640 || $height > 640) { + $ph->scaleImage(640); + $r = $ph->store($uid, $visitor, $hash, $tempfile, t('Wall Photos'), 1, 0, $defperm); + if ($r) { + $image["medium"] = System::baseUrl()."/photo/{$hash}-1.".$ph->getExt(); + } + } + + if ($width > 320 || $height > 320) { + $ph->scaleImage(320); + $r = $ph->store($uid, $visitor, $hash, $tempfile, t('Wall Photos'), 2, 0, $defperm); + if ($r) { + $image["small"] = System::baseUrl()."/photo/{$hash}-2.".$ph->getExt(); + } + } + + if ($width > 160 && $height > 160) { + $x = 0; + $y = 0; + + $min = $ph->getWidth(); + if ($min > 160) { + $x = ($min - 160) / 2; + } + + if ($ph->getHeight() < $min) { + $min = $ph->getHeight(); + if ($min > 160) { + $y = ($min - 160) / 2; + } + } + + $min = 160; + $ph->cropImage(160, $x, $y, $min, $min); + + $r = $ph->store($uid, $visitor, $hash, $tempfile, t('Wall Photos'), 3, 0, $defperm); + if ($r) { + $image["thumb"] = System::baseUrl()."/photo/{$hash}-3.".$ph->getExt(); + } + } + + // Set the full image as preview image. This will be overwritten, if the picture is larger than 640. + $image["preview"] = $image["full"]; + + // Deactivated, since that would result in a cropped preview, if the picture wasn't larger than 320 + //if (isset($image["thumb"])) + // $image["preview"] = $image["thumb"]; + + // Unsure, if this should be activated or deactivated + //if (isset($image["small"])) + // $image["preview"] = $image["small"]; + + if (isset($image["medium"])) { + $image["preview"] = $image["medium"]; + } + + return($image); + } +} diff --git a/src/Object/Post.php b/src/Object/Post.php deleted file mode 100644 index 231f2a5b84..0000000000 --- a/src/Object/Post.php +++ /dev/null @@ -1,906 +0,0 @@ - 'wall_thread.tpl', - 'wall2wall' => 'wallwall_thread.tpl' - ); - private $comment_box_template = 'comment_item.tpl'; - private $toplevel = false; - private $writable = false; - private $children = array(); - private $parent = null; - private $thread = null; - private $redirect_url = null; - private $owner_url = ''; - private $owner_photo = ''; - private $owner_name = ''; - private $wall_to_wall = false; - private $threaded = false; - private $visiting = false; - - /** - * Constructor - * - * @param array $data data array - */ - public function __construct($data) - { - $a = self::getApp(); - - $this->data = $data; - $this->setTemplate('wall'); - $this->toplevel = ($this->getId() == $this->getDataValue('parent')); - - if (is_array($_SESSION['remote'])) { - foreach ($_SESSION['remote'] as $visitor) { - if ($visitor['cid'] == $this->getDataValue('contact-id')) { - $this->visiting = true; - break; - } - } - } - - $this->writable = ($this->getDataValue('writable') || $this->getDataValue('self')); - - $ssl_state = ((local_user()) ? true : false); - $this->redirect_url = 'redir/' . $this->getDataValue('cid'); - - if (!$this->isToplevel()) { - $this->threaded = true; - } - - // Prepare the children - if (count($data['children'])) { - foreach ($data['children'] as $item) { - /* - * Only add will be displayed - */ - if ($item['network'] === NETWORK_MAIL && local_user() != $item['uid']) { - continue; - } elseif (! visible_activity($item)) { - continue; - } - - // You can always comment on Diaspora items - if (($item['network'] == NETWORK_DIASPORA) && (local_user() == $item['uid'])) { - $item['writable'] = true; - } - - $item['pagedrop'] = $data['pagedrop']; - $child = new Item($item); - $this->addChild($child); - } - } - } - - /** - * Get data in a form usable by a conversation template - * - * @param object $conv_responses conversation responses - * @param integer $thread_level default = 1 - * - * @return mixed The data requested on success - * false on failure - */ - public function getTemplateData($conv_responses, $thread_level = 1) - { - require_once "mod/proxy.php"; - - $result = array(); - - $a = self::getApp(); - - $item = $this->getData(); - $edited = false; - // If the time between "created" and "edited" differs we add - // a notice that the post was edited. - // Note: In some networks reshared items seem to have (sometimes) a difference - // between creation time and edit time of a second. Thats why we add the notice - // only if the difference is more than 1 second. - if (strtotime($item['edited']) - strtotime($item['created']) > 1) { - $edited = array( - 'label' => t('This entry was edited'), - 'date' => datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r'), - 'relative' => relative_date($item['edited']) - ); - } - $commentww = ''; - $sparkle = ''; - $buttons = ''; - $dropping = false; - $star = false; - $ignore = false; - $isstarred = "unstarred"; - $indent = ''; - $shiny = ''; - $osparkle = ''; - $total_children = $this->countDescendants(); - - $conv = $this->getThread(); - - $lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid']) - || strlen($item['deny_cid']) || strlen($item['deny_gid'])))) - ? t('Private Message') - : false); - $shareable = ((($conv->getProfileOwner() == local_user()) && ($item['private'] != 1)) ? true : false); - if (local_user() && link_compare($a->contact['url'], $item['author-link'])) { - if ($item["event-id"] != 0) { - $edpost = array("events/event/".$item['event-id'], t("Edit")); - } else { - $edpost = array("editpost/".$item['id'], t("Edit")); - } - } else { - $edpost = false; - } - - if (($this->getDataValue('uid') == local_user()) || $this->isVisiting()) { - $dropping = true; - } - - $drop = array( - 'dropping' => $dropping, - 'pagedrop' => ((Feature::isEnabled($conv->getProfileOwner(), 'multi_delete')) ? $item['pagedrop'] : ''), - 'select' => t('Select'), - 'delete' => t('Delete'), - ); - - $filer = (($conv->getProfileOwner() == local_user()) ? t("save to folder") : false); - - $diff_author = ((link_compare($item['url'], $item['author-link'])) ? false : true); - $profile_name = htmlentities(((strlen($item['author-name'])) && $diff_author) ? $item['author-name'] : $item['name']); - if ($item['author-link'] && (! $item['author-name'])) { - $profile_name = $item['author-link']; - } - - $sp = false; - $profile_link = best_link_url($item, $sp); - if ($profile_link === 'mailbox') { - $profile_link = ''; - } - - if ($sp) { - $sparkle = ' sparkle'; - } else { - $profile_link = zrl($profile_link); - } - - if (!isset($item['author-thumb']) || ($item['author-thumb'] == "")) { - $author_contact = Contact::getDetailsByURL($item['author-link'], $conv->getProfileOwner()); - if ($author_contact["thumb"]) { - $item['author-thumb'] = $author_contact["thumb"]; - } else { - $item['author-thumb'] = $item['author-avatar']; - } - } - - if (!isset($item['owner-thumb']) || ($item['owner-thumb'] == "")) { - $owner_contact = Contact::getDetailsByURL($item['owner-link'], $conv->getProfileOwner()); - if ($owner_contact["thumb"]) { - $item['owner-thumb'] = $owner_contact["thumb"]; - } else { - $item['owner-thumb'] = $item['owner-avatar']; - } - } - - $locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => ''); - call_hooks('render_location', $locate); - $location = ((strlen($locate['html'])) ? $locate['html'] : render_location_dummy($locate)); - - $tags=array(); - $hashtags = array(); - $mentions = array(); - - /*foreach(explode(',',$item['tag']) as $tag){ - $tag = trim($tag); - if ($tag!="") { - $t = bbcode($tag); - $tags[] = $t; - if($t[0] == '#') - $hashtags[] = $t; - elseif($t[0] == '@') - $mentions[] = $t; - } - }*/ - - // process action responses - e.g. like/dislike/attend/agree/whatever - $response_verbs = array('like', 'dislike'); - - if ($item['object-type'] === ACTIVITY_OBJ_EVENT) { - $response_verbs[] = 'attendyes'; - $response_verbs[] = 'attendno'; - $response_verbs[] = 'attendmaybe'; - if ($conv->isWritable()) { - $isevent = true; - $attend = array( t('I will attend'), t('I will not attend'), t('I might attend')); - } - } - - $responses = get_responses($conv_responses, $response_verbs, $this, $item); - - foreach ($response_verbs as $value => $verbs) { - $responses[$verbs]['output'] = ((x($conv_responses[$verbs], $item['uri'])) ? format_like($conv_responses[$verbs][$item['uri']], $conv_responses[$verbs][$item['uri'] . '-l'], $verbs, $item['uri']) : ''); - } - - /* - * We should avoid doing this all the time, but it depends on the conversation mode - * And the conv mode may change when we change the conv, or it changes its mode - * Maybe we should establish a way to be notified about conversation changes - */ - $this->checkWallToWall(); - - if ($this->isWallToWall() && ($this->getOwnerUrl() == $this->getRedirectUrl())) { - $osparkle = ' sparkle'; - } - - if ($this->isToplevel()) { - if ($conv->getProfileOwner() == local_user()) { - $isstarred = (($item['starred']) ? "starred" : "unstarred"); - - $star = array( - 'do' => t("add star"), - 'undo' => t("remove star"), - 'toggle' => t("toggle star status"), - 'classdo' => (($item['starred']) ? "hidden" : ""), - 'classundo' => (($item['starred']) ? "" : "hidden"), - 'starred' => t('starred'), - ); - $r = dba::select('thread', array('ignored'), array('uid' => $item['uid'], 'iid' => $item['id']), array('limit' => 1)); - if (DBM::is_result($r)) { - $ignore = array( - 'do' => t("ignore thread"), - 'undo' => t("unignore thread"), - 'toggle' => t("toggle ignore status"), - 'classdo' => (($r['ignored']) ? "hidden" : ""), - 'classundo' => (($r['ignored']) ? "" : "hidden"), - 'ignored' => t('ignored'), - ); - } - - $tagger = ''; - if (Feature::isEnabled($conv->getProfileOwner(), 'commtag')) { - $tagger = array( - 'add' => t("add tag"), - 'class' => "", - ); - } - } - } else { - $indent = 'comment'; - } - - if ($conv->isWritable()) { - $buttons = array( - 'like' => array( t("I like this \x28toggle\x29"), t("like")), - 'dislike' => ((Feature::isEnabled($conv->getProfileOwner(), 'dislike')) ? array( t("I don't like this \x28toggle\x29"), t("dislike")) : ''), - ); - if ($shareable) { - $buttons['share'] = array( t('Share this'), t('share')); - } - } - - $comment = $this->getCommentBox($indent); - - if (strcmp(datetime_convert('UTC', 'UTC', $item['created']), datetime_convert('UTC', 'UTC', 'now - 12 hours')) > 0) { - $shiny = 'shiny'; - } - - localize_item($item); - - $body = prepare_body($item, true); - - list($categories, $folders) = get_cats_and_terms($item); - - $body_e = $body; - $text_e = strip_tags($body); - $name_e = $profile_name; - $title_e = $item['title']; - $location_e = $location; - $owner_name_e = $this->getOwnerName(); - - // Disable features that aren't available in several networks - - /// @todo Add NETWORK_DIASPORA when it will pass this information - if (!in_array($item["item_network"], array(NETWORK_DFRN)) && isset($buttons["dislike"])) { - unset($buttons["dislike"], $isevent); - $tagger = ''; - } - - if (($item["item_network"] == NETWORK_FEED) && isset($buttons["like"])) { - unset($buttons["like"]); - } - - if (($item["item_network"] == NETWORK_MAIL) && isset($buttons["like"])) { - unset($buttons["like"]); - } - - $tmp_item = array( - 'template' => $this->getTemplate(), - 'type' => implode("", array_slice(explode("/", $item['verb']), -1)), - 'tags' => $item['tags'], - 'hashtags' => $item['hashtags'], - 'mentions' => $item['mentions'], - 'txt_cats' => t('Categories:'), - 'txt_folders' => t('Filed under:'), - 'has_cats' => ((count($categories)) ? 'true' : ''), - 'has_folders' => ((count($folders)) ? 'true' : ''), - 'categories' => $categories, - 'folders' => $folders, - 'body' => $body_e, - 'text' => $text_e, - 'id' => $this->getId(), - 'guid' => urlencode($item['guid']), - 'isevent' => $isevent, - 'attend' => $attend, - 'linktitle' => sprintf(t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])), - 'olinktitle' => sprintf(t('View %s\'s profile @ %s'), htmlentities($this->getOwnerName()), ((strlen($item['owner-link'])) ? $item['owner-link'] : $item['url'])), - 'to' => t('to'), - 'via' => t('via'), - 'wall' => t('Wall-to-Wall'), - 'vwall' => t('via Wall-To-Wall:'), - 'profile_url' => $profile_link, - 'item_photo_menu' => item_photo_menu($item), - 'name' => $name_e, - 'thumb' => $a->remove_baseurl(proxy_url($item['author-thumb'], false, PROXY_SIZE_THUMB)), - 'osparkle' => $osparkle, - 'sparkle' => $sparkle, - 'title' => $title_e, - 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'), - 'ago' => (($item['app']) ? sprintf(t('%s from %s'), relative_date($item['created']), $item['app']) : relative_date($item['created'])), - 'app' => $item['app'], - 'created' => relative_date($item['created']), - 'lock' => $lock, - 'location' => $location_e, - 'indent' => $indent, - 'shiny' => $shiny, - 'owner_url' => $this->getOwnerUrl(), - 'owner_photo' => $a->remove_baseurl(proxy_url($item['owner-thumb'], false, PROXY_SIZE_THUMB)), - 'owner_name' => htmlentities($owner_name_e), - 'plink' => get_plink($item), - 'edpost' => ((Feature::isEnabled($conv->getProfileOwner(), 'edit_posts')) ? $edpost : ''), - 'isstarred' => $isstarred, - 'star' => ((Feature::isEnabled($conv->getProfileOwner(), 'star_posts')) ? $star : ''), - 'ignore' => ((Feature::isEnabled($conv->getProfileOwner(), 'ignore_posts')) ? $ignore : ''), - 'tagger' => $tagger, - 'filer' => ((Feature::isEnabled($conv->getProfileOwner(), 'filing')) ? $filer : ''), - 'drop' => $drop, - 'vote' => $buttons, - 'like' => $responses['like']['output'], - 'dislike' => $responses['dislike']['output'], - 'responses' => $responses, - 'switchcomment' => t('Comment'), - 'comment' => $comment, - 'previewing' => ($conv->isPreview() ? ' preview ' : ''), - 'wait' => t('Please wait'), - 'thread_level' => $thread_level, - 'edited' => $edited, - 'network' => $item["item_network"], - 'network_name' => network_to_name($item['item_network'], $profile_link), - 'received' => $item['received'], - 'commented' => $item['commented'], - 'created_date' => $item['created'], - ); - - $arr = array('item' => $item, 'output' => $tmp_item); - call_hooks('display_item', $arr); - - $result = $arr['output']; - - $result['children'] = array(); - $children = $this->getChildren(); - $nb_children = count($children); - if ($nb_children > 0) { - foreach ($children as $child) { - $result['children'][] = $child->getTemplateData($conv_responses, $thread_level + 1); - } - // Collapse - if (($nb_children > 2) || ($thread_level > 1)) { - $result['children'][0]['comment_firstcollapsed'] = true; - $result['children'][0]['num_comments'] = sprintf(tt('%d comment', '%d comments', $total_children), $total_children); - $result['children'][0]['hidden_comments_num'] = $total_children; - $result['children'][0]['hidden_comments_text'] = tt('comment', 'comments', $total_children); - $result['children'][0]['hide_text'] = t('show more'); - if ($thread_level > 1) { - $result['children'][$nb_children - 1]['comment_lastcollapsed'] = true; - } else { - $result['children'][$nb_children - 3]['comment_lastcollapsed'] = true; - } - } - } - - if ($this->isToplevel()) { - $result['total_comments_num'] = "$total_children"; - $result['total_comments_text'] = tt('comment', 'comments', $total_children); - } - - $result['private'] = $item['private']; - $result['toplevel'] = ($this->isToplevel() ? 'toplevel_item' : ''); - - if ($this->isThreaded()) { - $result['flatten'] = false; - $result['threaded'] = true; - } else { - $result['flatten'] = true; - $result['threaded'] = false; - } - - return $result; - } - - /** - * @return integer - */ - public function getId() - { - return $this->getDataValue('id'); - } - - /** - * @return boolean - */ - public function isThreaded() - { - return $this->threaded; - } - - /** - * Add a child item - * - * @param object $item The child item to add - * - * @return mixed - */ - public function addChild(Item $item) - { - $item_id = $item->getId(); - if (!$item_id) { - logger('[ERROR] Item::addChild : Item has no ID!!', LOGGER_DEBUG); - return false; - } elseif ($this->getChild($item->getId())) { - logger('[WARN] Item::addChild : Item already exists ('. $item->getId() .').', LOGGER_DEBUG); - return false; - } - /* - * Only add what will be displayed - */ - if ($item->getDataValue('network') === NETWORK_MAIL && local_user() != $item->getDataValue('uid')) { - return false; - } elseif (activity_match($item->getDataValue('verb'), ACTIVITY_LIKE) || activity_match($item->getDataValue('verb'), ACTIVITY_DISLIKE)) { - return false; - } - - $item->setParent($this); - $this->children[] = $item; - - return end($this->children); - } - - /** - * Get a child by its ID - * - * @param integer $id The child id - * - * @return mixed - */ - public function getChild($id) - { - foreach ($this->getChildren() as $child) { - if ($child->getId() == $id) { - return $child; - } - } - - return null; - } - - /** - * Get all our children - * - * @return object - */ - public function getChildren() - { - return $this->children; - } - - /** - * Set our parent - * - * @param object $item The item to set as parent - * - * @return void - */ - protected function setParent($item) - { - $parent = $this->getParent(); - if ($parent) { - $parent->removeChild($this); - } - - $this->parent = $item; - $this->setThread($item->getThread()); - } - - /** - * Remove our parent - * - * @return void - */ - protected function removeParent() - { - $this->parent = null; - $this->thread = null; - } - - /** - * Remove a child - * - * @param object $item The child to be removed - * - * @return boolean Success or failure - */ - public function removeChild($item) - { - $id = $item->getId(); - foreach ($this->getChildren() as $key => $child) { - if ($child->getId() == $id) { - $child->removeParent(); - unset($this->children[$key]); - // Reindex the array, in order to make sure there won't be any trouble on loops using count() - $this->children = array_values($this->children); - return true; - } - } - logger('[WARN] Item::removeChild : Item is not a child ('. $id .').', LOGGER_DEBUG); - return false; - } - - /** - * Get parent item - * - * @return object - */ - protected function getParent() - { - return $this->parent; - } - - /** - * Set conversation - * - * @param object $conv The conversation - * - * @return void - */ - public function setThread($conv) - { - $previous_mode = ($this->thread ? $this->thread->getMode() : ''); - - $this->thread = $conv; - - // Set it on our children too - foreach ($this->getChildren() as $child) { - $child->setThread($conv); - } - } - - /** - * Get conversation - * - * @return object - */ - public function getThread() - { - return $this->thread; - } - - /** - * Get raw data - * - * We shouldn't need this - * - * @return array - */ - public function getData() - { - return $this->data; - } - - /** - * Get a data value - * - * @param object $name key - * - * @return mixed value on success - * false on failure - */ - public function getDataValue($name) - { - if (!isset($this->data[$name])) { - // logger('[ERROR] Item::getDataValue : Item has no value name "'. $name .'".', LOGGER_DEBUG); - return false; - } - - return $this->data[$name]; - } - - /** - * Set template - * - * @param object $name template name - * - * @return void - */ - private function setTemplate($name) - { - if (!x($this->available_templates, $name)) { - logger('[ERROR] Item::setTemplate : Template not available ("'. $name .'").', LOGGER_DEBUG); - return false; - } - - $this->template = $this->available_templates[$name]; - } - - /** - * Get template - * - * @return object - */ - private function getTemplate() - { - return $this->template; - } - - /** - * Check if this is a toplevel post - * - * @return boolean - */ - private function isToplevel() - { - return $this->toplevel; - } - - /** - * Check if this is writable - * - * @return boolean - */ - private function isWritable() - { - $conv = $this->getThread(); - - if ($conv) { - // This will allow us to comment on wall-to-wall items owned by our friends - // and community forums even if somebody else wrote the post. - - // bug #517 - this fixes for conversation owner - if ($conv->getMode() == 'profile' && $conv->getProfileOwner() == local_user()) { - return true; - } - - // this fixes for visitors - return ($this->writable || ($this->isVisiting() && $conv->getMode() == 'profile')); - } - return $this->writable; - } - - /** - * Count the total of our descendants - * - * @return integer - */ - private function countDescendants() - { - $children = $this->getChildren(); - $total = count($children); - if ($total > 0) { - foreach ($children as $child) { - $total += $child->countDescendants(); - } - } - - return $total; - } - - /** - * Get the template for the comment box - * - * @return string - */ - private function getCommentBoxTemplate() - { - return $this->comment_box_template; - } - - /** - * Get the comment box - * - * @param string $indent Indent value - * - * @return mixed The comment box string (empty if no comment box) - * false on failure - */ - private function getCommentBox($indent) - { - $a = self::getApp(); - - $comment_box = ''; - $conv = $this->getThread(); - $template = get_markup_template($this->getCommentBoxTemplate()); - $ww = ''; - if (($conv->getMode() === 'network') && $this->isWallToWall()) { - $ww = 'ww'; - } - - if ($conv->isWritable() && $this->isWritable()) { - $qc = $qcomment = null; - - /* - * Hmmm, code depending on the presence of a particular plugin? - * This should be better if done by a hook - */ - if (in_array('qcomment', $a->plugins)) { - $qc = ((local_user()) ? PConfig::get(local_user(), 'qcomment', 'words') : null); - $qcomment = (($qc) ? explode("\n", $qc) : null); - } - - $comment_box = replace_macros( - $template, - array( - '$return_path' => $a->query_string, - '$threaded' => $this->isThreaded(), - // '$jsreload' => (($conv->getMode() === 'display') ? $_SESSION['return_url'] : ''), - '$jsreload' => '', - '$type' => (($conv->getMode() === 'profile') ? 'wall-comment' : 'net-comment'), - '$id' => $this->getId(), - '$parent' => $this->getId(), - '$qcomment' => $qcomment, - '$profile_uid' => $conv->getProfileOwner(), - '$mylink' => $a->remove_baseurl($a->contact['url']), - '$mytitle' => t('This is you'), - '$myphoto' => $a->remove_baseurl($a->contact['thumb']), - '$comment' => t('Comment'), - '$submit' => t('Submit'), - '$edbold' => t('Bold'), - '$editalic' => t('Italic'), - '$eduline' => t('Underline'), - '$edquote' => t('Quote'), - '$edcode' => t('Code'), - '$edimg' => t('Image'), - '$edurl' => t('Link'), - '$edvideo' => t('Video'), - '$preview' => ((Feature::isEnabled($conv->getProfileOwner(), 'preview')) ? t('Preview') : ''), - '$indent' => $indent, - '$sourceapp' => t($a->sourcename), - '$ww' => (($conv->getMode() === 'network') ? $ww : ''), - '$rand_num' => random_digits(12)) - ); - } - - return $comment_box; - } - - /** - * @return string - */ - private function getRedirectUrl() - { - return $this->redirect_url; - } - - /** - * Check if we are a wall to wall item and set the relevant properties - * - * @return void - */ - protected function checkWallToWall() - { - $a = self::getApp(); - $conv = $this->getThread(); - $this->wall_to_wall = false; - - if ($this->isToplevel()) { - if ($conv->getMode() !== 'profile') { - if ($this->getDataValue('wall') && !$this->getDataValue('self')) { - // On the network page, I am the owner. On the display page it will be the profile owner. - // This will have been stored in $a->page_contact by our calling page. - // Put this person as the wall owner of the wall-to-wall notice. - - $this->owner_url = zrl($a->page_contact['url']); - $this->owner_photo = $a->page_contact['thumb']; - $this->owner_name = $a->page_contact['name']; - $this->wall_to_wall = true; - } elseif ($this->getDataValue('owner-link')) { - $owner_linkmatch = (($this->getDataValue('owner-link')) && link_compare($this->getDataValue('owner-link'), $this->getDataValue('author-link'))); - $alias_linkmatch = (($this->getDataValue('alias')) && link_compare($this->getDataValue('alias'), $this->getDataValue('author-link'))); - $owner_namematch = (($this->getDataValue('owner-name')) && $this->getDataValue('owner-name') == $this->getDataValue('author-name')); - - if ((! $owner_linkmatch) && (! $alias_linkmatch) && (! $owner_namematch)) { - // The author url doesn't match the owner (typically the contact) - // and also doesn't match the contact alias. - // The name match is a hack to catch several weird cases where URLs are - // all over the park. It can be tricked, but this prevents you from - // seeing "Bob Smith to Bob Smith via Wall-to-wall" and you know darn - // well that it's the same Bob Smith. - - // But it could be somebody else with the same name. It just isn't highly likely. - - - $this->owner_photo = $this->getDataValue('owner-avatar'); - $this->owner_name = $this->getDataValue('owner-name'); - $this->wall_to_wall = true; - // If it is our contact, use a friendly redirect link - if ((link_compare($this->getDataValue('owner-link'), $this->getDataValue('url'))) - && ($this->getDataValue('network') === NETWORK_DFRN) - ) { - $this->owner_url = $this->getRedirectUrl(); - } else { - $this->owner_url = zrl($this->getDataValue('owner-link')); - } - } - } - } - } - - if (!$this->wall_to_wall) { - $this->setTemplate('wall'); - $this->owner_url = ''; - $this->owner_photo = ''; - $this->owner_name = ''; - } - } - - /** - * @return boolean - */ - private function isWallToWall() - { - return $this->wall_to_wall; - } - - /** - * @return string - */ - private function getOwnerUrl() - { - return $this->owner_url; - } - - /** - * @return string - */ - private function getOwnerName() - { - return $this->owner_name; - } - - /** - * @return boolean - */ - private function isVisiting() - { - return $this->visiting; - } -} diff --git a/src/Object/Profile.php b/src/Object/Profile.php new file mode 100644 index 0000000000..29925a9497 --- /dev/null +++ b/src/Object/Profile.php @@ -0,0 +1,46 @@ +setMode($mode); - $this->preview = $preview; - } - - /** - * Set the mode we'll be displayed on - * - * @param string $mode The mode to set - * - * @return void - */ - private function setMode($mode) - { - if ($this->getMode() == $mode) { - return; - } - - $a = self::getApp(); - - switch ($mode) { - case 'network': - case 'notes': - $this->profile_owner = local_user(); - $this->writable = true; - break; - case 'profile': - $this->profile_owner = $a->profile['profile_uid']; - $this->writable = can_write_wall($a, $this->profile_owner); - break; - case 'display': - $this->profile_owner = $a->profile['uid']; - $this->writable = can_write_wall($a, $this->profile_owner); - break; - default: - logger('[ERROR] Conversation::setMode : Unhandled mode ('. $mode .').', LOGGER_DEBUG); - return false; - break; - } - $this->mode = $mode; - } - - /** - * Get mode - * - * @return string - */ - public function getMode() - { - return $this->mode; - } - - /** - * Check if page is writable - * - * @return boolean - */ - public function isWritable() - { - return $this->writable; - } - - /** - * Check if page is a preview - * - * @return boolean - */ - public function isPreview() - { - return $this->preview; - } - - /** - * Get profile owner - * - * @return integer - */ - public function getProfileOwner() - { - return $this->profile_owner; - } - - /** - * Add a thread to the conversation - * - * @param object $item The item to insert - * - * @return mixed The inserted item on success - * false on failure - */ - public function addParent($item) - { - $item_id = $item->getId(); - - if (!$item_id) { - logger('[ERROR] Conversation::addThread : Item has no ID!!', LOGGER_DEBUG); - return false; - } - - if ($this->getParent($item->getId())) { - logger('[WARN] Conversation::addThread : Thread already exists ('. $item->getId() .').', LOGGER_DEBUG); - return false; - } - - /* - * Only add will be displayed - */ - if ($item->getDataValue('network') === NETWORK_MAIL && local_user() != $item->getDataValue('uid')) { - logger('[WARN] Conversation::addThread : Thread is a mail ('. $item->getId() .').', LOGGER_DEBUG); - return false; - } - - if ($item->getDataValue('verb') === ACTIVITY_LIKE || $item->getDataValue('verb') === ACTIVITY_DISLIKE) { - logger('[WARN] Conversation::addThread : Thread is a (dis)like ('. $item->getId() .').', LOGGER_DEBUG); - return false; - } - - $item->setThread($this); - $this->parents[] = $item; - - return end($this->parents); - } - - /** - * Get data in a form usable by a conversation template - * - * We should find a way to avoid using those arguments (at least most of them) - * - * @param object $conv_responses data - * - * @return mixed The data requested on success - * false on failure - */ - public function getTemplateData($conv_responses) - { - $a = self::getApp(); - $result = array(); - $i = 0; - - foreach ($this->parents as $item) { - if ($item->getDataValue('network') === NETWORK_MAIL && local_user() != $item->getDataValue('uid')) { - continue; - } - - $item_data = $item->getTemplateData($conv_responses); - - if (!$item_data) { - logger('[ERROR] Conversation::getTemplateData : Failed to get item template data ('. $item->getId() .').', LOGGER_DEBUG); - return false; - } - $result[] = $item_data; - } - - return $result; - } - - /** - * Get a thread based on its item id - * - * @param integer $id Item id - * - * @return mixed The found item on success - * false on failure - */ - private function getParent($id) - { - foreach ($this->parents as $item) { - if ($item->getId() == $id) { - return $item; - } - } - - return false; - } -} diff --git a/src/ParseUrl.php b/src/ParseUrl.php index 35557067d7..2183a9c1e0 100644 --- a/src/ParseUrl.php +++ b/src/ParseUrl.php @@ -6,7 +6,7 @@ namespace Friendica; use Friendica\Core\Config; -use Friendica\Object\Image; +use Friendica\Object\Photo; use Friendica\Util\XML; use dba; @@ -353,7 +353,7 @@ class ParseUrl } $src = self::completeUrl($attr["src"], $url); - $photodata = Image::getInfoFromURL($src); + $photodata = Photo::getInfoFromURL($src); if (($photodata) && ($photodata[0] > 150) && ($photodata[1] > 150)) { if ($photodata[0] > 300) { @@ -374,7 +374,7 @@ class ParseUrl unset($siteinfo["image"]); - $photodata = Image::getInfoFromURL($src); + $photodata = Photo::getInfoFromURL($src); if (($photodata) && ($photodata[0] > 10) && ($photodata[1] > 10)) { $siteinfo["images"][] = array("src" => $src, diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 62ada9620a..5af082905d 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -13,10 +13,10 @@ use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Model\Contact; -use Friendica\Model\GContact; -use Friendica\Model\Profile; -use Friendica\Object\Image; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; +use Friendica\Object\Photo; +use Friendica\Object\Profile; use Friendica\Protocol\OStatus; use Friendica\Util\XML; @@ -476,7 +476,7 @@ class DFRN $uid ); $photos = array(); - $ext = Image::supportedTypes(); + $ext = Photo::supportedTypes(); foreach ($rp as $p) { $photos[$p['scale']] = System::baseUrl().'/photo/'.$p['resource-id'].'-'.$p['scale'].'.'.$ext[$p['type']]; @@ -1678,9 +1678,9 @@ class DFRN $poco["photo"] = $author["avatar"]; $poco["hide"] = $hide; $poco["contact-type"] = $contact["contact-type"]; - $gcid = GContact::update($poco); + $gcid = GlobalContact::update($poco); - GContact::link($gcid, $importer["uid"], $contact["id"]); + GlobalContact::link($gcid, $importer["uid"], $contact["id"]); } return($author); diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index d6f1078f4c..2cb5eb700b 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\GContact; -use Friendica\Model\Profile; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; +use Friendica\Object\Contact; +use Friendica\Object\Profile; use Friendica\Util\XML; use dba; @@ -2247,9 +2247,9 @@ class Diaspora "addr" => $author, "nick" => $nick, "keywords" => $keywords, "hide" => !$searchable, "nsfw" => $nsfw); - $gcid = GContact::update($gcontact); + $gcid = GlobalContact::update($gcontact); - GContact::link($gcid, $importer["uid"], $contact["id"]); + GlobalContact::link($gcid, $importer["uid"], $contact["id"]); logger("Profile of contact ".$contact["id"]." stored for user ".$importer["uid"], LOGGER_DEBUG); diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 2a021c89e9..9a2eaeb5b7 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -9,10 +9,10 @@ use Friendica\Core\Cache; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Model\Contact; -use Friendica\Model\GContact; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; -use Friendica\Object\Image; +use Friendica\Object\Contact; +use Friendica\Object\Photo; use Friendica\Util\Lock; use Friendica\Util\XML; use dba; @@ -226,9 +226,9 @@ class OStatus $contact["generation"] = 2; $contact["hide"] = false; // OStatus contacts are never hidden $contact["photo"] = $author["author-avatar"]; - $gcid = GContact::update($contact); + $gcid = GlobalContact::update($contact); - GContact::link($gcid, $contact["uid"], $contact["id"]); + GlobalContact::link($gcid, $contact["uid"], $contact["id"]); } return $author; @@ -1323,7 +1323,7 @@ class OStatus switch ($siteinfo["type"]) { case 'photo': - $imgdata = Image::getInfoFromURL($siteinfo["image"]); + $imgdata = Photo::getInfoFromURL($siteinfo["image"]); $attributes = array("rel" => "enclosure", "href" => $siteinfo["image"], "type" => $imgdata["mime"], @@ -1343,7 +1343,7 @@ class OStatus } if (!Config::get('system', 'ostatus_not_attach_preview') && ($siteinfo["type"] != "photo") && isset($siteinfo["image"])) { - $imgdata = Image::getInfoFromURL($siteinfo["image"]); + $imgdata = Photo::getInfoFromURL($siteinfo["image"]); $attributes = array("rel" => "enclosure", "href" => $siteinfo["image"], "type" => $imgdata["mime"], diff --git a/src/Protocol/PortableContact.php b/src/Protocol/PortableContact.php index 2b37a99624..84bfd4c4f1 100644 --- a/src/Protocol/PortableContact.php +++ b/src/Protocol/PortableContact.php @@ -12,9 +12,10 @@ namespace Friendica\Protocol; use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Model\GContact; -use Friendica\Model\Profile; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; +use Friendica\Object\Photo; +use Friendica\Object\Profile; use dba; use DOMDocument; use DomXPath; @@ -192,10 +193,10 @@ class PortableContact "generation" => $generation); try { - $gcontact = GContact::sanitize($gcontact); - $gcid = GContact::update($gcontact); + $gcontact = GlobalContact::sanitize($gcontact); + $gcid = GlobalContact::update($gcontact); - GContact::link($gcid, $uid, $cid, $zcid); + GlobalContact::link($gcid, $uid, $cid, $zcid); } catch (Exception $e) { logger($e->getMessage(), LOGGER_DEBUG); } @@ -424,7 +425,7 @@ class PortableContact $contact = array_merge($contact, $noscrape); - GContact::update($contact); + GlobalContact::update($contact); if (trim($noscrape["updated"]) != "") { q( @@ -446,7 +447,7 @@ class PortableContact if (!$force && !self::updateNeeded($gcontacts[0]["created"], $gcontacts[0]["updated"], $gcontacts[0]["last_failure"], $gcontacts[0]["last_contact"])) { logger("Profile ".$profile." was last updated at ".$gcontacts[0]["updated"]." (cached)", LOGGER_DEBUG); - GContact::update($contact); + GlobalContact::update($contact); return $gcontacts[0]["updated"]; } @@ -467,8 +468,8 @@ class PortableContact $gcontact["server_url"] = $data["baseurl"]; try { - $gcontact = GContact::sanitize($gcontact); - GContact::update($gcontact); + $gcontact = GlobalContact::sanitize($gcontact); + GlobalContact::update($gcontact); self::lastUpdated($data["url"], $force); } catch (Exception $e) { @@ -494,7 +495,7 @@ class PortableContact $contact["server_url"] = $data["baseurl"]; - GContact::update($contact); + GlobalContact::update($contact); $feedret = z_fetch_url($data["poll"]); @@ -1600,8 +1601,8 @@ class PortableContact "generation" => $generation); try { - $gcontact = GContact::sanitize($gcontact); - GContact::update($gcontact); + $gcontact = GlobalContact::sanitize($gcontact); + GlobalContact::update($gcontact); } catch (Exception $e) { logger($e->getMessage(), LOGGER_DEBUG); } diff --git a/src/Worker/CronJobs.php b/src/Worker/CronJobs.php index b59f096d7d..7df7d030cb 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\GContact; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; +use Friendica\Object\Contact; use Friendica\Protocol\PortableContact; use dba; @@ -280,7 +280,7 @@ class CronJobs $r = q("SELECT `uid` FROM `user` WHERE `verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`"); if (DBM::is_result($r)) { foreach ($r AS $user) { - GContact::updateForUser($user["uid"]); + GlobalContact::updateForUser($user["uid"]); } } diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php index c20bb8d8f8..bb30fc3bf4 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\Model\Contact; +use Friendica\Object\Contact; use Friendica\Protocol\Diaspora; use Friendica\Protocol\DFRN; use Friendica\Protocol\Email; diff --git a/src/Worker/DiscoverPoCo.php b/src/Worker/DiscoverPoCo.php index b3c03e9050..96cfae00b6 100644 --- a/src/Worker/DiscoverPoCo.php +++ b/src/Worker/DiscoverPoCo.php @@ -8,7 +8,7 @@ use Friendica\Core\Cache; use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Model\GContact; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; use Friendica\Protocol\PortableContact; @@ -90,7 +90,7 @@ class DiscoverPoCo { } logger($result, LOGGER_DEBUG); } elseif ($mode == 3) { - GContact::updateSuggestions(); + GlobalContact::updateSuggestions(); } elseif (($mode == 2) && Config::get('system', 'poco_completion')) { self::discoverUsers(); } elseif (($mode == 1) && ($search != "") && Config::get('system', 'poco_local_search')) { @@ -102,7 +102,7 @@ class DiscoverPoCo { // Query GNU Social servers for their users ("statistics" addon has to be enabled on the GS server) if (!Config::get('system', 'ostatus_disabled')) { - GContact::discoverGsUsers(); + GlobalContact::discoverGsUsers(); } } @@ -256,7 +256,7 @@ class DiscoverPoCo { $data["server_url"] = $data["baseurl"]; - GContact::update($data); + GlobalContact::update($data); } else { logger("Profile ".$jj->url." is not responding or no Friendica contact - but network ".$data["network"], LOGGER_DEBUG); } @@ -297,7 +297,7 @@ class DiscoverPoCo { $contact = Probe::uri($user->site_address."/".$user->name); if ($contact["network"] != NETWORK_PHANTOM) { $contact["about"] = $user->description; - GContact::update($contact); + GlobalContact::update($contact); } } } diff --git a/src/Worker/GProbe.php b/src/Worker/GProbe.php index 0d8c3765a8..2dd6633672 100644 --- a/src/Worker/GProbe.php +++ b/src/Worker/GProbe.php @@ -8,7 +8,7 @@ namespace Friendica\Worker; use Friendica\Core\Cache; use Friendica\Core\Config; use Friendica\Database\DBM; -use Friendica\Model\GContact; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; use Friendica\Protocol\PortableContact; @@ -47,7 +47,7 @@ class GProbe { } if (!in_array($arr["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) { - GContact::update($arr); + GlobalContact::update($arr); } $r = q( diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 18fff2afda..a3a03055ec 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 9024d0d4c9..1190c77f5f 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\Model\Contact; +use Friendica\Object\Contact; use Friendica\Protocol\Email; use Friendica\Protocol\PortableContact; use dba; diff --git a/update.php b/update.php index 751e15b587..12a04995c9 100644 --- a/update.php +++ b/update.php @@ -6,8 +6,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\Worker; use Friendica\Database\DBM; -use Friendica\Model\Photo; -use Friendica\Object\Image; +use Friendica\Object\Photo; /** * @@ -154,10 +153,10 @@ function update_1014() $r = q("SELECT * FROM `photo` WHERE `scale` = 4"); if (DBM::is_result($r)) { foreach ($r as $rr) { - $Image = new Image($rr['data']); - if ($Image->isValid()) { - $Image->scaleDown(48); - Photo::store($Image, $rr['uid'],$rr['contact-id'],$rr['resource-id'],$rr['filename'],$rr['album'],6,(($rr['profile']) ? 1 : 0)); + $ph = new Photo($rr['data']); + if ($ph->isValid()) { + $ph->scaleImage(48); + $ph->store($rr['uid'],$rr['contact-id'],$rr['resource-id'],$rr['filename'],$rr['album'],6,(($rr['profile']) ? 1 : 0)); } } } diff --git a/util/global_community_block.php b/util/global_community_block.php index 87044bb4e4..ab586b6510 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\Model\Contact; +use Friendica\Object\Contact; require_once 'boot.php'; require_once 'include/dba.php'; diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php index 8b17130269..0a6b48e4eb 100644 --- a/view/theme/frio/theme.php +++ b/view/theme/frio/theme.php @@ -12,7 +12,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Object\Image; +use Friendica\Object\Photo; $frio = "view/theme/frio"; @@ -82,7 +82,7 @@ function frio_uninstall() { */ function frio_item_photo_links(App $a, &$body_info) { - $phototypes = Image::supportedTypes(); + $phototypes = Photo::supportedTypes(); $occurence = 1; $p = bb_find_open_close($body_info['html'], ""); diff --git a/view/theme/frost/theme.php b/view/theme/frost/theme.php index f661546b39..5d5162cd32 100644 --- a/view/theme/frost/theme.php +++ b/view/theme/frost/theme.php @@ -11,7 +11,7 @@ use Friendica\App; use Friendica\Core\System; -use Friendica\Object\Image; +use Friendica\Object\Photo; function frost_init(App $a) { $a->videowidth = 400; @@ -48,7 +48,7 @@ function frost_uninstall() { function frost_item_photo_links(App $a, &$body_info) { - $phototypes = Image::supportedTypes(); + $phototypes = Photo::supportedTypes(); $occurence = 1; $p = bb_find_open_close($body_info['html'], ""); diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php index b7c76b02ef..0f81200890 100644 --- a/view/theme/vier/theme.php +++ b/view/theme/vier/theme.php @@ -15,7 +15,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBM; -use Friendica\Model\GContact; +use Friendica\Model\GlobalContact; require_once "include/plugin.php"; require_once "mod/proxy.php"; @@ -139,7 +139,7 @@ function vier_community_info() { // comunity_profiles if ($show_profiles) { - $r = GContact::suggestionQuery(local_user(), 0, 9); + $r = GlobalContact::suggestionQuery(local_user(), 0, 9); $tpl = get_markup_template('ch_directory_item.tpl'); if (DBM::is_result($r)) {