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';
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";
}
if ($localsearch) {
- $x = GContact::searchByName($search, $mode);
+ $x = GlobalContact::searchByName($search, $mode);
return $x;
}
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;
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;
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]';
$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"]);
$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)
$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 {
}
if ($filetype == "") {
- $filetype=Image::guessType($filename);
+ $filetype=Photo::guessImageType($filename);
}
$imagedata = getimagesize($src);
if ($imagedata) {
// 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
$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;
// 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");
}
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);
}
use Friendica\App;
use Friendica\Core\System;
-use Friendica\Model\Contact;
use Friendica\Network\Probe;
+use Friendica\Object\Contact;
use League\HTMLToMarkdown\HtmlConverter;
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';
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';
}
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(
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";
// 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
if ($item['id'] == $item['parent']) {
$item_object = new Item($item);
- $conv->addParent($item_object);
+ $conv->addThread($item_object);
}
}
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;
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';
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';
* 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']));
}
}
$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();
}
}
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
-use Friendica\Model\Contact;
+use Friendica\Object\Contact;
use Friendica\Protocol\Diaspora;
/**
use Friendica\Core\System;
use Friendica\Core\Config;
use Friendica\Network\Probe;
-use Friendica\Object\Image;
+use Friendica\Object\Photo;
use Friendica\Util\XML;
/**
}
// 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],
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";
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];
$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];
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
// 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"]));
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();
/**
* @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) {
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) {
/**
* @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.
*/
/**
* @brief Compare function to sort tags/terms alphabetically.
- *
+ *
* @param type $a
* @param type $b
- *
+ *
* @return int
*/
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.
*/
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`,
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);
$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']
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';
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';
$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.');
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';
*/
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';
}
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)) {
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']);
}
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';
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) {
);
// 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,
'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,
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';
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';
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';
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';
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);
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';
// 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) {
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) {
use Friendica\App;
use Friendica\Core\System;
-use Friendica\Object\Image;
+use Friendica\Object\Photo;
/**
* @param App $a
function _map_files1($rr){
$a = get_app();
- $types = Image::supportedTypes();
+ $types = Photo::supportedTypes();
$ext = $types[$rr['type']];
$filename_e = $rr['filename'];
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';
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
}
// 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);
use Friendica\App;
use Friendica\Core\System;
use Friendica\Database\DBM;
-use Friendica\Object\Image;
+use Friendica\Object\Photo;
$install_wizard_pass = 1;
if (class_exists('Imagick')) {
$imagick = true;
- $supported = Image::supportedTypes();
+ $supported = Photo::supportedTypes();
if (array_key_exists('image/gif', $supported)) {
$gif = true;
}
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;
$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;
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"])));
}
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';
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';
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';
*/
use Friendica\App;
use Friendica\Database\DBM;
-use Friendica\Model\Contact;
+use Friendica\Object\Contact;
require_once 'include/contact_selectors.php';
*/
use Friendica\App;
use Friendica\Database\DBM;
-use Friendica\Object\Image;
+use Friendica\Object\Photo;
require_once 'include/security.php';
$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);
}
$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);
}
}
// 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();
}
}
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';
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;
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),
);
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),
}
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),
$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);
$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);
killme();
}
- $exif = $Image->orient($src);
+ $exif = $ph->orient($src);
@unlink($src);
$max_length = Config::get('system', 'max_image_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();
$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);
}
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;
}
$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);
return;
}
- $phototypes = Image::supportedTypes();
+ $phototypes = Photo::supportedTypes();
$_SESSION['photo_return'] = $a->cmd;
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';
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) {
$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 );
);
$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())
);
$filesize = intval($_FILES['userfile']['size']);
$filetype = $_FILES['userfile']['type'];
if ($filetype == "") {
- $filetype = Image::guessType($filename);
+ $filetype = Photo::guessImageType($filename);
}
$maximagesize = Config::get('system', 'maximagesize');
}
$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);
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
}
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();
$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 );
}
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 );
$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;
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) {
Worker::add(PRIORITY_LOW, 'ProfileUpdate', local_user());
// Update the global contact for the user
- GContact::updateForUser(local_user());
+ GlobalContact::updateForUser(local_user());
}
}
}
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
// 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();
}
}
$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);
'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);
}
}
}
// 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();
}
}
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));
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;
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) {
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';
$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.');
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';
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');
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');
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) {
$filetype = "";
}
- if ($filetype == "") {
- $filetype = Image::guessType($filename);
+ if ($filetype=="") {
+ $filetype=Photo::guessImageType($filename);
}
// If there is a temp name, then do a manual check
}
$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));
killme();
}
- $Image->orient($src);
+ $ph->orient($src);
@unlink($src);
$max_length = Config::get('system', 'max_image_length');
$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();
$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.');
}
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;
}
$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));
/* 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 */
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';
+++ /dev/null
-<?php
-
-/**
- * @file src/Model/Contact.php
- */
-
-namespace Friendica\Model;
-
-use Friendica\BaseObject;
-use Friendica\Core\PConfig;
-use Friendica\Core\System;
-use Friendica\Core\Worker;
-use Friendica\Database\DBM;
-use Friendica\Network\Probe;
-use Friendica\Object\Image;
-use Friendica\Protocol\Diaspora;
-use Friendica\Protocol\DFRN;
-use Friendica\Protocol\OStatus;
-use Friendica\Protocol\Salmon;
-use dba;
-
-require_once 'boot.php';
-require_once 'include/text.php';
-
-/**
- * @brief functions for interacting with a contact
- */
-class Contact extends BaseObject
-{
- /**
- * Creates the self-contact for the provided user id
- *
- * @param int $uid
- * @return bool Operation success
- */
- public static function createSelfFromUserId($uid)
- {
- // Only create the entry if it doesn't exist yet
- if (dba::exists('contact', ['uid' => 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;
- }
-}
+++ /dev/null
-<?php
-/**
- * @file src/Model/GlobalContact.php
- * @brief This file includes the GlobalContact class with directory related functions
- */
-namespace Friendica\Model;
-
-use Friendica\Core\Config;
-use Friendica\Core\System;
-use Friendica\Core\Worker;
-use Friendica\Database\DBM;
-use Friendica\Model\Contact;
-use Friendica\Model\Profile;
-use Friendica\Network\Probe;
-use Friendica\Protocol\PortableContact;
-use dba;
-use Exception;
-
-require_once 'include/datetime.php';
-require_once 'include/network.php';
-require_once 'include/html2bbcode.php';
-
-/**
- * @brief This class handles GlobalContact related functions
- */
-class GContact
-{
- /**
- * @brief Search global contact table by nick or name
- *
- * @param string $search Name or nick
- * @param string $mode Search mode (e.g. "community")
- *
- * @return array with search results
- */
- public static function searchByName($search, $mode = '')
- {
- if ($search) {
- // check supported networks
- if (Config::get('system', 'diaspora_enabled')) {
- $diaspora = NETWORK_DIASPORA;
- } else {
- $diaspora = NETWORK_DFRN;
- }
-
- if (!Config::get('system', 'ostatus_disabled')) {
- $ostatus = NETWORK_OSTATUS;
- } else {
- $ostatus = NETWORK_DFRN;
- }
-
- // check if we search only communities or every contact
- if ($mode === "community") {
- $extra_sql = " AND `community`";
- } else {
- $extra_sql = "";
- }
-
- $search .= "%";
-
- $results = q(
- "SELECT `contact`.`id` AS `cid`, `gcontact`.`url`, `gcontact`.`name`, `gcontact`.`nick`, `gcontact`.`photo`,
- `gcontact`.`network`, `gcontact`.`keywords`, `gcontact`.`addr`, `gcontact`.`community`
- FROM `gcontact`
- LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl`
- AND `contact`.`uid` = %d AND NOT `contact`.`blocked`
- AND NOT `contact`.`pending` AND `contact`.`rel` IN ('%s', '%s')
- WHERE (`contact`.`id` > 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 '';
- }
-}
--- /dev/null
+<?php
+/**
+ * @file src/Model/GlobalContact.php
+ * @brief This file includes the GlobalContact class with directory related functions
+ */
+namespace Friendica\Model;
+
+use Friendica\Core\Config;
+use Friendica\Core\System;
+use Friendica\Core\Worker;
+use Friendica\Database\DBM;
+use Friendica\Network\Probe;
+use Friendica\Object\Contact;
+use Friendica\Object\Profile;
+use Friendica\Protocol\PortableContact;
+use dba;
+use Exception;
+
+require_once 'include/datetime.php';
+require_once 'include/network.php';
+require_once 'include/html2bbcode.php';
+
+/**
+ * @brief This class handles GlobalContact related functions
+ */
+class GlobalContact
+{
+ /**
+ * @brief Search global contact table by nick or name
+ *
+ * @param string $search Name or nick
+ * @param string $mode Search mode (e.g. "community")
+ *
+ * @return array with search results
+ */
+ public static function searchByName($search, $mode = '')
+ {
+ if ($search) {
+ // check supported networks
+ if (Config::get('system', 'diaspora_enabled')) {
+ $diaspora = NETWORK_DIASPORA;
+ } else {
+ $diaspora = NETWORK_DFRN;
+ }
+
+ if (!Config::get('system', 'ostatus_disabled')) {
+ $ostatus = NETWORK_OSTATUS;
+ } else {
+ $ostatus = NETWORK_DFRN;
+ }
+
+ // check if we search only communities or every contact
+ if ($mode === "community") {
+ $extra_sql = " AND `community`";
+ } else {
+ $extra_sql = "";
+ }
+
+ $search .= "%";
+
+ $results = q(
+ "SELECT `contact`.`id` AS `cid`, `gcontact`.`url`, `gcontact`.`name`, `gcontact`.`nick`, `gcontact`.`photo`,
+ `gcontact`.`network`, `gcontact`.`keywords`, `gcontact`.`addr`, `gcontact`.`community`
+ FROM `gcontact`
+ LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl`
+ AND `contact`.`uid` = %d AND NOT `contact`.`blocked`
+ AND NOT `contact`.`pending` AND `contact`.`rel` IN ('%s', '%s')
+ WHERE (`contact`.`id` > 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 '';
+ }
+}
+++ /dev/null
-<?php
-
-/**
- * @file src/Model/Photo.php
- * @brief This file contains the Photo class for database interface
- */
-
-namespace Friendica\Model;
-
-use Friendica\Core\System;
-use Friendica\Database\DBM;
-use Friendica\Object\Image;
-use dba;
-
-require_once "include/photos.php";
-/**
- * Class to handle photo dabatase table
- */
-class Photo
-{
- /**
- * @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 static function store(Image $Image, $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' => $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);
- }
-}
+++ /dev/null
-<?php
-
-/**
- * @file src/Model/Profile.php
- */
-
-namespace Friendica\Model;
-
-class Profile
-{
- /**
- * @brief Returns a formatted location string from the given profile array
- *
- * @param array $profile Profile array (Generated from the "profile" table)
- *
- * @return string Location string
- */
- public static function formatLocation(array $profile)
- {
- $location = '';
-
- if ($profile['locality']) {
- $location .= $profile['locality'];
- }
-
- if ($profile['region'] && ($profile['locality'] != $profile['region'])) {
- if ($location) {
- $location .= ', ';
- }
-
- $location .= $profile['region'];
- }
-
- if ($profile['country-name']) {
- if ($location) {
- $location .= ', ';
- }
-
- $location .= $profile['country-name'];
- }
-
- return $location;
- }
-}
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
-use Friendica\Model\Contact;
-use Friendica\Model\Photo;
-use Friendica\Object\Image;
+use Friendica\Object\Contact;
+use Friendica\Object\Photo;
use dba;
require_once 'boot.php';
$filename = basename($photo);
$img_str = fetch_url($photo, true);
// guess mimetype from headers or filename
- $type = Image::guessType($photo, true);
+ $type = Photo::guessImageType($photo, true);
- $Image = new Image($img_str, $type);
- if ($Image->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;
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;
--- /dev/null
+<?php
+
+/**
+ * @file src/Object/Contact.php
+ */
+
+namespace Friendica\Object;
+
+use Friendica\App;
+use Friendica\BaseObject;
+use Friendica\Core\PConfig;
+use Friendica\Core\System;
+use Friendica\Core\Worker;
+use Friendica\Database\DBM;
+use Friendica\Network\Probe;
+use Friendica\Object\Photo;
+use Friendica\Protocol\Diaspora;
+use Friendica\Protocol\DFRN;
+use Friendica\Protocol\OStatus;
+use Friendica\Protocol\Salmon;
+use dba;
+
+require_once 'boot.php';
+require_once 'include/text.php';
+
+/**
+ * @brief functions for interacting with a contact
+ */
+class Contact extends BaseObject
+{
+ /**
+ * Creates the self-contact for the provided user id
+ *
+ * @param int $uid
+ * @return bool Operation success
+ */
+ public static function createSelfFromUserId($uid)
+ {
+ // Only create the entry if it doesn't exist yet
+ if (dba::exists('contact', ['uid' => 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;
+ }
+}
--- /dev/null
+<?php
+/**
+ * @file src/Object/Conversation.php
+ */
+namespace Friendica\Object;
+
+use Friendica\BaseObject;
+use Friendica\Object\Item;
+
+require_once 'boot.php';
+require_once 'include/text.php';
+
+/**
+ * A list of threads
+ *
+ * We should think about making this a SPL Iterator
+ */
+class Conversation extends BaseObject
+{
+ private $threads = array();
+ private $mode = null;
+ private $writable = false;
+ private $profile_owner = 0;
+ private $preview = false;
+
+ /**
+ * Constructor
+ *
+ * @param string $mode The mode
+ * @param boolean $preview boolean value
+ */
+ public function __construct($mode, $preview)
+ {
+ $this->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;
+ }
+}
+++ /dev/null
-<?php
-/**
- * @file src/Object/Image.php
- * @brief This file contains the Image class for image processing
- */
-namespace Friendica\Object;
-
-use Friendica\App;
-use Friendica\Core\Cache;
-use Friendica\Core\Config;
-use Friendica\Core\System;
-use Friendica\Database\DBM;
-use Friendica\Model\Photo;
-use Exception;
-use Imagick;
-use ImagickPixel;
-
-require_once "include/photos.php";
-
-/**
- * Class to handle images
- */
-class Image
-{
- private $image;
-
- /*
- * Put back gd stuff, not everybody have Imagick
- */
- private $imagick;
- private $width;
- private $height;
- private $valid;
- private $type;
- private $types;
-
- /**
- * @brief supported mimetypes and corresponding file extensions
- * @return array
- */
- public static function supportedTypes()
- {
- if (class_exists('Imagick')) {
- // Imagick::queryFormats won't help us a lot there...
- // At least, not yet, other parts of friendica uses this array
- $t = array(
- 'image/jpeg' => '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);
- }
-}
--- /dev/null
+<?php
+/**
+ * @file src/Object/Item.php
+ */
+namespace Friendica\Object;
+
+use Friendica\BaseObject;
+use Friendica\Content\Feature;
+use Friendica\Core\Config;
+use Friendica\Core\PConfig;
+use Friendica\Database\DBM;
+use Friendica\Object\Contact;
+use dba;
+
+require_once 'include/text.php';
+require_once 'boot.php';
+require_once "include/conversation.php";
+
+/**
+ * An item
+ */
+class Item extends BaseObject
+{
+ private $data = array();
+ private $template = null;
+ private $available_templates = array(
+ 'wall' => '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;
+ }
+}
--- /dev/null
+<?php
+/**
+ * @file src/Object/Photo.php
+ * @brief This file contains the Photo class for image processing
+ */
+namespace Friendica\Object;
+
+use Friendica\App;
+use Friendica\Core\Cache;
+use Friendica\Core\Config;
+use Friendica\Core\System;
+use Friendica\Database\DBM;
+use dba;
+use Exception;
+use Imagick;
+use ImagickPixel;
+
+require_once "include/photos.php";
+
+/**
+ * Class to handle Photos
+ */
+class Photo
+{
+ private $image;
+
+ /*
+ * Put back gd stuff, not everybody have Imagick
+ */
+ private $imagick;
+ private $width;
+ private $height;
+ private $valid;
+ private $type;
+ private $types;
+
+ /**
+ * @brief supported mimetypes and corresponding file extensions
+ * @return array
+ */
+ public static function supportedTypes()
+ {
+ if (class_exists('Imagick')) {
+ // Imagick::queryFormats won't help us a lot there...
+ // At least, not yet, other parts of friendica uses this array
+ $t = array(
+ 'image/jpeg' => '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);
+ }
+}
+++ /dev/null
-<?php
-/**
- * @file src/Object/Post.php
- */
-namespace Friendica\Object;
-
-use Friendica\BaseObject;
-use Friendica\Content\Feature;
-use Friendica\Core\PConfig;
-use Friendica\Database\DBM;
-use Friendica\Model\Contact;
-use dba;
-
-require_once 'include/text.php';
-require_once 'boot.php';
-require_once 'include/conversation.php';
-
-/**
- * An item
- */
-class Post extends BaseObject
-{
- private $data = array();
- private $template = null;
- private $available_templates = array(
- 'wall' => '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;
- }
-}
--- /dev/null
+<?php
+
+/**
+ * @file src/Object/Profile.php
+ */
+
+namespace Friendica\Object;
+
+use Friendica\BaseObject;
+
+class Profile extends BaseObject
+{
+ /**
+ * @brief Returns a formatted location string from the given profile array
+ *
+ * @param array $profile Profile array (Generated from the "profile" table)
+ *
+ * @return string Location string
+ */
+ public static function formatLocation(array $profile)
+ {
+ $location = '';
+
+ if ($profile['locality']) {
+ $location .= $profile['locality'];
+ }
+
+ if ($profile['region'] && ($profile['locality'] != $profile['region'])) {
+ if ($location) {
+ $location .= ', ';
+ }
+
+ $location .= $profile['region'];
+ }
+
+ if ($profile['country-name']) {
+ if ($location) {
+ $location .= ', ';
+ }
+
+ $location .= $profile['country-name'];
+ }
+
+ return $location;
+ }
+}
+++ /dev/null
-<?php
-/**
- * @file src/Object/Thread.php
- */
-namespace Friendica\Object;
-
-use Friendica\BaseObject;
-use Friendica\Object\Item;
-
-require_once 'boot.php';
-require_once 'include/text.php';
-
-/**
- * A list of threads
- *
- * We should think about making this a SPL Iterator
- */
-class Thread extends BaseObject
-{
- private $parents = array();
- private $mode = null;
- private $writable = false;
- private $profile_owner = 0;
- private $preview = false;
-
- /**
- * Constructor
- *
- * @param string $mode The mode
- * @param boolean $preview boolean value
- */
- public function __construct($mode, $preview)
- {
- $this->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;
- }
-}
namespace Friendica;
use Friendica\Core\Config;
-use Friendica\Object\Image;
+use Friendica\Object\Photo;
use Friendica\Util\XML;
use dba;
}
$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) {
unset($siteinfo["image"]);
- $photodata = Image::getInfoFromURL($src);
+ $photodata = Photo::getInfoFromURL($src);
if (($photodata) && ($photodata[0] > 10) && ($photodata[1] > 10)) {
$siteinfo["images"][] = array("src" => $src,
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;
$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']];
$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);
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;
"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);
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;
$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;
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"],
}
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"],
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;
"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);
}
$contact = array_merge($contact, $noscrape);
- GContact::update($contact);
+ GlobalContact::update($contact);
if (trim($noscrape["updated"]) != "") {
q(
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"];
}
$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) {
$contact["server_url"] = $data["baseurl"];
- GContact::update($contact);
+ GlobalContact::update($contact);
$feedret = z_fetch_url($data["poll"]);
"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);
}
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;
$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"]);
}
}
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;
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;
}
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')) {
// 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();
}
}
$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);
}
$contact = Probe::uri($user->site_address."/".$user->name);
if ($contact["network"] != NETWORK_PHANTOM) {
$contact["about"] = $user->description;
- GContact::update($contact);
+ GlobalContact::update($contact);
}
}
}
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;
}
if (!in_array($arr["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) {
- GContact::update($arr);
+ GlobalContact::update($arr);
}
$r = q(
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;
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;
use Friendica\Core\PConfig;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
-use Friendica\Model\Photo;
-use Friendica\Object\Image;
+use Friendica\Object\Photo;
/**
*
$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));
}
}
}
}
use Friendica\BaseObject;
-use Friendica\Model\Contact;
+use Friendica\Object\Contact;
require_once 'boot.php';
require_once 'include/dba.php';
use Friendica\Core\PConfig;
use Friendica\Core\System;
use Friendica\Database\DBM;
-use Friendica\Object\Image;
+use Friendica\Object\Photo;
$frio = "view/theme/frio";
*/
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'], "<a", ">");
use Friendica\App;
use Friendica\Core\System;
-use Friendica\Object\Image;
+use Friendica\Object\Photo;
function frost_init(App $a) {
$a->videowidth = 400;
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'], "<a", ">");
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";
// 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)) {