mirror of
https://github.com/friendica/friendica
synced 2025-04-14 15:19:04 +00:00
231 lines
7.7 KiB
PHP
231 lines
7.7 KiB
PHP
<?php
|
|
/**
|
|
* @copyright Copyright (C) 2010-2022, 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\Module\Settings\Profile\Photo;
|
|
|
|
use Friendica\Core\Renderer;
|
|
use Friendica\Database\DBA;
|
|
use Friendica\DI;
|
|
use Friendica\Model\Contact;
|
|
use Friendica\Model\Photo;
|
|
use Friendica\Model\Profile;
|
|
use Friendica\Module\BaseSettings;
|
|
use Friendica\Network\HTTPException;
|
|
|
|
class Crop extends BaseSettings
|
|
{
|
|
protected function post(array $request = [])
|
|
{
|
|
if (!DI::userSession()->isAuthenticated()) {
|
|
return;
|
|
}
|
|
|
|
$photo_prefix = $this->parameters['guid'];
|
|
$resource_id = $photo_prefix;
|
|
$scale = 0;
|
|
if (substr($photo_prefix, -2, 1) == '-') {
|
|
list($resource_id, $scale) = explode('-', $photo_prefix);
|
|
}
|
|
|
|
self::checkFormSecurityTokenRedirectOnError('settings/profile/photo/crop/' . $photo_prefix, 'settings_profile_photo_crop');
|
|
|
|
$action = $_POST['action'] ?? 'crop';
|
|
|
|
// Image selection origin is top left
|
|
$selectionX = intval($_POST['xstart'] ?? 0);
|
|
$selectionY = intval($_POST['ystart'] ?? 0);
|
|
$selectionW = intval($_POST['width'] ?? 0);
|
|
$selectionH = intval($_POST['height'] ?? 0);
|
|
|
|
$path = 'profile/' . DI::app()->getLoggedInUserNickname();
|
|
|
|
$base_image = Photo::selectFirst([], ['resource-id' => $resource_id, 'uid' => DI::userSession()->getLocalUserId(), 'scale' => $scale]);
|
|
if (DBA::isResult($base_image)) {
|
|
$Image = Photo::getImageForPhoto($base_image);
|
|
if (empty($Image)) {
|
|
throw new HTTPException\InternalServerErrorException();
|
|
}
|
|
|
|
if ($Image->isValid()) {
|
|
// If setting for the default profile, unset the profile photo flag from any other photos I own
|
|
DBA::update('photo', ['profile' => 0], ['uid' => DI::userSession()->getLocalUserId()]);
|
|
|
|
// Normalizing expected square crop parameters
|
|
$selectionW = $selectionH = min($selectionW, $selectionH);
|
|
|
|
$imageIsSquare = $Image->getWidth() === $Image->getHeight();
|
|
$selectionIsFullImage = $selectionX === 0 && $selectionY === 0 && $selectionW === $Image->getWidth() && $selectionH === $Image->getHeight();
|
|
|
|
// Bypassed UI with a rectangle image, we force a square cropped image
|
|
if (!$imageIsSquare && $action == 'skip') {
|
|
$selectionX = $selectionY = 0;
|
|
$selectionW = $selectionH = min($Image->getWidth(), $Image->getHeight());
|
|
$action = 'crop';
|
|
}
|
|
|
|
// Selective crop if it was asked and the selection isn't the full image
|
|
if ($action == 'crop'
|
|
&& !($imageIsSquare && !$selectionIsFullImage)
|
|
) {
|
|
$Image->crop(300, $selectionX, $selectionY, $selectionW, $selectionH);
|
|
$resource_id = Photo::newResource();
|
|
} else {
|
|
$Image->scaleDown(300);
|
|
}
|
|
|
|
$condition = ['resource-id' => $resource_id, 'uid' => DI::userSession()->getLocalUserId(), 'contact-id' => 0];
|
|
|
|
$r = Photo::store(
|
|
$Image,
|
|
DI::userSession()->getLocalUserId(),
|
|
0,
|
|
$resource_id,
|
|
$base_image['filename'],
|
|
DI::l10n()->t(Photo::PROFILE_PHOTOS),
|
|
4,
|
|
Photo::USER_AVATAR
|
|
);
|
|
if ($r === false) {
|
|
DI::sysmsg()->addNotice(DI::l10n()->t('Image size reduction [%s] failed.', '300'));
|
|
} else {
|
|
Photo::update(['profile' => true], array_merge($condition, ['scale' => 4]));
|
|
}
|
|
|
|
$Image->scaleDown(80);
|
|
|
|
$r = Photo::store(
|
|
$Image,
|
|
DI::userSession()->getLocalUserId(),
|
|
0,
|
|
$resource_id,
|
|
$base_image['filename'],
|
|
DI::l10n()->t(Photo::PROFILE_PHOTOS),
|
|
5,
|
|
Photo::USER_AVATAR
|
|
);
|
|
if ($r === false) {
|
|
DI::sysmsg()->addNotice(DI::l10n()->t('Image size reduction [%s] failed.', '80'));
|
|
} else {
|
|
Photo::update(['profile' => true], array_merge($condition, ['scale' => 5]));
|
|
}
|
|
|
|
$Image->scaleDown(48);
|
|
|
|
$r = Photo::store(
|
|
$Image,
|
|
DI::userSession()->getLocalUserId(),
|
|
0,
|
|
$resource_id,
|
|
$base_image['filename'],
|
|
DI::l10n()->t(Photo::PROFILE_PHOTOS),
|
|
6,
|
|
Photo::USER_AVATAR
|
|
);
|
|
if ($r === false) {
|
|
DI::sysmsg()->addNotice(DI::l10n()->t('Image size reduction [%s] failed.', '48'));
|
|
} else {
|
|
Photo::update(['profile' => true], array_merge($condition, ['scale' => 6]));
|
|
}
|
|
|
|
Contact::updateSelfFromUserID(DI::userSession()->getLocalUserId(), true);
|
|
|
|
DI::sysmsg()->addInfo(DI::l10n()->t('Shift-reload the page or clear browser cache if the new photo does not display immediately.'));
|
|
|
|
// Update global directory in background
|
|
Profile::publishUpdate(DI::userSession()->getLocalUserId());
|
|
} else {
|
|
DI::sysmsg()->addNotice(DI::l10n()->t('Unable to process image'));
|
|
}
|
|
}
|
|
|
|
DI::baseUrl()->redirect($path);
|
|
}
|
|
|
|
protected function content(array $request = []): string
|
|
{
|
|
if (!DI::userSession()->isAuthenticated()) {
|
|
throw new HTTPException\ForbiddenException(DI::l10n()->t('Permission denied.'));
|
|
}
|
|
|
|
parent::content();
|
|
|
|
$resource_id = $this->parameters['guid'];
|
|
|
|
$photos = Photo::selectToArray([], ['resource-id' => $resource_id, 'uid' => DI::userSession()->getLocalUserId()], ['order' => ['scale' => false]]);
|
|
if (!DBA::isResult($photos)) {
|
|
throw new HTTPException\NotFoundException(DI::l10n()->t('Photo not found.'));
|
|
}
|
|
|
|
$havescale = false;
|
|
$smallest = 0;
|
|
foreach ($photos as $photo) {
|
|
$smallest = $photo['scale'] == 1 ? 1 : $smallest;
|
|
$havescale = $havescale || $photo['scale'] == 5;
|
|
}
|
|
|
|
// set an already uloaded photo as profile photo
|
|
// if photo is in 'Profile Photos', change it in db
|
|
if ($photos[0]['photo-type'] == Photo::USER_AVATAR && $havescale) {
|
|
Photo::update(['profile' => false], ['uid' => DI::userSession()->getLocalUserId()]);
|
|
|
|
Photo::update(['profile' => true], ['resource-id' => $resource_id, 'uid' => DI::userSession()->getLocalUserId()]);
|
|
|
|
Contact::updateSelfFromUserID(DI::userSession()->getLocalUserId(), true);
|
|
|
|
// Update global directory in background
|
|
Profile::publishUpdate(DI::userSession()->getLocalUserId());
|
|
|
|
DI::sysmsg()->addInfo(DI::l10n()->t('Profile picture successfully updated.'));
|
|
|
|
DI::baseUrl()->redirect('profile/' . DI::app()->getLoggedInUserNickname());
|
|
}
|
|
|
|
$Image = Photo::getImageForPhoto($photos[0]);
|
|
if (empty($Image)) {
|
|
throw new HTTPException\InternalServerErrorException();
|
|
}
|
|
|
|
$imagecrop = [
|
|
'resource-id' => $resource_id,
|
|
'scale' => $smallest,
|
|
'ext' => $Image->getExt(),
|
|
];
|
|
|
|
$isSquare = $Image->getWidth() === $Image->getHeight();
|
|
|
|
DI::page()['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('settings/profile/photo/crop_head.tpl'), []);
|
|
|
|
$filename = $imagecrop['resource-id'] . '-' . $imagecrop['scale'] . '.' . $imagecrop['ext'];
|
|
$tpl = Renderer::getMarkupTemplate('settings/profile/photo/crop.tpl');
|
|
$o = Renderer::replaceMacros($tpl, [
|
|
'$filename' => $filename,
|
|
'$resource' => $imagecrop['resource-id'] . '-' . $imagecrop['scale'],
|
|
'$image_url' => DI::baseUrl() . '/photo/' . $filename,
|
|
'$title' => DI::l10n()->t('Crop Image'),
|
|
'$desc' => DI::l10n()->t('Please adjust the image cropping for optimum viewing.'),
|
|
'$form_security_token' => self::getFormSecurityToken('settings_profile_photo_crop'),
|
|
'$skip' => $isSquare ? DI::l10n()->t('Use Image As Is') : '',
|
|
'$crop' => DI::l10n()->t('Crop Image'),
|
|
]);
|
|
|
|
return $o;
|
|
}
|
|
}
|