X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fapi.php;h=bd579bf19adc3a1dacc0d5f3d9159a5caf0aab18;hb=5d0e7d24babf345431df73472fc0d1c7c80996f9;hp=287ae255468ff057e4034ffd36d526ec9d1f0b44;hpb=5a28eae59da8267ea8d67727d7821df106a4cd35;p=friendica.git
diff --git a/include/api.php b/include/api.php
index 287ae25546..bd579bf19a 100644
--- a/include/api.php
+++ b/include/api.php
@@ -6,7 +6,9 @@
* @todo Automatically detect if incoming data is HTML or BBCode
*/
-use \Friendica\Core\Config;
+use Friendica\App;
+use Friendica\Core\System;
+use Friendica\Core\Config;
require_once 'include/HTTPExceptions.php';
require_once 'include/bbcode.php';
@@ -95,7 +97,7 @@ $called_api = null;
*
* Register a function to be the endpont for defined API path.
*
- * @param string $path API URL path, relative to App::get_baseurl()
+ * @param string $path API URL path, relative to System::baseUrl()
* @param string $func Function name to call on path request
* @param bool $auth API need logged user
* @param string $method HTTP method reqiured to call this endpoint.
@@ -435,12 +437,12 @@ $called_api = null;
$arr['$user'] = $user_info;
$arr['$rss'] = array(
'alternate' => $user_info['url'],
- 'self' => App::get_baseurl() . "/" . $a->query_string,
- 'base' => App::get_baseurl(),
+ 'self' => System::baseUrl() . "/" . $a->query_string,
+ 'base' => System::baseUrl(),
'updated' => api_date(null),
'atom_updated' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME),
'language' => $user_info['language'],
- 'logo' => App::get_baseurl() . "/images/friendica-32.png",
+ 'logo' => System::baseUrl() . "/images/friendica-32.png",
);
return $arr;
@@ -455,10 +457,13 @@ $called_api = null;
* Contact url or False if contact id is unknown
*/
function api_unique_id_to_url($id) {
- $r = q("SELECT `url` FROM `contact` WHERE `uid` = 0 AND `id` = %d LIMIT 1",
- intval($id));
+ $r = dba::select('contact', array('url'), array('uid' => 0, 'id' => $id), array('limit' => 1));
- return (dbm::is_result($r) && $r[0]["url"]);
+ if (dbm::is_result($r)) {
+ return $r["url"];
+ } else {
+ return false;
+ }
}
/**
@@ -479,7 +484,7 @@ $called_api = null;
logger("api_get_user: Fetching user data for user ".$contact_id, LOGGER_DEBUG);
// Searching for contact URL
- if (!is_null($contact_id) AND (intval($contact_id) == 0)) {
+ if (!is_null($contact_id) && (intval($contact_id) == 0)) {
$user = dbesc(normalise_link($contact_id));
$url = $user;
$extra_query = "AND `contact`.`nurl` = '%s' ";
@@ -489,7 +494,7 @@ $called_api = null;
}
// Searching for contact id with uid = 0
- if (!is_null($contact_id) AND (intval($contact_id) != 0)) {
+ if (!is_null($contact_id) && (intval($contact_id) != 0)) {
$user = dbesc(api_unique_id_to_url($contact_id));
if ($user == "") {
@@ -525,7 +530,16 @@ $called_api = null;
}
}
- if (is_null($user) AND ($a->argc > (count($called_api) - 1)) AND (count($called_api) > 0)) {
+ if (is_null($user) && x($_GET, 'profileurl')) {
+ $user = dbesc(normalise_link($_GET['profileurl']));
+ $nick = $user;
+ $extra_query = "AND `contact`.`nurl` = '%s' ";
+ if (api_user() !== false) {
+ $extra_query .= "AND `contact`.`uid`=".intval(api_user());
+ }
+ }
+
+ if (is_null($user) && ($a->argc > (count($called_api) - 1)) && (count($called_api) > 0)) {
$argid = count($called_api);
list($user, $null) = explode(".", $a->argv[$argid]);
if (is_numeric($user)) {
@@ -587,7 +601,7 @@ $called_api = null;
$network_name = network_to_name($r[0]['network'], $r[0]['url']);
// If no nick where given, extract it from the address
- if (($r[0]['nick'] == "") OR ($r[0]['name'] == $r[0]['nick'])) {
+ if (($r[0]['nick'] == "") || ($r[0]['name'] == $r[0]['nick'])) {
$r[0]['nick'] = api_get_nick($r[0]["url"]);
}
@@ -703,7 +717,7 @@ $called_api = null;
$starred = 0;
// Add a nick if it isn't present there
- if (($uinfo[0]['nick'] == "") OR ($uinfo[0]['name'] == $uinfo[0]['nick'])) {
+ if (($uinfo[0]['nick'] == "") || ($uinfo[0]['name'] == $uinfo[0]['nick'])) {
$uinfo[0]['nick'] = api_get_nick($uinfo[0]["url"]);
}
@@ -736,12 +750,12 @@ $called_api = null;
'contributors_enabled' => false,
'is_translator' => false,
'is_translation_enabled' => false,
- 'following' => (($uinfo[0]['rel'] == CONTACT_IS_FOLLOWER) OR ($uinfo[0]['rel'] == CONTACT_IS_FRIEND)),
+ 'following' => (($uinfo[0]['rel'] == CONTACT_IS_FOLLOWER) || ($uinfo[0]['rel'] == CONTACT_IS_FRIEND)),
'follow_request_sent' => false,
'statusnet_blocking' => false,
'notifications' => false,
/// @TODO old way?
- //'statusnet_profile_url' => App::get_baseurl()."/contacts/".$uinfo[0]['cid'],
+ //'statusnet_profile_url' => System::baseUrl()."/contacts/".$uinfo[0]['cid'],
'statusnet_profile_url' => $uinfo[0]['url'],
'uid' => intval($uinfo[0]['uid']),
'cid' => intval($uinfo[0]['cid']),
@@ -764,13 +778,17 @@ $called_api = null;
$status_user = api_get_user($a, $item["author-link"]);
- $status_user["protected"] = (($item["allow_cid"] != "") OR
- ($item["allow_gid"] != "") OR
- ($item["deny_cid"] != "") OR
- ($item["deny_gid"] != "") OR
+ $status_user["protected"] = (($item["allow_cid"] != "") ||
+ ($item["allow_gid"] != "") ||
+ ($item["deny_cid"] != "") ||
+ ($item["deny_gid"] != "") ||
$item["private"]);
- $owner_user = api_get_user($a, $item["owner-link"]);
+ if ($item['thr-parent'] == $item['uri']) {
+ $owner_user = api_get_user($a, $item["owner-link"]);
+ } else {
+ $owner_user = $status_user;
+ }
return (array($status_user, $owner_user));
}
@@ -1147,8 +1165,8 @@ $called_api = null;
if (dbm::is_result($r)) {
$phototypes = Photo::supportedTypes();
$ext = $phototypes[$r[0]['type']];
- $_REQUEST['body'] .= "\n\n" . '[url=' . App::get_baseurl() . '/photos/' . $r[0]['nickname'] . '/image/' . $r[0]['resource-id'] . ']';
- $_REQUEST['body'] .= '[img]' . App::get_baseurl() . '/photo/' . $r[0]['resource-id'] . '-' . $r[0]['scale'] . '.' . $ext . '[/img][/url]';
+ $_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]';
}
}
@@ -1288,9 +1306,9 @@ $called_api = null;
$status_info["entities"] = $converted["entities"];
}
- if (($lastwall['item_network'] != "") AND ($status["source"] == 'web')) {
+ if (($lastwall['item_network'] != "") && ($status["source"] == 'web')) {
$status_info["source"] = network_to_name($lastwall['item_network'], $user_info['url']);
- } elseif (($lastwall['item_network'] != "") AND (network_to_name($lastwall['item_network'], $user_info['url']) != $status_info["source"])) {
+ } elseif (($lastwall['item_network'] != "") && (network_to_name($lastwall['item_network'], $user_info['url']) != $status_info["source"])) {
$status_info["source"] = trim($status_info["source"].' ('.network_to_name($lastwall['item_network'], $user_info['url']).')');
}
@@ -1376,11 +1394,11 @@ $called_api = null;
$user_info["status"]["entities"] = $converted["entities"];
}
- if (($lastwall['item_network'] != "") AND ($user_info["status"]["source"] == 'web')) {
+ if (($lastwall['item_network'] != "") && ($user_info["status"]["source"] == 'web')) {
$user_info["status"]["source"] = network_to_name($lastwall['item_network'], $user_info['url']);
}
- if (($lastwall['item_network'] != "") AND (network_to_name($lastwall['item_network'], $user_info['url']) != $user_info["status"]["source"])) {
+ if (($lastwall['item_network'] != "") && (network_to_name($lastwall['item_network'], $user_info['url']) != $user_info["status"]["source"])) {
$user_info["status"]["source"] = trim($user_info["status"]["source"] . ' (' . network_to_name($lastwall['item_network'], $user_info['url']) . ')');
}
@@ -1396,6 +1414,7 @@ $called_api = null;
/// @TODO move to top of file or somewhere better
api_register_func('api/users/show','api_users_show');
+ api_register_func('api/externalprofile/show','api_users_show');
function api_users_search($type) {
@@ -1799,7 +1818,7 @@ $called_api = null;
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE `item`.`visible` AND NOT `item`.`moderated` AND NOT `item`.`deleted`
- AND NOT `item`.`private` AND `item`.`allow_cid` = '' AND `item`.`allow`.`gid` = ''
+ AND NOT `item`.`private` AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
$sql_extra
AND `item`.`id`=%d",
@@ -1911,7 +1930,7 @@ $called_api = null;
$start = $page * $count;
// Ugly code - should be changed
- $myurl = App::get_baseurl() . '/profile/'. $a->user['nickname'];
+ $myurl = System::baseUrl() . '/profile/'. $a->user['nickname'];
$myurl = substr($myurl,strpos($myurl, '://') + 3);
//$myurl = str_replace(array('www.','.'),array('','\\.'),$myurl);
$myurl = str_replace('www.', '', $myurl);
@@ -2160,7 +2179,7 @@ $called_api = null;
`contact`.`id` AS `cid`
FROM `item`, `contact`
WHERE `item`.`uid` = %d
- AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
+ AND `item`.`visible` = 1 AND `item`.`moderated` = 0 AND `item`.`deleted` = 0
AND `item`.`starred` = 1
AND `contact`.`id` = `item`.`contact-id`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
@@ -2214,7 +2233,7 @@ $called_api = null;
//don't send title to regular StatusNET requests to avoid confusing these apps
if (x($_GET, 'getText')) {
- $ret['title'] = $item['title'] ;
+ $ret['title'] = $item['title'];
if ($_GET['getText'] == 'html') {
$ret['text'] = bbcode($item['body'], false, false);
} elseif ($_GET['getText'] == 'plain') {
@@ -2245,30 +2264,49 @@ $called_api = null;
$statustitle = trim($item['title']);
- if (($statustitle != '') and (strpos($statusbody, $statustitle) !== false)) {
+ if (($statustitle != '') && (strpos($statusbody, $statustitle) !== false)) {
$statustext = trim($statusbody);
} else {
$statustext = trim($statustitle."\n\n".$statusbody);
}
- if (($item["network"] == NETWORK_FEED) and (strlen($statustext)> 1000)) {
+ if (($item["network"] == NETWORK_FEED) && (strlen($statustext)> 1000)) {
$statustext = substr($statustext, 0, 1000)."... \n".$item["plink"];
}
$statushtml = trim(bbcode($body, false, false));
+ // Workaround for clients with limited HTML parser functionality
$search = array("
", "
", "
",
"", "
", "", "
",
"", "
", "", "
",
"", "
", "", "
");
- $replace = array("
\n", "\n", "
\n",
- "\n", "
\n", "\n", "
\n",
- "\n", "
\n", "\n", "
\n",
- "\n", "
\n", "\n", "
\n");
+ $replace = array("
", "
", "
",
+ "
", "
", "
", "
",
+ "
", "
", "
", "
",
+ "
", "
", "
", "
");
$statushtml = str_replace($search, $replace, $statushtml);
if ($item['title'] != "") {
- $statushtml = "" . bbcode($item['title']) . "
\n" . $statushtml;
+ $statushtml = "
" . bbcode($item['title']) . "
" . $statushtml;
+ }
+
+ do {
+ $oldtext = $statushtml;
+ $statushtml = str_replace("
", "
", $statushtml);
+ } while ($oldtext != $statushtml);
+
+ if (substr($statushtml, 0, 4) == '
') {
+ $statushtml = substr($statushtml, 4);
+ }
+
+ if (substr($statushtml, 0, -4) == '
') {
+ $statushtml = substr($statushtml, -4);
+ }
+
+ // feeds without body should contain the link
+ if (($item['network'] == NETWORK_FEED) && (strlen($item['body']) == 0)) {
+ $statushtml .= bbcode($item['plink']);
}
$entities = api_get_entitities($statustext, $body);
@@ -2379,8 +2417,8 @@ $called_api = null;
$offset = 0;
//foreach ($urls[1] AS $id=>$url) {
foreach ($ordered_urls AS $url) {
- if ((substr($url["title"], 0, 7) != "http://") AND (substr($url["title"], 0, 8) != "https://") AND
- !strpos($url["title"], "http://") AND !strpos($url["title"], "https://"))
+ if ((substr($url["title"], 0, 7) != "http://") && (substr($url["title"], 0, 8) != "https://") &&
+ !strpos($url["title"], "http://") && !strpos($url["title"], "https://"))
$display_url = $url["title"];
else {
$display_url = str_replace(array("http://www.", "https://www."), array("", ""), $url["url"]);
@@ -2432,7 +2470,7 @@ $called_api = null;
$scale = scale_image($image[0], $image[1], 150);
$sizes["thumb"] = array("w" => $scale["width"], "h" => $scale["height"], "resize" => "fit");
- if (($image[0] > 150) OR ($image[1] > 150)) {
+ if (($image[0] > 150) || ($image[1] > 150)) {
$scale = scale_image($image[0], $image[1], 340);
$sizes["small"] = array("w" => $scale["width"], "h" => $scale["height"], "resize" => "fit");
}
@@ -2440,7 +2478,7 @@ $called_api = null;
$scale = scale_image($image[0], $image[1], 600);
$sizes["medium"] = array("w" => $scale["width"], "h" => $scale["height"], "resize" => "fit");
- if (($image[0] > 600) OR ($image[1] > 600)) {
+ if (($image[0] > 600) || ($image[1] > 600)) {
$scale = scale_image($image[0], $image[1], 1024);
$sizes["large"] = array("w" => $scale["width"], "h" => $scale["height"], "resize" => "fit");
}
@@ -2471,7 +2509,7 @@ $called_api = null;
$text = preg_replace_callback(
"|data:image/([^;]+)[^=]+=*|m",
function($match) use ($item) {
- return App::get_baseurl()."/display/".$item['guid'];
+ return System::baseUrl()."/display/".$item['guid'];
},
$text);
return $text;
@@ -2642,10 +2680,10 @@ $called_api = null;
foreach ($r as $item) {
localize_item($item);
- list($status_user, $owner_user) = api_item_get_user($a,$item);
+ list($status_user, $owner_user) = api_item_get_user($a, $item);
// Look if the posts are matching if they should be filtered by user id
- if ($filter_user AND ($status_user["id"] != $user_info["id"])) {
+ if ($filter_user && ($status_user["id"] != $user_info["id"])) {
continue;
}
@@ -2689,9 +2727,9 @@ $called_api = null;
$status["entities"] = $converted["entities"];
}
- if (($item['item_network'] != "") AND ($status["source"] == 'web')) {
+ if (($item['item_network'] != "") && ($status["source"] == 'web')) {
$status["source"] = network_to_name($item['item_network'], $user_info['url']);
- } elseif (($item['item_network'] != "") AND (network_to_name($item['item_network'], $user_info['url']) != $status["source"])) {
+ } elseif (($item['item_network'] != "") && (network_to_name($item['item_network'], $user_info['url']) != $status["source"])) {
$status["source"] = trim($status["source"].' ('.network_to_name($item['item_network'], $user_info['url']).')');
}
@@ -2700,7 +2738,7 @@ $called_api = null;
// It doesn't work reliable with the link if its a feed
//$IsRetweet = ($item['owner-link'] != $item['author-link']);
//if ($IsRetweet)
- // $IsRetweet = (($item['owner-name'] != $item['author-name']) OR ($item['owner-avatar'] != $item['author-avatar']));
+ // $IsRetweet = (($item['owner-name'] != $item['author-name']) || ($item['owner-avatar'] != $item['author-avatar']));
if ($item["id"] == $item["parent"]) {
@@ -2708,7 +2746,7 @@ $called_api = null;
if ($retweeted_item !== false) {
$retweeted_status = $status;
try {
- $retweeted_status["user"] = api_get_user($a,$retweeted_item["author-link"]);
+ $retweeted_status["user"] = api_get_user($a, $retweeted_item["author-link"]);
} catch( BadRequestException $e ) {
// user not found. should be found?
/// @todo check if the user should be always found
@@ -2888,7 +2926,7 @@ $called_api = null;
$name = $a->config['sitename'];
$server = $a->get_hostname();
- $logo = App::get_baseurl() . '/images/friendica-64.png';
+ $logo = System::baseUrl() . '/images/friendica-64.png';
$email = $a->config['admin_email'];
$closed = (($a->config['register_policy'] == REGISTER_CLOSED) ? 'true' : 'false');
$private = ((Config::get('system', 'block_public')) ? 'true' : 'false');
@@ -2897,7 +2935,7 @@ $called_api = null;
$texlimit = string($a->config['api_import_size']);
}
$ssl = ((Config::get('system', 'have_ssl')) ? 'true' : 'false');
- $sslserver = (($ssl === 'true') ? str_replace('http:','https:',App::get_baseurl()) : '');
+ $sslserver = (($ssl === 'true') ? str_replace('http:','https:',System::baseUrl()) : '');
$config = array(
'site' => array('name' => $name,'server' => $server, 'theme' => 'default', 'path' => '',
@@ -2970,12 +3008,13 @@ $called_api = null;
}
$ids = array();
- foreach ($r as $rr)
- if ($stringify_ids)
+ foreach ($r as $rr) {
+ if ($stringify_ids) {
$ids[] = $rr['id'];
} else {
$ids[] = intval($rr['id']);
}
+ }
return api_format_data("ids", $type, array('id' => $ids));
}
@@ -2998,7 +3037,7 @@ $called_api = null;
if (api_user() === false) throw new ForbiddenException();
- if (!x($_POST, "text") OR (!x($_POST,"screen_name") AND !x($_POST,"user_id"))) return;
+ if (!x($_POST, "text") || (!x($_POST,"screen_name") && !x($_POST,"user_id"))) return;
$sender = api_get_user($a);
@@ -3011,8 +3050,9 @@ $called_api = null;
api_best_nickname($r);
$recipient = api_get_user($a, $r[0]['nurl']);
- } else
+ } else {
$recipient = api_get_user($a, $_POST['user_id']);
+ }
$replyto = '';
$sub = '';
@@ -3271,13 +3311,116 @@ $called_api = null;
api_register_func('api/oauth/request_token', 'api_oauth_request_token', false);
api_register_func('api/oauth/access_token', 'api_oauth_access_token', false);
- function api_fr_photos_list($type) {
+
+ /**
+ * @brief delete a complete photoalbum with all containing photos from database through api
+ *
+ * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ * @return string
+ */
+ function api_fr_photoalbum_delete($type) {
+ if (api_user() === false) {
+ throw new ForbiddenException();
+ }
+ // input params
+ $album = (x($_REQUEST,'album') ? $_REQUEST['album'] : "");
+
+ // we do not allow calls without album string
+ if ($album == "") {
+ throw new BadRequestException("no albumname specified");
+ }
+ // check if album is existing
+ $r = q("SELECT DISTINCT `resource-id` FROM `photo` WHERE `uid` = %d AND `album` = '%s'",
+ intval(api_user()),
+ dbesc($album));
+ if (!dbm::is_result($r))
+ throw new BadRequestException("album not available");
+
+ // function for setting the items to "deleted = 1" which ensures that comments, likes etc. are not shown anymore
+ // to the user and the contacts of the users (drop_items() performs the federation of the deletion to other networks
+ foreach ($r as $rr) {
+ $photo_item = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `resource-id` = '%s' AND `type` = 'photo'",
+ intval(local_user()),
+ dbesc($rr['resource-id'])
+ );
+
+ if (!dbm::is_result($photo_item)) {
+ throw new InternalServerErrorException("problem with deleting items occured");
+ }
+ drop_item($photo_item[0]['id'],false);
+ }
+
+ // now let's delete all photos from the album
+ $result = q("DELETE FROM `photo` WHERE `uid` = %d AND `album` = '%s'",
+ intval(api_user()),
+ dbesc($album));
+
+ // return success of deletion or error message
+ if ($result) {
+ $answer = array('result' => 'deleted', 'message' => 'album `' . $album . '` with all containing photos has been deleted.');
+ return api_format_data("photoalbum_delete", $type, array('$result' => $answer));
+ } else {
+ throw new InternalServerErrorException("unknown error - deleting from database failed");
+ }
+
+ }
+
+ /**
+ * @brief update the name of the album for all photos of an album
+ *
+ * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ * @return string
+ */
+ function api_fr_photoalbum_update($type) {
if (api_user() === false) {
throw new ForbiddenException();
}
+ // input params
+ $album = (x($_REQUEST,'album') ? $_REQUEST['album'] : "");
+ $album_new = (x($_REQUEST,'album_new') ? $_REQUEST['album_new'] : "");
+
+ // we do not allow calls without album string
+ if ($album == "") {
+ throw new BadRequestException("no albumname specified");
+ }
+ if ($album_new == "") {
+ throw new BadRequestException("no new albumname specified");
+ }
+ // check if album is existing
+ $r = q("SELECT `id` FROM `photo` WHERE `uid` = %d AND `album` = '%s'",
+ intval(api_user()),
+ dbesc($album));
+ if (!dbm::is_result($r)) {
+ throw new BadRequestException("album not available");
+ }
+ // now let's update all photos to the albumname
+ $result = q("UPDATE `photo` SET `album` = '%s' WHERE `uid` = %d AND `album` = '%s'",
+ dbesc($album_new),
+ intval(api_user()),
+ dbesc($album));
- $r = q("SELECT `resource-id`, MAX(`scale`) AS `scale`, `album`, `filename`, `type`
- FROM `photo`
+ // return success of updating or error message
+ if ($result) {
+ $answer = array('result' => 'updated', 'message' => 'album `' . $album . '` with all containing photos has been renamed to `' . $album_new . '`.');
+ return api_format_data("photoalbum_update", $type, array('$result' => $answer));
+ } else {
+ throw new InternalServerErrorException("unknown error - updating in database failed");
+ }
+ }
+
+
+ /**
+ * @brief list all photos of the authenticated user
+ *
+ * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ * @return string
+ */
+ function api_fr_photos_list($type) {
+ if (api_user() === false) {
+ throw new ForbiddenException();
+ }
+ $r = q("SELECT `resource-id`, MAX(scale) AS `scale`, `album`, `filename`, `type`, MAX(`created`) AS `created`,
+ MAX(`edited`) AS `edited`, MAX(`desc`) AS `desc` FROM `photo`
WHERE `uid` = %d AND `album` != 'Contact Photos' GROUP BY `resource-id`",
intval(local_user())
);
@@ -3286,7 +3429,7 @@ $called_api = null;
'image/png' => 'png',
'image/gif' => 'gif'
);
- $data = array('photo' => array());
+ $data = array('photo'=>array());
if (dbm::is_result($r)) {
foreach ($r as $rr) {
$photo = array();
@@ -3294,7 +3437,10 @@ $called_api = null;
$photo['album'] = $rr['album'];
$photo['filename'] = $rr['filename'];
$photo['type'] = $rr['type'];
- $thumb = App::get_baseurl() . "/photo/" . $rr['resource-id'] . "-" . $rr['scale'] . "." . $typetoext[$rr['type']];
+ $thumb = System::baseUrl() . "/photo/" . $rr['resource-id'] . "-" . $rr['scale'] . "." . $typetoext[$rr['type']];
+ $photo['created'] = $rr['created'];
+ $photo['edited'] = $rr['edited'];
+ $photo['desc'] = $rr['desc'];
if ($type == "xml") {
$data['photo'][] = array("@attributes" => $photo, "1" => $thumb);
@@ -3307,23 +3453,562 @@ $called_api = null;
return api_format_data("photos", $type, $data);
}
+ /**
+ * @brief upload a new photo or change an existing photo
+ *
+ * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ * @return string
+ */
+ function api_fr_photo_create_update($type) {
+ if (api_user() === false) {
+ throw new ForbiddenException();
+ }
+ // input params
+ $photo_id = (x($_REQUEST, 'photo_id') ? $_REQUEST['photo_id'] : null);
+ $desc = (x($_REQUEST, 'desc') ? $_REQUEST['desc'] : (array_key_exists('desc', $_REQUEST) ? "" : null)); // extra check necessary to distinguish between 'not provided' and 'empty string'
+ $album = (x($_REQUEST,'album') ? $_REQUEST['album'] : null);
+ $album_new = (x($_REQUEST,'album_new') ? $_REQUEST['album_new'] : null);
+ $allow_cid = (x($_REQUEST, 'allow_cid') ? $_REQUEST['allow_cid'] : (array_key_exists('allow_cid', $_REQUEST) ? " " : null));
+ $deny_cid = (x($_REQUEST, 'deny_cid') ? $_REQUEST['deny_cid'] : (array_key_exists('deny_cid', $_REQUEST) ? " " : null));
+ $allow_gid = (x($_REQUEST, 'allow_gid') ? $_REQUEST['allow_gid'] : (array_key_exists('allow_gid', $_REQUEST) ? " " : null));
+ $deny_gid = (x($_REQUEST, 'deny_gid') ? $_REQUEST['deny_gid'] : (array_key_exists('deny_gid', $_REQUEST) ? " " : null));
+ $visibility = (x($_REQUEST, 'visibility') ? (($_REQUEST['visibility'] == "true" || $_REQUEST['visibility'] == 1) ? true : false) : false);
+
+ // do several checks on input parameters
+ // we do not allow calls without album string
+ if ($album == null) {
+ throw new BadRequestException("no albumname specified");
+ }
+ // if photo_id == null --> we are uploading a new photo
+ if ($photo_id == null) {
+ $mode = "create";
+
+ // error if no media posted in create-mode
+ if (!x($_FILES,'media')) {
+ // Output error
+ throw new BadRequestException("no media data submitted");
+ }
+
+ // album_new will be ignored in create-mode
+ $album_new = "";
+ } else {
+ $mode = "update";
+
+ // check if photo is existing in database
+ $r = q("SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' AND `album` = '%s'",
+ intval(api_user()),
+ dbesc($photo_id),
+ dbesc($album));
+ if (!dbm::is_result($r)) {
+ throw new BadRequestException("photo not available");
+ }
+ }
+
+ // checks on acl strings provided by clients
+ $acl_input_error = false;
+ $acl_input_error |= check_acl_input($allow_cid);
+ $acl_input_error |= check_acl_input($deny_cid);
+ $acl_input_error |= check_acl_input($allow_gid);
+ $acl_input_error |= check_acl_input($deny_gid);
+ if ($acl_input_error) {
+ throw new BadRequestException("acl data invalid");
+ }
+ // now let's upload the new media in create-mode
+ if ($mode == "create") {
+ $media = $_FILES['media'];
+ $data = save_media_to_database("photo", $media, $type, $album, trim($allow_cid), trim($deny_cid), trim($allow_gid), trim($deny_gid), $desc, $visibility);
+
+ // return success of updating or error message
+ if (!is_null($data)) {
+ return api_format_data("photo_create", $type, $data);
+ } else {
+ throw new InternalServerErrorException("unknown error - uploading photo failed, see Friendica log for more information");
+ }
+ }
+
+ // now let's do the changes in update-mode
+ if ($mode == "update") {
+ $sql_extra = "";
+
+ if (!is_null($desc)) {
+ $sql_extra .= (($sql_extra != "") ? " ," : "") . "`desc` = '$desc'";
+ }
+
+ if (!is_null($album_new)) {
+ $sql_extra .= (($sql_extra != "") ? " ," : "") . "`album` = '$album_new'";
+ }
+
+ if (!is_null($allow_cid)) {
+ $allow_cid = trim($allow_cid);
+ $sql_extra .= (($sql_extra != "") ? " ," : "") . "`allow_cid` = '$allow_cid'";
+ }
+
+ if (!is_null($deny_cid)) {
+ $deny_cid = trim($deny_cid);
+ $sql_extra .= (($sql_extra != "") ? " ," : "") . "`deny_cid` = '$deny_cid'";
+ }
+
+ if (!is_null($allow_gid)) {
+ $allow_gid = trim($allow_gid);
+ $sql_extra .= (($sql_extra != "") ? " ," : "") . "`allow_gid` = '$allow_gid'";
+ }
+
+ if (!is_null($deny_gid)) {
+ $deny_gid = trim($deny_gid);
+ $sql_extra .= (($sql_extra != "") ? " ," : "") . "`deny_gid` = '$deny_gid'";
+ }
+
+ $result = false;
+ if ($sql_extra != "") {
+ $nothingtodo = false;
+ $result = q("UPDATE `photo` SET %s, `edited`='%s' WHERE `uid` = %d AND `resource-id` = '%s' AND `album` = '%s'",
+ $sql_extra,
+ datetime_convert(), // update edited timestamp
+ intval(api_user()),
+ dbesc($photo_id),
+ dbesc($album));
+ } else {
+ $nothingtodo = true;
+ }
+
+ if (x($_FILES,'media')) {
+ $nothingtodo = false;
+ $media = $_FILES['media'];
+ $data = save_media_to_database("photo", $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, 0, $visibility, $photo_id);
+ if (!is_null($data)) {
+ return api_format_data("photo_update", $type, $data);
+ }
+ }
+
+ // return success of updating or error message
+ if ($result) {
+ $answer = array('result' => 'updated', 'message' => 'Image id `' . $photo_id . '` has been updated.');
+ return api_format_data("photo_update", $type, array('$result' => $answer));
+ } else {
+ if ($nothingtodo) {
+ $answer = array('result' => 'cancelled', 'message' => 'Nothing to update for image id `' . $photo_id . '`.');
+ return api_format_data("photo_update", $type, array('$result' => $answer));
+ }
+ throw new InternalServerErrorException("unknown error - update photo entry in database failed");
+ }
+ }
+ throw new InternalServerErrorException("unknown error - this error on uploading or updating a photo should never happen");
+ }
+
+
+ /**
+ * @brief delete a single photo from the database through api
+ *
+ * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ * @return string
+ */
+ function api_fr_photo_delete($type) {
+ if (api_user() === false) {
+ throw new ForbiddenException();
+ }
+ // input params
+ $photo_id = (x($_REQUEST, 'photo_id') ? $_REQUEST['photo_id'] : null);
+
+ // do several checks on input parameters
+ // we do not allow calls without photo id
+ if ($photo_id == null) {
+ throw new BadRequestException("no photo_id specified");
+ }
+ // check if photo is existing in database
+ $r = q("SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'",
+ intval(api_user()),
+ dbesc($photo_id)
+ );
+ if (!dbm::is_result($r)) {
+ throw new BadRequestException("photo not available");
+ }
+ // now we can perform on the deletion of the photo
+ $result = q("DELETE FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'",
+ intval(api_user()),
+ dbesc($photo_id));
+
+ // return success of deletion or error message
+ if ($result) {
+ // retrieve the id of the parent element (the photo element)
+ $photo_item = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `resource-id` = '%s' AND `type` = 'photo'",
+ intval(local_user()),
+ dbesc($photo_id)
+ );
+
+ if (!dbm::is_result($photo_item)) {
+ throw new InternalServerErrorException("problem with deleting items occured");
+ }
+ // function for setting the items to "deleted = 1" which ensures that comments, likes etc. are not shown anymore
+ // to the user and the contacts of the users (drop_items() do all the necessary magic to avoid orphans in database and federate deletion)
+ drop_item($photo_item[0]['id'], false);
+
+ $answer = array('result' => 'deleted', 'message' => 'photo with id `' . $photo_id . '` has been deleted from server.');
+ return api_format_data("photo_delete", $type, array('$result' => $answer));
+ } else {
+ throw new InternalServerErrorException("unknown error on deleting photo from database table");
+ }
+ }
+
+
+ /**
+ * @brief returns the details of a specified photo id, if scale is given, returns the photo data in base 64
+ *
+ * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ * @return string
+ */
function api_fr_photo_detail($type) {
if (api_user() === false) {
throw new ForbiddenException();
- } elseif (!x($_REQUEST, 'photo_id')) {
+ }
+ if (!x($_REQUEST, 'photo_id')) {
throw new BadRequestException("No photo id.");
}
$scale = (x($_REQUEST, 'scale') ? intval($_REQUEST['scale']) : false);
- $scale_sql = ($scale === false ? "" : sprintf("and scale=%d", intval($scale)));
+ $photo_id = $_REQUEST['photo_id'];
+
+ // prepare json/xml output with data from database for the requested photo
+ $data = prepare_photo_data($type, $scale, $photo_id);
+
+ return api_format_data("photo_detail", $type, $data);
+ }
+
+
+ /**
+ * @brief updates the profile image for the user (either a specified profile or the default profile)
+ *
+ * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ * @return string
+ */
+ function api_account_update_profile_image($type) {
+ if (api_user() === false) {
+ throw new ForbiddenException();
+ }
+ // input params
+ $profileid = (x($_REQUEST, 'profile_id') ? $_REQUEST['profile_id'] : 0);
+
+ // error if image data is missing
+ if (!x($_FILES, 'image')) {
+ throw new BadRequestException("no media data submitted");
+ }
+
+ // check if specified profile id is valid
+ if ($profileid != 0) {
+ $r = q("SELECT `id` FROM `profile` WHERE `uid` = %d AND `id` = %d",
+ intval(api_user()),
+ intval($profileid));
+ // error message if specified profile id is not in database
+ if (!dbm::is_result($r)) {
+ throw new BadRequestException("profile_id not available");
+ }
+ $is_default_profile = $r['profile'];
+ } else {
+ $is_default_profile = 1;
+ }
+
+ // get mediadata from image or media (Twitter call api/account/update_profile_image provides image)
+ $media = null;
+ if (x($_FILES, 'image')) {
+ $media = $_FILES['image'];
+ } elseif (x($_FILES, 'media')) {
+ $media = $_FILES['media'];
+ }
+ // save new profile image
+ $data = save_media_to_database("profileimage", $media, $type, t('Profile Photos'), "", "", "", "", "", $is_default_profile);
+
+ // get filetype
+ if (is_array($media['type'])) {
+ $filetype = $media['type'][0];
+ } else {
+ $filetype = $media['type'];
+ }
+ if ($filetype == "image/jpeg") {
+ $fileext = "jpg";
+ } elseif ($filetype == "image/png") {
+ $fileext = "png";
+ }
+ // change specified profile or all profiles to the new resource-id
+ if ($is_default_profile) {
+ $r = q("UPDATE `photo` SET `profile` = 0 WHERE `profile` = 1 AND `resource-id` != '%s' AND `uid` = %d",
+ dbesc($data['photo']['id']),
+ intval(local_user())
+ );
+
+ $r = q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s' WHERE `self` AND `uid` = %d",
+ dbesc(System::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $fileext),
+ dbesc(System::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $fileext),
+ dbesc(System::baseUrl() . '/photo/' . $data['photo']['id'] . '-6.' . $fileext),
+ intval(local_user())
+ );
+ } else {
+ $r = q("UPDATE `profile` SET `photo` = '%s', `thumb` = '%s' WHERE `id` = %d AND `uid` = %d",
+ dbesc(System::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $filetype),
+ dbesc(System::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $filetype),
+ intval($_REQUEST['profile']),
+ intval(local_user())
+ );
+ }
+
+ // we'll set the updated profile-photo timestamp even if it isn't the default profile,
+ // so that browsers will do a cache update unconditionally
+
+ $r = q("UPDATE `contact` SET `avatar-date` = '%s' WHERE `self` = 1 AND `uid` = %d",
+ dbesc(datetime_convert()),
+ intval(local_user())
+ );
+
+ // Update global directory in background
+ //$user = api_get_user(get_app());
+ $url = System::baseUrl() . '/profile/' . get_app()->user['nickname'];
+ if ($url && strlen(get_config('system', 'directory'))) {
+ proc_run(PRIORITY_LOW, "include/directory.php", $url);
+ }
+
+ proc_run(PRIORITY_LOW, 'include/profile_update.php', api_user());
+
+ // output for client
+ if ($data) {
+ return api_account_verify_credentials($type);
+ } else {
+ // SaveMediaToDatabase failed for some reason
+ throw new InternalServerErrorException("image upload failed");
+ }
+ }
+
+ // place api-register for photoalbum calls before 'api/friendica/photo', otherwise this function is never reached
+ api_register_func('api/friendica/photoalbum/delete', 'api_fr_photoalbum_delete', true, API_METHOD_DELETE);
+ api_register_func('api/friendica/photoalbum/update', 'api_fr_photoalbum_update', true, API_METHOD_POST);
+ api_register_func('api/friendica/photos/list', 'api_fr_photos_list', true);
+ api_register_func('api/friendica/photo/create', 'api_fr_photo_create_update', true, API_METHOD_POST);
+ api_register_func('api/friendica/photo/update', 'api_fr_photo_create_update', true, API_METHOD_POST);
+ api_register_func('api/friendica/photo/delete', 'api_fr_photo_delete', true, API_METHOD_DELETE);
+ api_register_func('api/friendica/photo', 'api_fr_photo_detail', true);
+ api_register_func('api/account/update_profile_image', 'api_account_update_profile_image', true, API_METHOD_POST);
+
+
+ function check_acl_input($acl_string) {
+ if ($acl_string == null || $acl_string == " ") {
+ return false;
+ }
+ $contact_not_found = false;
+
+ // split into array of cid's
+ preg_match_all("/<[A-Za-z0-9]+>/", $acl_string, $array);
+
+ // check for each cid if it is available on server
+ $cid_array = $array[0];
+ foreach ($cid_array as $cid) {
+ $cid = str_replace("<", "", $cid);
+ $cid = str_replace(">", "", $cid);
+ $contact = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d",
+ intval($cid),
+ intval(api_user()));
+ $contact_not_found |= !dbm::is_result($contact);
+ }
+ return $contact_not_found;
+ }
+
+ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, $profile = 0, $visibility = false, $photo_id = null) {
+ $visitor = 0;
+ $src = "";
+ $filetype = "";
+ $filename = "";
+ $filesize = 0;
+
+ if (is_array($media)) {
+ if (is_array($media['tmp_name'])) {
+ $src = $media['tmp_name'][0];
+ } else {
+ $src = $media['tmp_name'];
+ }
+ if (is_array($media['name'])) {
+ $filename = basename($media['name'][0]);
+ } else {
+ $filename = basename($media['name']);
+ }
+ if (is_array($media['size'])) {
+ $filesize = intval($media['size'][0]);
+ } else {
+ $filesize = intval($media['size']);
+ }
+ if (is_array($media['type'])) {
+ $filetype = $media['type'][0];
+ } else {
+ $filetype = $media['type'];
+ }
+ }
+
+ if ($filetype == "") {
+ $filetype=guess_image_type($filename);
+ }
+ $imagedata = getimagesize($src);
+ if ($imagedata) {
+ $filetype = $imagedata['mime'];
+ }
+ logger("File upload src: " . $src . " - filename: " . $filename .
+ " - size: " . $filesize . " - type: " . $filetype, LOGGER_DEBUG);
+
+ // check if there was a php upload error
+ if ($filesize == 0 && $media['error'] == 1) {
+ throw new InternalServerErrorException("image size exceeds PHP config settings, file was rejected by server");
+ }
+ // check against max upload size within Friendica instance
+ $maximagesize = get_config('system', 'maximagesize');
+ if (($maximagesize) && ($filesize > $maximagesize)) {
+ $formattedBytes = formatBytes($maximagesize);
+ throw new InternalServerErrorException("image size exceeds Friendica config setting (uploaded size: $formattedBytes)");
+ }
+
+ // create Photo instance with the data of the image
+ $imagedata = @file_get_contents($src);
+ $ph = new Photo($imagedata, $filetype);
+ if (! $ph->is_valid()) {
+ throw new InternalServerErrorException("unable to process image data");
+ }
+
+ // check orientation of image
+ $ph->orient($src);
+ @unlink($src);
+
+ // check max length of images on server
+ $max_length = get_config('system', 'max_image_length');
+ if (! $max_length) {
+ $max_length = MAX_IMAGE_LENGTH;
+ }
+ if ($max_length > 0) {
+ $ph->scaleImage($max_length);
+ logger("File upload: Scaling picture to new size " . $max_length, LOGGER_DEBUG);
+ }
+ $width = $ph->getWidth();
+ $height = $ph->getHeight();
+
+ // create a new resource-id if not already provided
+ $hash = ($photo_id == null) ? photo_new_resource() : $photo_id;
+
+ if ($mediatype == "photo") {
+ // upload normal image (scales 0, 1, 2)
+ logger("photo upload: starting new photo upload", LOGGER_DEBUG);
+
+ $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) {
+ $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) {
+ $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: new photo upload ended", LOGGER_DEBUG);
+ } elseif ($mediatype == "profileimage") {
+ // upload profile image (scales 4, 5, 6)
+ logger("photo upload: starting new profile image upload", LOGGER_DEBUG);
+
+ if ($width > 175 || $height > 175) {
+ $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) {
+ $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) {
+ $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");
+ }
+ }
+ $ph->__destruct();
+ logger("photo upload: new profile image upload ended", LOGGER_DEBUG);
+ }
+
+ if ($r) {
+ // create entry in 'item'-table on new uploads to enable users to comment/like/dislike the photo
+ if ($photo_id == null && $mediatype == "photo") {
+ post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility);
+ }
+ // on success return image data in json/xml format (like /api/friendica/photo does when no scale is given)
+ return prepare_photo_data($type, false, $hash);
+ } else {
+ throw new InternalServerErrorException("image upload failed");
+ }
+ }
+
+ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility = false) {
+ // get data about the api authenticated user
+ $uri = item_new_uri(get_app()->get_hostname(), intval(api_user()));
+ $owner_record = q("SELECT * FROM `contact` WHERE `uid`= %d AND `self` LIMIT 1", intval(api_user()));
+
+ $arr = array();
+ $arr['guid'] = get_guid(32);
+ $arr['uid'] = intval(api_user());
+ $arr['uri'] = $uri;
+ $arr['parent-uri'] = $uri;
+ $arr['type'] = 'photo';
+ $arr['wall'] = 1;
+ $arr['resource-id'] = $hash;
+ $arr['contact-id'] = $owner_record[0]['id'];
+ $arr['owner-name'] = $owner_record[0]['name'];
+ $arr['owner-link'] = $owner_record[0]['url'];
+ $arr['owner-avatar'] = $owner_record[0]['thumb'];
+ $arr['author-name'] = $owner_record[0]['name'];
+ $arr['author-link'] = $owner_record[0]['url'];
+ $arr['author-avatar'] = $owner_record[0]['thumb'];
+ $arr['title'] = "";
+ $arr['allow_cid'] = $allow_cid;
+ $arr['allow_gid'] = $allow_gid;
+ $arr['deny_cid'] = $deny_cid;
+ $arr['deny_gid'] = $deny_gid;
+ $arr['last-child'] = 1;
+ $arr['visible'] = $visibility;
+ $arr['origin'] = 1;
+
+ $typetoext = array(
+ 'image/jpeg' => 'jpg',
+ 'image/png' => 'png',
+ 'image/gif' => 'gif'
+ );
+
+ // adds link to the thumbnail scale photo
+ $arr['body'] = '[url=' . System::baseUrl() . '/photos/' . $owner_record[0]['nick'] . '/image/' . $hash . ']'
+ . '[img]' . System::baseUrl() . '/photo/' . $hash . '-' . "2" . '.'. $typetoext[$filetype] . '[/img]'
+ . '[/url]';
+
+ // do the magic for storing the item in the database and trigger the federation to other contacts
+ item_store($arr);
+ }
+
+ function prepare_photo_data($type, $scale, $photo_id) {
+ $scale_sql = ($scale === false ? "" : sprintf("AND scale=%d", intval($scale)));
$data_sql = ($scale === false ? "" : "data, ");
+ // added allow_cid, allow_gid, deny_cid, deny_gid to output as string like stored in database
+ // clients needs to convert this in their way for further processing
$r = q("SELECT %s `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`,
- `type`, `height`, `width`, `datasize`, `profile`, MIN(`scale`) AS `minscale`, MAX(`scale`) AS `maxscale`
+ `type`, `height`, `width`, `datasize`, `profile`, `allow_cid`, `deny_cid`, `allow_gid`, `deny_gid`,
+ MIN(`scale`) AS `minscale`, MAX(`scale`) AS `maxscale`
FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' %s GROUP BY `resource-id`",
$data_sql,
intval(local_user()),
- dbesc($_REQUEST['photo_id']),
+ dbesc($photo_id),
$scale_sql
);
@@ -3333,6 +4018,7 @@ $called_api = null;
'image/gif' => 'gif'
);
+ // prepare output data for photo
if (dbm::is_result($r)) {
$data = array('photo' => $r[0]);
$data['photo']['id'] = $data['photo']['resource-id'];
@@ -3345,13 +4031,16 @@ $called_api = null;
$data['photo']['links'] = array();
for ($k = intval($data['photo']['minscale']); $k <= intval($data['photo']['maxscale']); $k++) {
$data['photo']['links'][$k . ":link"]["@attributes"] = array("type" => $data['photo']['type'],
- "scale" => $k,
- "href" => App::get_baseurl() . "/photo/" . $data['photo']['resource-id'] . "-" . $k . "." . $typetoext[$data['photo']['type']]);
+ "scale" => $k,
+ "href" => System::baseUrl() . "/photo/" . $data['photo']['resource-id'] . "-" . $k . "." . $typetoext[$data['photo']['type']]);
}
} else {
$data['photo']['link'] = array();
+ // when we have profile images we could have only scales from 4 to 6, but index of array always needs to start with 0
+ $i = 0;
for ($k = intval($data['photo']['minscale']); $k <= intval($data['photo']['maxscale']); $k++) {
- $data['photo']['link'][$k] = App::get_baseurl() . "/photo/" . $data['photo']['resource-id'] . "-" . $k . "." . $typetoext[$data['photo']['type']];
+ $data['photo']['link'][$i] = System::baseUrl() . "/photo/" . $data['photo']['resource-id'] . "-" . $k . "." . $typetoext[$data['photo']['type']];
+ $i++;
}
}
unset($data['photo']['resource-id']);
@@ -3362,12 +4051,53 @@ $called_api = null;
throw new NotFoundException();
}
- return api_format_data("photo_detail", $type, $data);
- }
+ // retrieve item element for getting activities (like, dislike etc.) related to photo
+ $item = q("SELECT * FROM `item` WHERE `uid` = %d AND `resource-id` = '%s' AND `type` = 'photo'",
+ intval(local_user()),
+ dbesc($photo_id)
+ );
+ $data['photo']['friendica_activities'] = api_format_items_activities($item[0], $type);
- api_register_func('api/friendica/photos/list', 'api_fr_photos_list', true);
- api_register_func('api/friendica/photo', 'api_fr_photo_detail', true);
+ // retrieve comments on photo
+ $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
+ `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
+ `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
+ `contact`.`id` AS `cid`
+ FROM `item`
+ STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
+ AND (NOT `contact`.`blocked` OR `contact`.`pending`)
+ WHERE `item`.`parent` = %d AND `item`.`visible`
+ AND NOT `item`.`moderated` AND NOT `item`.`deleted`
+ AND `item`.`uid` = %d AND (`item`.`verb`='%s' OR `type`='photo')",
+ intval($item[0]['parent']),
+ intval(api_user()),
+ dbesc(ACTIVITY_POST)
+ );
+ // prepare output of comments
+ $commentData = api_format_items($r, api_get_user(get_app()), false, $type);
+ $comments = array();
+ if ($type == "xml") {
+ $k = 0;
+ foreach ($commentData as $comment) {
+ $comments[$k++ . ":comment"] = $comment;
+ }
+ } else {
+ foreach ($commentData as $comment) {
+ $comments[] = $comment;
+ }
+ }
+ $data['photo']['friendica_comments'] = $comments;
+
+ // include info if rights on photo and rights on item are mismatching
+ $rights_mismatch = $data['photo']['allow_cid'] != $item[0]['allow_cid'] ||
+ $data['photo']['deny_cid'] != $item[0]['deny_cid'] ||
+ $data['photo']['allow_gid'] != $item[0]['allow_gid'] ||
+ $data['photo']['deny_cid'] != $item[0]['deny_cid'];
+ $data['photo']['rights_mismatch'] = $rights_mismatch;
+
+ return $data;
+ }
/**
@@ -3619,7 +4349,7 @@ $called_api = null;
$in_reply_to['user_id_str'] = NULL;
$in_reply_to['screen_name'] = NULL;
- if (($item['thr-parent'] != $item['uri']) AND (intval($item['parent']) != intval($item['id']))) {
+ if (($item['thr-parent'] != $item['uri']) && (intval($item['parent']) != intval($item['id']))) {
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' LIMIT 1",
intval($item['uid']),
dbesc($item['thr-parent']));
@@ -3700,7 +4430,7 @@ $called_api = null;
if (isset($data["text"]))
$body = $data["text"];
- if (($body == "") AND (isset($data["title"])))
+ if (($body == "") && (isset($data["title"])))
$body = $data["title"];
if (isset($data["url"]))
@@ -4291,7 +5021,6 @@ friendships/exists
friendships/show
account/update_location
account/update_profile_background_image
-account/update_profile_image
blocks/create
blocks/destroy
friendica/profile/update