Merge pull request #3418 from gerhard6380/develop
New API calls for photo management
This commit is contained in:
commit
1f58bcc114
118
doc/api.md
118
doc/api.md
|
@ -465,6 +465,28 @@ Friendica doesn't allow showing followers of other users.
|
||||||
Friendica doesn't allow showing friends of other users.
|
Friendica doesn't allow showing friends of other users.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
### account/update_profile_image (POST; AUTH)
|
||||||
|
#### Parameters
|
||||||
|
* image: image data as base64 (Twitter has a limit of 700kb, Friendica allows more)
|
||||||
|
* profile_id (optional): id of the profile for which the image should be used, default is changing the default profile
|
||||||
|
|
||||||
|
uploads a new profile image (scales 4-6) to database, changes default or specified profile to the new photo
|
||||||
|
|
||||||
|
#### Return values
|
||||||
|
|
||||||
|
On success:
|
||||||
|
* JSON return: returns the updated user details (see account/verify_credentials)
|
||||||
|
|
||||||
|
On error:
|
||||||
|
* 403 FORBIDDEN: if not authenticated
|
||||||
|
* 400 BADREQUEST: "no media data submitted", "profile_id not available"
|
||||||
|
* 500 INTERNALSERVERERROR: "image size exceeds PHP config settings, file was rejected by server",
|
||||||
|
"image size exceeds Friendica Config setting (uploaded size: x)",
|
||||||
|
"unable to process image data",
|
||||||
|
"image upload failed"
|
||||||
|
|
||||||
|
|
||||||
## Implemented API calls (not compatible with other APIs)
|
## Implemented API calls (not compatible with other APIs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -724,6 +746,100 @@ xml
|
||||||
</photos>
|
</photos>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
### friendica/photoalbum/delete (POST,DELETE; AUTH)
|
||||||
|
#### Parameters
|
||||||
|
* album: name of the album to be deleted
|
||||||
|
|
||||||
|
deletes all images with the specified album name, is not reversible -> ensure that client is asking user for being sure to do this
|
||||||
|
|
||||||
|
#### Return values
|
||||||
|
|
||||||
|
On success:
|
||||||
|
* JSON return {"result":"deleted","message":"album 'xyz' with all containing photos has been deleted."}
|
||||||
|
|
||||||
|
On error:
|
||||||
|
* 403 FORBIDDEN: if not authenticated
|
||||||
|
* 400 BADREQUEST: "no albumname specified", "album not available"
|
||||||
|
* 500 INTERNALSERVERERROR: "problem with deleting item occured", "unknown error - deleting from database failed"
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
### friendica/photoalbum/update (POST,PUT; AUTH)
|
||||||
|
#### Parameters
|
||||||
|
* album: name of the album to be updated
|
||||||
|
* album_new: new name of the album
|
||||||
|
|
||||||
|
changes the album name to album_new for all photos in album
|
||||||
|
|
||||||
|
#### Return values
|
||||||
|
|
||||||
|
On success:
|
||||||
|
* JSON return {"result":"updated","message":"album 'abc' with all containing photos has been renamed to 'xyz'."}
|
||||||
|
|
||||||
|
On error:
|
||||||
|
* 403 FORBIDDEN: if not authenticated
|
||||||
|
* 400 BADREQUEST: "no albumname specified", "no new albumname specified", "album not available"
|
||||||
|
* 500 INTERNALSERVERERROR: "unknown error - updating in database failed"
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
### friendica/photo/create (POST; AUTH)
|
||||||
|
### friendica/photo/update (POST; AUTH)
|
||||||
|
#### Parameters
|
||||||
|
* photo_id (optional): if specified the photo with this id will be updated
|
||||||
|
* media (optional): image data as base64, only optional if photo_id is specified (new upload must have media)
|
||||||
|
* desc (optional): description for the photo, updated when photo_id is specified
|
||||||
|
* album: name of the album to be deleted (always necessary)
|
||||||
|
* album_new (optional): can be used to change the album of a single photo if photo_id is specified
|
||||||
|
* allow_cid/allow_gid/deny_cid/deny_gid (optional): on create: empty string or omitting = public photo, specify in format '```<x><y><z>```' for private photo;
|
||||||
|
on update: keys need to be present with empty values for setting a private photo now to public
|
||||||
|
|
||||||
|
both calls point to one function for creating AND updating photos.
|
||||||
|
Saves data for the scales 0-2 to database (see above for scale description).
|
||||||
|
Call adds non-visible entries to items table to enable authenticated contacts to comment/like the photo.
|
||||||
|
Client should pay attention to the fact that updated access rights are not transferred to the contacts. i.e. public photos remain publicly visible if they have been commented/liked before setting visibility back to a limited group.
|
||||||
|
Currently it is best way to inform user that updating rights is not the best way, offer a solution to add photo as a new photo with the new rights.
|
||||||
|
|
||||||
|
#### Return values
|
||||||
|
|
||||||
|
On success:
|
||||||
|
* new photo uploaded: JSON return with photo data (see friendica/photo)
|
||||||
|
* photo updated - changed photo data: JSON return with photo data (see friendica/photo)
|
||||||
|
* photo updated - changed info: JSON return {"result":"updated","message":"Image id 'xyz' has been updated."}
|
||||||
|
* photo updated - nothing changed: JSON return {"result":"cancelled","message":"Nothing to update for image id 'xyz'."}
|
||||||
|
|
||||||
|
On error:
|
||||||
|
* 403 FORBIDDEN: if not authenticated
|
||||||
|
* 400 BADREQUEST: "no albumname specified", "no media data submitted", "photo not available", "acl data invalid"
|
||||||
|
* 500 INTERNALSERVERERROR: "image size exceeds PHP config settings, file was rejected by server",
|
||||||
|
"image size exceeds Friendica Config setting (uploaded size: x)",
|
||||||
|
"unable to process image data",
|
||||||
|
"image upload failed",
|
||||||
|
"unknown error - uploading photo failed, see Friendica log for more information",
|
||||||
|
"unknown error - update photo entry in database failed",
|
||||||
|
"unknown error - this error on uploading or updating a photo should never happen"
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
### friendica/photo/delete (DELETE; AUTH)
|
||||||
|
#### Parameters
|
||||||
|
* photo_id: id of the photo to be deleted
|
||||||
|
|
||||||
|
deletes a single image with the specified id, is not reversible -> ensure that client is asking user for being sure to do this
|
||||||
|
Sets item table entries for this photo to deleted = 1
|
||||||
|
|
||||||
|
#### Return values
|
||||||
|
|
||||||
|
On success:
|
||||||
|
* JSON return {"result":"deleted","message":"photo with id 'xyz' has been deleted from server."}
|
||||||
|
|
||||||
|
On error:
|
||||||
|
* 403 FORBIDDEN: if not authenticated
|
||||||
|
* 400 BADREQUEST: "no photo_id specified", "photo not available"
|
||||||
|
* 500 INTERNALSERVERERROR: "unknown error on deleting photo", "problem with deleting items occurred"
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
### friendica/direct_messages_setseen (GET; AUTH)
|
### friendica/direct_messages_setseen (GET; AUTH)
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
@ -794,7 +910,6 @@ The following API calls are implemented in GNU Social but not in Friendica: (inc
|
||||||
* friendships/exists
|
* friendships/exists
|
||||||
* friendships/show
|
* friendships/show
|
||||||
* account/update_profile_background_image
|
* account/update_profile_background_image
|
||||||
* account/update_profile_image
|
|
||||||
* blocks/create
|
* blocks/create
|
||||||
* blocks/destroy
|
* blocks/destroy
|
||||||
|
|
||||||
|
@ -817,7 +932,6 @@ The following API calls from the Twitter API aren't implemented neither in Frien
|
||||||
* account/update_delivery_device
|
* account/update_delivery_device
|
||||||
* account/update_profile
|
* account/update_profile
|
||||||
* account/update_profile_background_image
|
* account/update_profile_background_image
|
||||||
* account/update_profile_image
|
|
||||||
* blocks/list
|
* blocks/list
|
||||||
* blocks/ids
|
* blocks/ids
|
||||||
* users/lookup
|
* users/lookup
|
||||||
|
|
|
@ -70,7 +70,9 @@ class Photo {
|
||||||
$this->image->destroy();
|
$this->image->destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
imagedestroy($this->image);
|
if (is_resource($this->image)) {
|
||||||
|
imagedestroy($this->image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +328,7 @@ class Photo {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if script dies at this point check memory_limit setting in php.ini
|
||||||
$this->image = imagerotate($this->image,$degrees,0);
|
$this->image = imagerotate($this->image,$degrees,0);
|
||||||
$this->width = imagesx($this->image);
|
$this->width = imagesx($this->image);
|
||||||
$this->height = imagesy($this->image);
|
$this->height = imagesy($this->image);
|
||||||
|
@ -622,7 +625,7 @@ class Photo {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function store($uid, $cid, $rid, $filename, $album, $scale, $profile = 0, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '') {
|
public function store($uid, $cid, $rid, $filename, $album, $scale, $profile = 0, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '', $desc = '') {
|
||||||
|
|
||||||
$r = q("SELECT `guid` FROM `photo` WHERE `resource-id` = '%s' AND `guid` != '' LIMIT 1",
|
$r = q("SELECT `guid` FROM `photo` WHERE `resource-id` = '%s' AND `guid` != '' LIMIT 1",
|
||||||
dbesc($rid)
|
dbesc($rid)
|
||||||
|
@ -659,7 +662,8 @@ class Photo {
|
||||||
`allow_cid` = '%s',
|
`allow_cid` = '%s',
|
||||||
`allow_gid` = '%s',
|
`allow_gid` = '%s',
|
||||||
`deny_cid` = '%s',
|
`deny_cid` = '%s',
|
||||||
`deny_gid` = '%s'
|
`deny_gid` = '%s',
|
||||||
|
`desc` = '%s'
|
||||||
WHERE `id` = %d",
|
WHERE `id` = %d",
|
||||||
|
|
||||||
intval($uid),
|
intval($uid),
|
||||||
|
@ -681,12 +685,13 @@ class Photo {
|
||||||
dbesc($allow_gid),
|
dbesc($allow_gid),
|
||||||
dbesc($deny_cid),
|
dbesc($deny_cid),
|
||||||
dbesc($deny_gid),
|
dbesc($deny_gid),
|
||||||
|
dbesc($desc),
|
||||||
intval($x[0]['id'])
|
intval($x[0]['id'])
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$r = q("INSERT INTO `photo`
|
$r = q("INSERT INTO `photo`
|
||||||
(`uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, type, `album`, `height`, `width`, `datasize`, `data`, `scale`, `profile`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`)
|
(`uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, type, `album`, `height`, `width`, `datasize`, `data`, `scale`, `profile`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `desc`)
|
||||||
VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', %d, %d, '%s', '%s', '%s', '%s')",
|
VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', %d, %d, '%s', '%s', '%s', '%s', '%s')",
|
||||||
intval($uid),
|
intval($uid),
|
||||||
intval($cid),
|
intval($cid),
|
||||||
dbesc($guid),
|
dbesc($guid),
|
||||||
|
@ -705,7 +710,8 @@ class Photo {
|
||||||
dbesc($allow_cid),
|
dbesc($allow_cid),
|
||||||
dbesc($allow_gid),
|
dbesc($allow_gid),
|
||||||
dbesc($deny_cid),
|
dbesc($deny_cid),
|
||||||
dbesc($deny_gid)
|
dbesc($deny_gid),
|
||||||
|
dbesc($desc)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
735
include/api.php
735
include/api.php
|
@ -3287,14 +3287,117 @@ $called_api = null;
|
||||||
api_register_func('api/oauth/request_token', 'api_oauth_request_token', false);
|
api_register_func('api/oauth/request_token', 'api_oauth_request_token', false);
|
||||||
api_register_func('api/oauth/access_token', 'api_oauth_access_token', false);
|
api_register_func('api/oauth/access_token', 'api_oauth_access_token', false);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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));
|
||||||
|
|
||||||
|
// 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) {
|
function api_fr_photos_list($type) {
|
||||||
if (api_user() === false) {
|
if (api_user() === false) {
|
||||||
throw new ForbiddenException();
|
throw new ForbiddenException();
|
||||||
}
|
}
|
||||||
|
$r = q("SELECT `resource-id`, MAX(scale) AS `scale`, `album`, `filename`, `type`, MAX(`created`) AS `created`,
|
||||||
$r = q("SELECT `resource-id`, MAX(`scale`) AS `scale`, `album`, `filename`, `type`
|
MAX(`edited`) AS `edited`, MAX(`desc`) AS `desc` FROM `photo`
|
||||||
FROM `photo`
|
WHERE `uid` = %d AND `album` != 'Contact Photos' GROUP BY `resource-id`",
|
||||||
WHERE `uid` = %d AND `album` != 'Contact Photos' GROUP BY `resource-id`, `album`, `filename`, `type`",
|
|
||||||
intval(local_user())
|
intval(local_user())
|
||||||
);
|
);
|
||||||
$typetoext = array(
|
$typetoext = array(
|
||||||
|
@ -3302,7 +3405,7 @@ $called_api = null;
|
||||||
'image/png' => 'png',
|
'image/png' => 'png',
|
||||||
'image/gif' => 'gif'
|
'image/gif' => 'gif'
|
||||||
);
|
);
|
||||||
$data = array('photo' => array());
|
$data = array('photo'=>array());
|
||||||
if (dbm::is_result($r)) {
|
if (dbm::is_result($r)) {
|
||||||
foreach ($r as $rr) {
|
foreach ($r as $rr) {
|
||||||
$photo = array();
|
$photo = array();
|
||||||
|
@ -3311,6 +3414,9 @@ $called_api = null;
|
||||||
$photo['filename'] = $rr['filename'];
|
$photo['filename'] = $rr['filename'];
|
||||||
$photo['type'] = $rr['type'];
|
$photo['type'] = $rr['type'];
|
||||||
$thumb = App::get_baseurl() . "/photo/" . $rr['resource-id'] . "-" . $rr['scale'] . "." . $typetoext[$rr['type']];
|
$thumb = App::get_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") {
|
if ($type == "xml") {
|
||||||
$data['photo'][] = array("@attributes" => $photo, "1" => $thumb);
|
$data['photo'][] = array("@attributes" => $photo, "1" => $thumb);
|
||||||
|
@ -3323,26 +3429,563 @@ $called_api = null;
|
||||||
return api_format_data("photos", $type, $data);
|
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) {
|
function api_fr_photo_detail($type) {
|
||||||
if (api_user() === false) {
|
if (api_user() === false) {
|
||||||
throw new ForbiddenException();
|
throw new ForbiddenException();
|
||||||
} elseif (!x($_REQUEST, 'photo_id')) {
|
}
|
||||||
|
if (!x($_REQUEST, 'photo_id')) {
|
||||||
throw new BadRequestException("No photo id.");
|
throw new BadRequestException("No photo id.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$scale = (x($_REQUEST, 'scale') ? intval($_REQUEST['scale']) : false);
|
$scale = (x($_REQUEST, 'scale') ? intval($_REQUEST['scale']) : false);
|
||||||
$scale_sql = ($scale === false ? "" : sprintf("AND `scale`=%d",intval($scale)));
|
$photo_id = $_REQUEST['photo_id'];
|
||||||
$data_sql = ($scale === false ? "" : "ANY_VALUE(`data`) AS data`,");
|
|
||||||
|
|
||||||
$r = q("SELECT %s ANY_VALUE(`resource-id`) AS `resource-id`, ANY_VALUE(`created`) AS `created`,
|
// prepare json/xml output with data from database for the requested photo
|
||||||
ANY_VALUE(`edited`) AS `edited`, ANY_VALUE(`title`) AS `title`, ANY_VALUE(`desc`) AS `desc`,
|
$data = prepare_photo_data($type, $scale, $photo_id);
|
||||||
ANY_VALUE(`album`) AS `album`, ANY_VALUE(`filename`) AS `filename`, ANY_VALUE(`type`) AS `type`,
|
|
||||||
ANY_VALUE(`height`) AS `height`, ANY_VALUE(`width`) AS `width`, ANY_VALUE(`datasize`) AS `datasize`,
|
return api_format_data("photo_detail", $type, $data);
|
||||||
ANY_VALUE(`profile`) AS `profile`, min(`scale`) as minscale, max(`scale`) as maxscale
|
}
|
||||||
FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' %s",
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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(App::get_baseurl() . '/photo/' . $data['photo']['id'] . '-4.' . $fileext),
|
||||||
|
dbesc(App::get_baseurl() . '/photo/' . $data['photo']['id'] . '-5.' . $fileext),
|
||||||
|
dbesc(App::get_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(App::get_baseurl() . '/photo/' . $data['photo']['id'] . '-4.' . $filetype),
|
||||||
|
dbesc(App::get_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 = App::get_baseurl() . '/profile/' . get_app()->user['nickname'];
|
||||||
|
if ($url && strlen(get_config('system', 'directory'))) {
|
||||||
|
proc_run(PRIORITY_LOW, "include/directory.php", $url);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once 'include/profile_update.php';
|
||||||
|
profile_change();
|
||||||
|
|
||||||
|
// 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 <x><y><z> 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=' . App::get_baseurl() . '/photos/' . $owner_record[0]['name'] . '/image/' . $hash . ']'
|
||||||
|
. '[img]' . App::get_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`, `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,
|
$data_sql,
|
||||||
intval(local_user()),
|
intval(local_user()),
|
||||||
dbesc($_REQUEST['photo_id']),
|
dbesc($photo_id),
|
||||||
$scale_sql
|
$scale_sql
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -3352,6 +3995,7 @@ $called_api = null;
|
||||||
'image/gif' => 'gif'
|
'image/gif' => 'gif'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// prepare output data for photo
|
||||||
if (dbm::is_result($r)) {
|
if (dbm::is_result($r)) {
|
||||||
$data = array('photo' => $r[0]);
|
$data = array('photo' => $r[0]);
|
||||||
$data['photo']['id'] = $data['photo']['resource-id'];
|
$data['photo']['id'] = $data['photo']['resource-id'];
|
||||||
|
@ -3364,13 +4008,16 @@ $called_api = null;
|
||||||
$data['photo']['links'] = array();
|
$data['photo']['links'] = array();
|
||||||
for ($k = intval($data['photo']['minscale']); $k <= intval($data['photo']['maxscale']); $k++) {
|
for ($k = intval($data['photo']['minscale']); $k <= intval($data['photo']['maxscale']); $k++) {
|
||||||
$data['photo']['links'][$k . ":link"]["@attributes"] = array("type" => $data['photo']['type'],
|
$data['photo']['links'][$k . ":link"]["@attributes"] = array("type" => $data['photo']['type'],
|
||||||
"scale" => $k,
|
"scale" => $k,
|
||||||
"href" => App::get_baseurl() . "/photo/" . $data['photo']['resource-id'] . "-" . $k . "." . $typetoext[$data['photo']['type']]);
|
"href" => App::get_baseurl() . "/photo/" . $data['photo']['resource-id'] . "-" . $k . "." . $typetoext[$data['photo']['type']]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$data['photo']['link'] = array();
|
$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++) {
|
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] = App::get_baseurl() . "/photo/" . $data['photo']['resource-id'] . "-" . $k . "." . $typetoext[$data['photo']['type']];
|
||||||
|
$i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unset($data['photo']['resource-id']);
|
unset($data['photo']['resource-id']);
|
||||||
|
@ -3381,13 +4028,54 @@ $called_api = null;
|
||||||
throw new NotFoundException();
|
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);
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
api_register_func('api/friendica/photos/list', 'api_fr_photos_list', true);
|
|
||||||
api_register_func('api/friendica/photo', 'api_fr_photo_detail', true);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* similar as /mod/redir.php
|
* similar as /mod/redir.php
|
||||||
|
@ -4310,7 +4998,6 @@ friendships/exists
|
||||||
friendships/show
|
friendships/show
|
||||||
account/update_location
|
account/update_location
|
||||||
account/update_profile_background_image
|
account/update_profile_background_image
|
||||||
account/update_profile_image
|
|
||||||
blocks/create
|
blocks/create
|
||||||
blocks/destroy
|
blocks/destroy
|
||||||
friendica/profile/update
|
friendica/profile/update
|
||||||
|
|
Loading…
Reference in New Issue
Block a user