Merge pull request #10425 from annando/api-avatar
API: Improved avatar handling
This commit is contained in:
commit
d798d0bcd4
7 changed files with 188 additions and 37 deletions
|
@ -126,6 +126,9 @@ class StorageManager
|
|||
case Storage\SystemResource::getName():
|
||||
$this->backendInstances[$name] = new Storage\SystemResource();
|
||||
break;
|
||||
case Storage\ExternalResource::getName():
|
||||
$this->backendInstances[$name] = new Storage\ExternalResource();
|
||||
break;
|
||||
default:
|
||||
$data = [
|
||||
'name' => $name,
|
||||
|
@ -158,7 +161,7 @@ class StorageManager
|
|||
public function isValidBackend(string $name = null, bool $onlyUserBackend = false)
|
||||
{
|
||||
return array_key_exists($name, $this->backends) ||
|
||||
(!$onlyUserBackend && $name === Storage\SystemResource::getName());
|
||||
(!$onlyUserBackend && in_array($name, [Storage\SystemResource::getName(), Storage\ExternalResource::getName()]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1614,7 +1614,7 @@ class Contact
|
|||
*
|
||||
* @param array $contact contact array
|
||||
* @param string $size Size of the avatar picture
|
||||
* @return void
|
||||
* @return string avatar URL
|
||||
*/
|
||||
public static function getDefaultAvatar(array $contact, string $size)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@ use Friendica\Core\System;
|
|||
use Friendica\Database\DBA;
|
||||
use Friendica\Database\DBStructure;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Storage\ExternalResource;
|
||||
use Friendica\Model\Storage\SystemResource;
|
||||
use Friendica\Object\Image;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
@ -263,6 +264,28 @@ class Photo
|
|||
return $photo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a photo array for an external resource image
|
||||
*
|
||||
* @param string $url Image URL
|
||||
* @param string $mimetype Image mime type. Defaults to "image/jpeg"
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function createPhotoForExternalResource($url, $mimetype = "image/jpeg")
|
||||
{
|
||||
$fields = self::getFields();
|
||||
$values = array_fill(0, count($fields), "");
|
||||
|
||||
$photo = array_combine($fields, $values);
|
||||
$photo['backend-class'] = ExternalResource::NAME;
|
||||
$photo['backend-ref'] = $url;
|
||||
$photo['type'] = $mimetype;
|
||||
$photo['cacheable'] = false;
|
||||
|
||||
return $photo;
|
||||
}
|
||||
|
||||
/**
|
||||
* store photo metadata in db and binary in default backend
|
||||
|
|
99
src/Model/Storage/ExternalResource.php
Normal file
99
src/Model/Storage/ExternalResource.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Model\Storage;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Friendica\DI;
|
||||
|
||||
/**
|
||||
* External resource storage class
|
||||
*
|
||||
* This class is used to load external resources, like images.
|
||||
* Is not intended to be selectable by admins as default storage class.
|
||||
*/
|
||||
class ExternalResource implements IStorage
|
||||
{
|
||||
const NAME = 'ExternalResource';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function get(string $filename)
|
||||
{
|
||||
$parts = parse_url($filename);
|
||||
if (empty($parts['scheme']) || empty($parts['host'])) {
|
||||
return "";
|
||||
}
|
||||
|
||||
$curlResult = DI::httpRequest()->get($filename);
|
||||
if ($curlResult->isSuccess()) {
|
||||
return $curlResult->getBody();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function put(string $data, string $filename = '')
|
||||
{
|
||||
throw new BadMethodCallException();
|
||||
}
|
||||
|
||||
public function delete(string $filename)
|
||||
{
|
||||
throw new BadMethodCallException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function saveOptions(array $data)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function getName()
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
}
|
|
@ -44,11 +44,6 @@ class Photo extends BaseModule
|
|||
public static function rawContent(array $parameters = [])
|
||||
{
|
||||
$totalstamp = microtime(true);
|
||||
$a = DI::app();
|
||||
// @TODO: Replace with parameter from router
|
||||
if ($a->argc <= 1 || $a->argc > 4) {
|
||||
throw new \Friendica\Network\HTTPException\BadRequestException();
|
||||
}
|
||||
|
||||
if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) {
|
||||
header("HTTP/1.1 304 Not Modified");
|
||||
|
@ -69,30 +64,27 @@ class Photo extends BaseModule
|
|||
$customsize = 0;
|
||||
$photo = false;
|
||||
$scale = null;
|
||||
// @TODO: Replace with parameter from router
|
||||
$stamp = microtime(true);
|
||||
switch($a->argc) {
|
||||
case 4:
|
||||
$customsize = intval($a->argv[2]);
|
||||
$uid = MPhoto::stripExtension($a->argv[3]);
|
||||
$photo = self::getAvatar($uid, $a->argv[1]);
|
||||
break;
|
||||
case 3:
|
||||
$uid = MPhoto::stripExtension($a->argv[2]);
|
||||
$photo = self::getAvatar($uid, $a->argv[1]);
|
||||
break;
|
||||
case 2:
|
||||
$photoid = MPhoto::stripExtension($a->argv[1]);
|
||||
$scale = 0;
|
||||
if (substr($photoid, -2, 1) == "-") {
|
||||
$scale = intval(substr($photoid, -1, 1));
|
||||
$photoid = substr($photoid, 0, -2);
|
||||
}
|
||||
$photo = MPhoto::getPhoto($photoid, $scale);
|
||||
if ($photo === false) {
|
||||
throw new \Friendica\Network\HTTPException\NotFoundException(DI::l10n()->t('The Photo with id %s is not available.', $photoid));
|
||||
}
|
||||
break;
|
||||
if (!empty($parameters['customsize'])) {
|
||||
$customsize = intval($parameters['customsize']);
|
||||
$uid = MPhoto::stripExtension($parameters['name']);
|
||||
$photo = self::getAvatar($uid, $parameters['type']);
|
||||
} elseif (!empty($parameters['type'])) {
|
||||
$uid = MPhoto::stripExtension($parameters['name']);
|
||||
$photo = self::getAvatar($uid, $parameters['type']);
|
||||
} elseif (!empty($parameters['name'])) {
|
||||
$photoid = MPhoto::stripExtension($parameters['name']);
|
||||
$scale = 0;
|
||||
if (substr($photoid, -2, 1) == "-") {
|
||||
$scale = intval(substr($photoid, -1, 1));
|
||||
$photoid = substr($photoid, 0, -2);
|
||||
}
|
||||
$photo = MPhoto::getPhoto($photoid, $scale);
|
||||
if ($photo === false) {
|
||||
throw new \Friendica\Network\HTTPException\NotFoundException(DI::l10n()->t('The Photo with id %s is not available.', $photoid));
|
||||
}
|
||||
} else {
|
||||
throw new \Friendica\Network\HTTPException\BadRequestException();
|
||||
}
|
||||
$fetch = microtime(true) - $stamp;
|
||||
|
||||
|
@ -160,6 +152,36 @@ class Photo extends BaseModule
|
|||
private static function getAvatar($uid, $type="avatar")
|
||||
{
|
||||
switch($type) {
|
||||
case "contact":
|
||||
$contact = Contact::getById($uid, ['uid', 'url', 'avatar', 'photo']);
|
||||
if (empty($contact)) {
|
||||
return false;
|
||||
}
|
||||
If (($contact['uid'] != 0) && empty($contact['photo']) && empty($contact['avatar'])) {
|
||||
$contact = Contact::getByURL($contact['url'], false, ['avatar', 'photo']);
|
||||
}
|
||||
if (!empty($contact['photo'])) {
|
||||
$url = $contact['photo'];
|
||||
} elseif (!empty($contact['avatar'])) {
|
||||
$url = $contact['avatar'];
|
||||
} else {
|
||||
$url = DI::baseUrl() . Contact::DEFAULT_AVATAR_PHOTO;
|
||||
}
|
||||
return MPhoto::createPhotoForExternalResource($url);
|
||||
case "header":
|
||||
$contact = Contact::getById($uid, ['uid', 'url', 'header']);
|
||||
if (empty($contact)) {
|
||||
return false;
|
||||
}
|
||||
If (($contact['uid'] != 0) && empty($contact['header'])) {
|
||||
$contact = Contact::getByURL($contact['url'], false, ['header']);
|
||||
}
|
||||
if (!empty($contact['header'])) {
|
||||
$url = $contact['header'];
|
||||
} else {
|
||||
$url = DI::baseUrl() . '/images/blank.png';
|
||||
}
|
||||
return MPhoto::createPhotoForExternalResource($url);
|
||||
case "profile":
|
||||
case "custom":
|
||||
$scale = 4;
|
||||
|
@ -189,7 +211,12 @@ class Photo extends BaseModule
|
|||
$default = Contact::getDefaultAvatar($contact, Proxy::SIZE_THUMB);
|
||||
}
|
||||
|
||||
$photo = MPhoto::createPhotoForSystemResource($default);
|
||||
$parts = parse_url($default);
|
||||
if (!empty($parts['scheme']) || !empty($parts['host'])) {
|
||||
$photo = MPhoto::createPhotoForExternalResource($default);
|
||||
} else {
|
||||
$photo = MPhoto::createPhotoForSystemResource($default);
|
||||
}
|
||||
}
|
||||
return $photo;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ use Friendica\Database\DBA;
|
|||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Proxy;
|
||||
|
||||
/**
|
||||
* Class Account
|
||||
|
@ -114,9 +113,9 @@ class Account extends BaseDataTransferObject
|
|||
|
||||
$this->note = BBCode::convert($publicContact['about'], false);
|
||||
$this->url = $publicContact['url'];
|
||||
$this->avatar = ($userContact['photo'] ?? $publicContact['photo']) ?: Proxy::proxifyUrl($userContact['avatar'] ?? $publicContact['avatar']);
|
||||
$this->avatar = (($userContact['photo'] ?? '') ?: $publicContact['photo']) ?: DI::baseUrl() . '/photo/contact/'. (($userContact['id'] ?? 0) ?: $publicContact['id']);
|
||||
$this->avatar_static = $this->avatar;
|
||||
$this->header = Proxy::proxifyUrl($userContact['header'] ?? $publicContact['header'] ?? '') ?: DI::baseUrl() . '/images/blank.png';
|
||||
$this->header = DI::baseUrl() . '/photo/header/'. (($userContact['id'] ?? 0) ?: $publicContact['id']);
|
||||
$this->header_static = $this->header;
|
||||
$this->followers_count = $apcontact['followers_count'] ?? 0;
|
||||
$this->following_count = $apcontact['following_count'] ?? 0;
|
||||
|
|
|
@ -363,9 +363,9 @@ return [
|
|||
'/permission/tooltip/{type}/{id:\d+}' => [Module\PermissionTooltip::class, [R::GET]],
|
||||
|
||||
'/photo' => [
|
||||
'/{name}' => [Module\Photo::class, [R::GET]],
|
||||
'/{type}/{name}' => [Module\Photo::class, [R::GET]],
|
||||
'/{type}/{customize}/{name}' => [Module\Photo::class, [R::GET]],
|
||||
'/{name}' => [Module\Photo::class, [R::GET]],
|
||||
'/{type}/{name}' => [Module\Photo::class, [R::GET]],
|
||||
'/{type}/{customsize}/{name}' => [Module\Photo::class, [R::GET]],
|
||||
],
|
||||
|
||||
'/pretheme' => [Module\ThemeDetails::class, [R::GET]],
|
||||
|
|
Loading…
Reference in a new issue