X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2FPhoto.php;h=8ba01e33655d280ede203d5f774e3c6b51465a42;hb=7d21f6f8d383d4aa2d9def9023b56c44f5ebd38c;hp=46360380438a89d2a039b4bc359f0927ea6cd18c;hpb=3972fe62fe8afb3791e9d6526e7665501a577b81;p=friendica.git diff --git a/src/Model/Photo.php b/src/Model/Photo.php index 4636038043..8ba01e3365 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -1,6 +1,6 @@ strlen($Image->asString()), "data" => $data, "scale" => $scale, - "profile" => $profile, + "photo-type" => $type, + "profile" => false, "allow_cid" => $allow_cid, "allow_gid" => $allow_gid, "deny_cid" => $deny_cid, @@ -478,7 +485,7 @@ class Photo $micro = ""; $photo = DBA::selectFirst( - "photo", ["resource-id"], ["uid" => $uid, "contact-id" => $cid, "scale" => 4, "album" => self::CONTACT_PHOTOS] + "photo", ["resource-id"], ["uid" => $uid, "contact-id" => $cid, "scale" => 4, "photo-type" => self::CONTACT_AVATAR] ); if (!empty($photo['resource-id'])) { $resource_id = $photo["resource-id"]; @@ -531,7 +538,7 @@ class Photo Logger::info('Avatar is resized', ['uid' => $uid, 'cid' => $cid, 'size' => $filesize, 'type' => $Image->getType()]); } - $r = self::store($Image, $uid, $cid, $resource_id, $filename, self::CONTACT_PHOTOS, 4); + $r = self::store($Image, $uid, $cid, $resource_id, $filename, self::CONTACT_PHOTOS, 4, self::CONTACT_AVATAR); if ($r === false) { $photo_failure = true; @@ -539,7 +546,7 @@ class Photo $Image->scaleDown(80); - $r = self::store($Image, $uid, $cid, $resource_id, $filename, self::CONTACT_PHOTOS, 5); + $r = self::store($Image, $uid, $cid, $resource_id, $filename, self::CONTACT_PHOTOS, 5, self::CONTACT_AVATAR); if ($r === false) { $photo_failure = true; @@ -547,7 +554,7 @@ class Photo $Image->scaleDown(48); - $r = self::store($Image, $uid, $cid, $resource_id, $filename, self::CONTACT_PHOTOS, 6); + $r = self::store($Image, $uid, $cid, $resource_id, $filename, self::CONTACT_PHOTOS, 6, self::CONTACT_AVATAR); if ($r === false) { $photo_failure = true; @@ -558,25 +565,6 @@ class Photo $image_url = DI::baseUrl() . "/photo/" . $resource_id . "-4." . $Image->getExt() . $suffix; $thumb = DI::baseUrl() . "/photo/" . $resource_id . "-5." . $Image->getExt() . $suffix; $micro = DI::baseUrl() . "/photo/" . $resource_id . "-6." . $Image->getExt() . $suffix; - - // Remove the cached photo - $a = DI::app(); - $basepath = $a->getBasePath(); - - if (is_dir($basepath . "/photo")) { - $filename = $basepath . "/photo/" . $resource_id . "-4." . $Image->getExt(); - if (file_exists($filename)) { - unlink($filename); - } - $filename = $basepath . "/photo/" . $resource_id . "-5." . $Image->getExt(); - if (file_exists($filename)) { - unlink($filename); - } - $filename = $basepath . "/photo/" . $resource_id . "-6." . $Image->getExt(); - if (file_exists($filename)) { - unlink($filename); - } - } } else { $photo_failure = true; } @@ -645,6 +633,9 @@ class Photo { $sql_extra = Security::getPermissionsSQLByUserId($uid); + $avatar_type = (local_user() && (local_user() == $uid)) ? self::USER_AVATAR : self::DEFAULT; + $banner_type = (local_user() && (local_user() == $uid)) ? self::USER_BANNER : self::DEFAULT; + $key = "photo_albums:".$uid.":".local_user().":".remote_user(); $albums = DI::cache()->get($key); if (is_null($albums) || $update) { @@ -653,20 +644,22 @@ class Photo // At this time we just store the data in the cache $albums = DBA::toArray(DBA::p("SELECT COUNT(DISTINCT `resource-id`) AS `total`, `album`, ANY_VALUE(`created`) AS `created` FROM `photo` - WHERE `uid` = ? AND `album` != ? AND `album` != ? $sql_extra + WHERE `uid` = ? AND `photo-type` IN (?, ?, ?) $sql_extra GROUP BY `album` ORDER BY `created` DESC", $uid, - self::CONTACT_PHOTOS, - DI::l10n()->t(self::CONTACT_PHOTOS) + self::DEFAULT, + $banner_type, + $avatar_type )); } else { // This query doesn't do the count and is much faster $albums = DBA::toArray(DBA::p("SELECT DISTINCT(`album`), '' AS `total` FROM `photo` USE INDEX (`uid_album_scale_created`) - WHERE `uid` = ? AND `album` != ? AND `album` != ? $sql_extra", + WHERE `uid` = ? AND `photo-type` IN (?, ?, ?) $sql_extra", $uid, - self::CONTACT_PHOTOS, - DI::l10n()->t(self::CONTACT_PHOTOS) + self::DEFAULT, + $banner_type, + $avatar_type )); } DI::cache()->set($key, $albums, Duration::DAY); @@ -753,7 +746,7 @@ class Photo 'allow_cid' => $srch, 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '', 'resource-id' => $image_rid, 'uid' => $uid ]; - if (!Photo::exists($condition)) { + if (!self::exists($condition)) { $photo = self::selectFirst(['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'uid'], ['resource-id' => $image_rid]); if (!DBA::isResult($photo)) { Logger::info('Image not found', ['resource-id' => $image_rid]); @@ -779,7 +772,7 @@ class Photo /** * Add permissions to photo ressource * @todo mix with previous photo permissions - * + * * @param string $image_rid * @param integer $uid * @param string $str_contact_allow @@ -796,7 +789,7 @@ class Photo $condition = ['resource-id' => $image_rid, 'uid' => $uid]; Logger::info('Set permissions', ['condition' => $condition, 'permissions' => $fields]); - Photo::update($fields, $condition); + self::update($fields, $condition); } /** @@ -881,22 +874,73 @@ class Photo return DBA::exists('photo', ['resource-id' => $guid]); } - /** - * - * @param int $uid User ID - * @param array $files uploaded file array - * @return array photo record - */ - public static function upload(int $uid, array $files) + private static function fitImageSize($Image) { - Logger::info('starting new upload'); + $max_length = DI::config()->get('system', 'max_image_length'); + if ($max_length > 0) { + $Image->scaleDown($max_length); + Logger::info('File upload: Scaling picture to new size', ['max-length' => $max_length]); + } - $user = User::getOwnerDataById($uid); - if (empty($user)) { - Logger::notice('User not found', ['uid' => $uid]); + $filesize = strlen($Image->asString()); + $width = $Image->getWidth(); + $height = $Image->getHeight(); + + $maximagesize = DI::config()->get('system', 'maximagesize'); + + if (!empty($maximagesize) && ($filesize > $maximagesize)) { + // Scale down to multiples of 640 until the maximum size isn't exceeded anymore + foreach ([5120, 2560, 1280, 640] as $pixels) { + if (($filesize > $maximagesize) && (max($width, $height) > $pixels)) { + Logger::info('Resize', ['size' => $filesize, 'width' => $width, 'height' => $height, 'max' => $maximagesize, 'pixels' => $pixels]); + $Image->scaleDown($pixels); + $filesize = strlen($Image->asString()); + $width = $Image->getWidth(); + $height = $Image->getHeight(); + } + } + if ($filesize > $maximagesize) { + Logger::notice('Image size is too big', ['size' => $filesize, 'max' => $maximagesize]); + return null; + } + } + + return $Image; + } + + private static function loadImageFromURL(string $image_url) + { + $filename = basename($image_url); + if (!empty($image_url)) { + $ret = DI::httpClient()->get($image_url); + $img_str = $ret->getBody(); + $type = $ret->getContentType(); + } else { + $img_str = ''; + $type = ''; + } + + if (empty($img_str)) { + Logger::notice('Empty content'); + return []; + } + + $type = Images::getMimeTypeByData($img_str, $image_url, $type); + + $Image = new Image($img_str, $type); + + $Image = self::fitImageSize($Image); + if (empty($Image)) { return []; } + return ['image' => $Image, 'filename' => $filename]; + } + + private static function uploadImage(array $files) + { + Logger::info('starting new upload'); + if (empty($files)) { Logger::notice('Empty upload file'); return []; @@ -943,7 +987,7 @@ class Photo } if (empty($src)) { - Logger::notice('No source file name', ['uid' => $uid, 'files' => $files]); + Logger::notice('No source file name', ['files' => $files]); return []; } @@ -954,53 +998,64 @@ class Photo $imagedata = @file_get_contents($src); $Image = new Image($imagedata, $filetype); if (!$Image->isValid()) { - Logger::notice('Image is unvalid', ['uid' => $uid, 'files' => $files]); + Logger::notice('Image is unvalid', ['files' => $files]); return []; } $Image->orient($src); @unlink($src); - $max_length = DI::config()->get('system', 'max_image_length'); - if (!$max_length) { - $max_length = MAX_IMAGE_LENGTH; - } - if ($max_length > 0) { - $Image->scaleDown($max_length); - $filesize = strlen($Image->asString()); - Logger::info('File upload: Scaling picture to new size', ['max-length' => $max_length]); + $Image = self::fitImageSize($Image); + if (empty($Image)) { + return []; } - $width = $Image->getWidth(); - $height = $Image->getHeight(); + return ['image' => $Image, 'filename' => $filename]; + } - $maximagesize = DI::config()->get('system', 'maximagesize'); + /** + * @param int $uid User ID + * @param array $files uploaded file array + * @param string $album + * @param string|null $allow_cid + * @param string|null $allow_gid + * @param string $deny_cid + * @param string $deny_gid + * @param string $desc + * @param string $resource_id + * @return array photo record + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + public static function upload(int $uid, array $files, string $album = '', string $allow_cid = null, string $allow_gid = null, string $deny_cid = '', string $deny_gid = '', string $desc = '', string $resource_id = ''): array + { + $user = User::getOwnerDataById($uid); + if (empty($user)) { + Logger::notice('User not found', ['uid' => $uid]); + return []; + } - if (!empty($maximagesize) && ($filesize > $maximagesize)) { - // Scale down to multiples of 640 until the maximum size isn't exceeded anymore - foreach ([5120, 2560, 1280, 640] as $pixels) { - if (($filesize > $maximagesize) && (max($width, $height) > $pixels)) { - Logger::info('Resize', ['size' => $filesize, 'width' => $width, 'height' => $height, 'max' => $maximagesize, 'pixels' => $pixels]); - $Image->scaleDown($pixels); - $filesize = strlen($Image->asString()); - $width = $Image->getWidth(); - $height = $Image->getHeight(); - } - } - if ($filesize > $maximagesize) { - @unlink($src); - Logger::notice('Image size is too big', ['size' => $filesize, 'max' => $maximagesize]); - return []; - } + $data = self::uploadImage($files); + if (empty($data)) { + Logger::info('upload failed'); + return []; } - $resource_id = Photo::newResource(); - $album = DI::l10n()->t('Wall Photos'); - $defperm = '<' . $user['id'] . '>'; + $Image = $data['image']; + $filename = $data['filename']; + $width = $Image->getWidth(); + $height = $Image->getHeight(); + + $resource_id = $resource_id ?: self::newResource(); + $album = $album ?: DI::l10n()->t('Wall Photos'); + + if (is_null($allow_cid) && is_null($allow_gid)) { + $allow_cid = '<' . $user['id'] . '>'; + $allow_gid = ''; + } $smallest = 0; - $r = Photo::store($Image, $user['uid'], 0, $resource_id, $filename, $album, 0, 0, $defperm); + $r = self::store($Image, $user['uid'], 0, $resource_id, $filename, $album, 0, self::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); if (!$r) { Logger::notice('Photo could not be stored'); return []; @@ -1008,7 +1063,7 @@ class Photo if ($width > 640 || $height > 640) { $Image->scaleDown(640); - $r = Photo::store($Image, $user['uid'], 0, $resource_id, $filename, $album, 1, 0, $defperm); + $r = self::store($Image, $user['uid'], 0, $resource_id, $filename, $album, 1, self::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); if ($r) { $smallest = 1; } @@ -1016,7 +1071,7 @@ class Photo if ($width > 320 || $height > 320) { $Image->scaleDown(320); - $r = Photo::store($Image, $user['uid'], 0, $resource_id, $filename, $album, 2, 0, $defperm); + $r = self::store($Image, $user['uid'], 0, $resource_id, $filename, $album, 2, self::DEFAULT, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc); if ($r && ($smallest == 0)) { $smallest = 2; } @@ -1031,16 +1086,152 @@ class Photo $picture = []; - $picture['id'] = $photo['id']; - $picture['size'] = $photo['datasize']; - $picture['width'] = $photo['width']; - $picture['height'] = $photo['height']; - $picture['type'] = $photo['type']; - $picture['albumpage'] = DI::baseUrl() . '/photos/' . $user['nickname'] . '/image/' . $resource_id; - $picture['picture'] = DI::baseUrl() . '/photo/{$resource_id}-0.' . $Image->getExt(); - $picture['preview'] = DI::baseUrl() . '/photo/{$resource_id}-{$smallest}.' . $Image->getExt(); + $picture['id'] = $photo['id']; + $picture['resource_id'] = $resource_id; + $picture['size'] = $photo['datasize']; + $picture['width'] = $photo['width']; + $picture['height'] = $photo['height']; + $picture['type'] = $photo['type']; + $picture['albumpage'] = DI::baseUrl() . '/photos/' . $user['nickname'] . '/image/' . $resource_id; + $picture['picture'] = DI::baseUrl() . '/photo/{$resource_id}-0.' . $Image->getExt(); + $picture['preview'] = DI::baseUrl() . '/photo/{$resource_id}-{$smallest}.' . $Image->getExt(); Logger::info('upload done', ['picture' => $picture]); return $picture; } + + /** + * Upload a user avatar + * + * @param int $uid User ID + * @param array $files uploaded file array + * @param string $url External image url + * @return string avatar resource + */ + public static function uploadAvatar(int $uid, array $files, string $url = ''): string + { + if (!empty($files)) { + $data = self::uploadImage($files); + if (empty($data)) { + Logger::info('upload failed'); + return ''; + } + } elseif (!empty($url)) { + $data = self::loadImageFromURL($url); + if (empty($data)) { + Logger::info('loading from external url failed'); + return ''; + } + } else { + Logger::info('Neither files nor url provided'); + return ''; + } + + $Image = $data['image']; + $filename = $data['filename']; + $width = $Image->getWidth(); + $height = $Image->getHeight(); + + $resource_id = self::newResource(); + $album = DI::l10n()->t(self::PROFILE_PHOTOS); + + // upload profile image (scales 4, 5, 6) + logger::info('starting new profile image upload'); + + if ($width > 300 || $height > 300) { + $Image->scaleDown(300); + } + + $r = self::store($Image, $uid, 0, $resource_id, $filename, $album, 4, self::USER_AVATAR); + if (!$r) { + logger::notice('profile image upload with scale 4 (300) failed'); + } + + if ($width > 80 || $height > 80) { + $Image->scaleDown(80); + } + + $r = self::store($Image, $uid, 0, $resource_id, $filename, $album, 5, self::USER_AVATAR); + if (!$r) { + logger::notice('profile image upload with scale 5 (80) failed'); + } + + if ($width > 48 || $height > 48) { + $Image->scaleDown(48); + } + + $r = self::store($Image, $uid, 0, $resource_id, $filename, $album, 6, self::USER_AVATAR); + if (!$r) { + logger::notice('profile image upload with scale 6 (48) failed'); + } + + logger::info('new profile image upload ended'); + + $condition = ["`profile` AND `resource-id` != ? AND `uid` = ?", $resource_id, $uid]; + self::update(['profile' => false, 'photo-type' => self::DEFAULT], $condition); + + Contact::updateSelfFromUserID($uid, true); + + // Update global directory in background + Profile::publishUpdate($uid); + + return $resource_id; + } + + /** + * Upload a user banner + * + * @param int $uid User ID + * @param array $files uploaded file array + * @param string $url External image url + * @return string avatar resource + */ + public static function uploadBanner(int $uid, array $files = [], string $url = ''): string + { + if (!empty($files)) { + $data = self::uploadImage($files); + if (empty($data)) { + Logger::info('upload failed'); + return ''; + } + } elseif (!empty($url)) { + $data = self::loadImageFromURL($url); + if (empty($data)) { + Logger::info('loading from external url failed'); + return ''; + } + } else { + Logger::info('Neither files nor url provided'); + return ''; + } + + $Image = $data['image']; + $filename = $data['filename']; + $width = $Image->getWidth(); + $height = $Image->getHeight(); + + $resource_id = self::newResource(); + $album = DI::l10n()->t(self::BANNER_PHOTOS); + + if ($width > 960) { + $Image->scaleDown(960); + } + + $r = self::store($Image, $uid, 0, $resource_id, $filename, $album, 3, self::USER_BANNER); + if (!$r) { + logger::notice('profile banner upload with scale 3 (960) failed'); + } + + logger::info('new profile banner upload ended'); + + $condition = ["`photo-type` = ? AND `resource-id` != ? AND `uid` = ?", self::USER_BANNER, $resource_id, $uid]; + self::update(['photo-type' => self::DEFAULT], $condition); + + Contact::updateSelfFromUserID($uid, true); + + // Update global directory in background + Profile::publishUpdate($uid); + + return $resource_id; + } }