Skip to content

Commit

Permalink
Syncing files from cloud/release/2024.002 to release/2024.002
Browse files Browse the repository at this point in the history
  • Loading branch information
Crousem committed Feb 5, 2024
1 parent 72fd382 commit b3d1844
Show file tree
Hide file tree
Showing 204 changed files with 3,974 additions and 1,046 deletions.
6 changes: 0 additions & 6 deletions addons/themes/theme-dashboard/views/admin.master.twig
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@
<div class="panel panel-left">
<div class="panel-nav panel-content-wrapper">
<div class="js-fluid-fixed panel-content">
<a href="/" class="title">
{{ forumLinkLabel }}
<svg class="icon icon-svg icon-16" alt="external-link" viewbox="0 0 17 17">
<use xlink:href="#external-link"></use>
</svg>
</a>
<div id="panel-nav" class="js-panel-nav">
{{ dashboardNav|raw }}
</div>
Expand Down
21 changes: 11 additions & 10 deletions applications/dashboard/controllers/api/UsersApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -902,13 +902,6 @@ public function patch($id, array $body)
throw new \Garden\Web\Exception\ForbiddenException(t(self::ERROR_PATCH_HIGHER_PERMISSION_USER));
}

// Check for self-edit
if ($id == $this->getSession()->UserID) {
$this->validatePatchSelfEditCredentials($user, $body);
} else {
$this->permission("Garden.Users.Edit");
}

$this->idParamSchema("in");
if ($this->checkPermission("Garden.Users.Edit")) {
$in = $this->schema($this->userPatchSchema(), ["UserPatchCommon", "in"])->setDescription("Update a user.");
Expand All @@ -917,13 +910,23 @@ public function patch($id, array $body)
"Update a user."
);
}

if ($id == $this->getSession()->UserID) {
$in->merge(Schema::parse(["passwordConfirmation:s?"]));
}
$in->addValidator("roleID", $this->createRoleIDValidator($id));
$in->addValidator("profileFields", $this->profileFieldModel->validateEditable($id));

$out = $this->userSchema("out");
$body = $in->validate($body);

// Check for self-edit
if ($id == $this->getSession()->UserID) {
$this->validatePatchSelfEditCredentials($user, $body);
unset($body["passwordConfirmation"]);
} else {
$this->permission("Garden.Users.Edit");
}

$userData = $this->normalizeInput($body);
$userData["UserID"] = $id;
$settings = ["ValidateName" => false];
Expand Down Expand Up @@ -1564,8 +1567,6 @@ public function viewProfileSchema()
"url:s?",
"dateInserted?",
"dateLastActive:dt?",
"isAdmin:b?",
"isSysAdmin:b?",
"countDiscussions?",
"countComments?",
"label:s?",
Expand Down
79 changes: 51 additions & 28 deletions applications/dashboard/controllers/class.profilecontroller.php
Original file line number Diff line number Diff line change
Expand Up @@ -631,9 +631,12 @@ public function index($user = "", $username = "", $userID = "", $page = false)
if (!$user && !$username && !$userID) {
$this->permission("session.valid");
}
if (!Gdn::session()->isValid()) {
//if the user hasn't signed in, check if the guest have permission to view profiles
$this->permission("Garden.Profiles.View");
}

$this->editMode(false);

$this->getUserInfo($user, $username, $userID);

// Optional profile redirection.
Expand Down Expand Up @@ -1061,6 +1064,7 @@ public function picture($userReference = "", $username = "", $userID = "")
);
}

$isSvgImage = Gdn_UploadSvg::isSvg("Avatar");
// Get user data & prep form.
if ($this->Form->authenticatedPostBack() && $this->Form->getFormValue("UserID")) {
$userID = $this->Form->getFormValue("UserID");
Expand All @@ -1075,10 +1079,16 @@ public function picture($userReference = "", $username = "", $userID = "")
$avatar = UserModel::getDefaultAvatarUrl();
}

$extension = strtolower(pathinfo($avatar, PATHINFO_EXTENSION));
$source = "";
$crop = null;
// Don't crop if the uploaded image is a svg file

if ($this->isUploadedAvatar($avatar)) {
if (
((!isset($_FILES["Avatar"]) && $extension !== "svg") ||
(isset($_FILES["Avatar"]) && !$isSvgImage && $extension !== "svg")) &&
$this->isUploadedAvatar($avatar)
) {
// Get the image source so we can manipulate it in the crop module.
$upload = new Gdn_UploadImage();
$thumbnailSize = c("Garden.Thumbnail.Size");
Expand All @@ -1091,18 +1101,18 @@ public function picture($userReference = "", $username = "", $userID = "")
$crop->setSourceImageUrl(Gdn_UploadImage::url(changeBasename($avatar, "p%s")));
$this->setData("crop", $crop);
} else {
$this->setData("avatar", $avatar);
$this->setData("avatar", isUrl($avatar) ? $avatar : Gdn_UploadImage::url(changeBasename($avatar, "p%s")));
}

if (!$this->Form->authenticatedPostBack()) {
$this->Form->setData($configurationModel->Data);
} elseif ($this->Form->save() !== false) {
$upload = new Gdn_UploadImage();
$upload = $isSvgImage ? new Gdn_UploadSvg() : new Gdn_UploadImage();
$newAvatar = false;
if ($tmpAvatar = $upload->validateUpload("Avatar", false)) {
// New upload
$thumbOptions = ["Crop" => true, "SaveGif" => c("Garden.Thumbnail.SaveGif")];
$newAvatar = $this->saveAvatars($tmpAvatar, $thumbOptions, $upload);
$newAvatar = $this->saveAvatars($tmpAvatar, $thumbOptions, $upload, $isSvgImage);
} elseif ($avatar && $crop && $crop->isCropped()) {
// New thumbnail
$tmpAvatar = $source;
Expand All @@ -1116,7 +1126,7 @@ public function picture($userReference = "", $username = "", $userID = "")
$newAvatar = $this->saveAvatars($tmpAvatar, $thumbOptions);
}
if ($this->Form->errorCount() == 0) {
if ($newAvatar !== false) {
if ($newAvatar !== false && !$isSvgImage) {
$thumbnailSize = c("Garden.Thumbnail.Size");
// Update crop properties.
$basename = changeBasename($newAvatar, "p%s");
Expand All @@ -1126,14 +1136,21 @@ public function picture($userReference = "", $username = "", $userID = "")
$crop->setExistingCropUrl(Gdn_UploadImage::url(changeBasename($newAvatar, "n%s")));
$crop->setSourceImageUrl(Gdn_UploadImage::url(changeBasename($newAvatar, "p%s")));
$this->setData("crop", $crop);
} else {
$this->setData(
"avatar",
isUrl($this->User->Photo)
? $this->User->Photo
: Gdn_UploadImage::url(changeBasename($this->User->Photo, "p%s"))
);
}
}
if ($this->deliveryType() === DELIVERY_TYPE_VIEW) {
$this->jsonTarget("", "", "Refresh");

$this->setRedirectTo(userUrl($this->User));
}
if ($upload->Exception) {
if (!empty($upload->Exception)) {
$this->Form->addError($upload->Exception);
} else {
$this->informMessage(t("Your settings have been saved."));
Expand Down Expand Up @@ -1184,42 +1201,48 @@ private function isUploadedAvatar($avatar)
*
* @param string $source The path to the local copy of the image.
* @param array $thumbOptions The options to save the thumbnail-sized avatar with.
* @param Gdn_UploadImage|null $upload The upload object.
* @param Gdn_Upload|null $upload The upload object.
* @param bool $isSvg Whether the image is an SVG.
* @return bool Whether the saves were successful.
*/
private function saveAvatars($source, $thumbOptions, $upload = null)
private function saveAvatars($source, $thumbOptions, $upload = null, $isSvg = false)
{
try {
$ext = "";
if (!$upload) {
$upload = new Gdn_UploadImage();
$ext = "jpg";
$upload = $isSvg ? new Gdn_UploadSvg() : new Gdn_UploadImage();
$ext = $isSvg ? "svg" : "jpg";
}

// Generate the target image name
$targetImage = $upload->generateTargetName(PATH_UPLOADS, $ext, true);
$imageBaseName = pathinfo($targetImage, PATHINFO_BASENAME);
$subdir = stringBeginsWith(dirname($targetImage), PATH_UPLOADS . "/", false, true);

// Save the profile size image.
$parts = Gdn_UploadImage::saveImageAs(
$source,
self::AVATAR_FOLDER . "/$subdir/p$imageBaseName",
c("Garden.Profile.MaxHeight"),
c("Garden.Profile.MaxWidth"),
["SaveGif" => c("Garden.Thumbnail.SaveGif")]
);
if ($isSvg) {
$parts = $upload->saveAs($source, self::AVATAR_FOLDER . "/$subdir/p$imageBaseName", [], true);
$upload->saveAs($source, self::AVATAR_FOLDER . "/$subdir/n$imageBaseName", [], true);
} else {
// Save the profile size image.
$parts = Gdn_UploadImage::saveImageAs(
$source,
self::AVATAR_FOLDER . "/$subdir/p$imageBaseName",
c("Garden.Profile.MaxHeight"),
c("Garden.Profile.MaxWidth"),
["SaveGif" => c("Garden.Thumbnail.SaveGif")]
);

$thumbnailSize = c("Garden.Thumbnail.Size");
$thumbnailSize = c("Garden.Thumbnail.Size");

// Save the thumbnail size image.
Gdn_UploadImage::saveImageAs(
$source,
self::AVATAR_FOLDER . "/$subdir/n$imageBaseName",
$thumbnailSize,
$thumbnailSize,
$thumbOptions
);
// Save the thumbnail size image.
Gdn_UploadImage::saveImageAs(
$source,
self::AVATAR_FOLDER . "/$subdir/n$imageBaseName",
$thumbnailSize,
$thumbnailSize,
$thumbOptions
);
}
} catch (Exception $ex) {
$this->Form->addError($ex);
return false;
Expand Down
113 changes: 74 additions & 39 deletions applications/dashboard/controllers/class.settingscontroller.php
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,23 @@ public function defaultAvatar()
$configurationModel = new Gdn_ConfigurationModel($validation);
$this->Form->setModel($configurationModel);

if (($avatar = c("Garden.DefaultAvatar")) && $this->isUploadedDefaultAvatar($avatar)) {
// If the avatar is a svg file, don't show crop module.
$avatar = c("Garden.DefaultAvatar");
$ext = !empty($avatar) ? strtolower(pathinfo($avatar, PATHINFO_EXTENSION)) : "";
$isSvg = Gdn_UploadSvg::isSvg("DefaultAvatar");
$isImageUploaded = !empty($_FILES["DefaultAvatar"]);

/*
* Don't show crop module on the following conditions as we are not able to crop them:
* 1) if the current avatar is an svg file
* 2) if the current avatar is not a svg file but the uploaded file is a svg file
* 3) if the current avatar is not a svg file but the uploaded file is a svg file
*/
if (
(($isImageUploaded && !$isSvg && $ext !== "svg") || (!$isImageUploaded && $ext !== "svg")) &&
$avatar &&
$this->isUploadedDefaultAvatar($avatar)
) {
//Get the image source so we can manipulate it in the crop module.
$upload = new Gdn_UploadImage();
$thumbnailSize = c("Garden.Thumbnail.Size");
Expand All @@ -434,20 +450,25 @@ public function defaultAvatar()
$crop->setSourceImageUrl(Gdn_UploadImage::url(changeBasename($avatar, "p%s")));
$this->setData("crop", $crop);
} else {
$this->setData("avatar", UserModel::getDefaultAvatarUrl());
$userImage = $avatar
? (isUrl($avatar)
? $avatar
: Gdn_UploadImage::url(changeBasename($avatar, "p%s")))
: UserModel::getDefaultAvatarUrl();
$this->setData("avatar", $userImage);
}

if (!$this->Form->authenticatedPostBack()) {
$this->Form->setData($configurationModel->Data);
} elseif ($this->Form->save() !== false) {
$upload = new Gdn_UploadImage();
$upload = $isSvg ? new Gdn_UploadSvg() : new Gdn_UploadImage();
$newAvatar = false;
$newUpload = false;
if ($tmpAvatar = $upload->validateUpload("DefaultAvatar", false)) {
// New upload
$newUpload = true;
$thumbOptions = ["Crop" => true, "SaveGif" => c("Garden.Thumbnail.SaveGif")];
$newAvatar = $this->saveDefaultAvatars($tmpAvatar, $thumbOptions);
$newAvatar = $this->saveDefaultAvatars($tmpAvatar, $thumbOptions, $isSvg);
} elseif ($avatar && $crop && $crop->isCropped()) {
// New thumbnail
$tmpAvatar = $source;
Expand All @@ -464,18 +485,24 @@ public function defaultAvatar()
if ($newAvatar) {
$this->deleteDefaultAvatars($avatar);
$avatar = c("Garden.DefaultAvatar");
$thumbnailSize = c("Garden.Thumbnail.Size");

// Update crop properties.
$basename = changeBasename($avatar, "p%s");
$source = $upload->copyLocal($basename);
$crop = new CropImageModule($this, $this->Form, $thumbnailSize, $thumbnailSize, $source);
$crop->saveButton = false;
$crop->setSize($thumbnailSize, $thumbnailSize);
$crop->setExistingCropUrl(Gdn_UploadImage::url(changeBasename($avatar, "n%s")));
$crop->setSourceImageUrl(Gdn_UploadImage::url(changeBasename($avatar, "p%s")));
$this->setData("crop", $crop);

if (!$isSvg) {
$thumbnailSize = c("Garden.Thumbnail.Size");

// Update crop properties.
$basename = changeBasename($avatar, "p%s");
$source = $upload->copyLocal($basename);
$crop = new CropImageModule($this, $this->Form, $thumbnailSize, $thumbnailSize, $source);
$crop->saveButton = false;
$crop->setSize($thumbnailSize, $thumbnailSize);
$crop->setExistingCropUrl(Gdn_UploadImage::url(changeBasename($avatar, "n%s")));
$crop->setSourceImageUrl(Gdn_UploadImage::url(changeBasename($avatar, "p%s")));
$this->setData("crop", $crop);
} else {
$this->setData(
"avatar",
isurl($avatar) ? $avatar : Gdn_UploadImage::url(changeBasename($avatar, "p%s"))
);
}
// New uploads stay on the page to allow cropping. Otherwise, redirect to avatar settings page.
if (!$newUpload) {
redirectTo("/dashboard/settings/avatars");
Expand All @@ -495,37 +522,45 @@ public function defaultAvatar()
*
* @param string $source The path to the local copy of the image.
* @param array $thumbOptions The options to save the thumbnail-sized avatar with.
* @param bool $isSvg Whether the image is SVG.
* @return bool Whether the saves were successful.
*/
private function saveDefaultAvatars($source, $thumbOptions)
private function saveDefaultAvatars($source, $thumbOptions, $isSvg = false)
{
try {
$upload = new Gdn_UploadImage();
$upload = $isSvg ? new Gdn_UploadSvg() : new Gdn_UploadImage();
$ext = $isSvg ? "svg" : "jpg";
// Generate the target image name
$targetImage = $upload->generateTargetName(PATH_UPLOADS);
$targetImage = $upload->generateTargetName(PATH_UPLOADS, $ext);
$imageBaseName = pathinfo($targetImage, PATHINFO_BASENAME);

// Save the full size image.
$parts = Gdn_UploadImage::saveImageAs($source, self::DEFAULT_AVATAR_FOLDER . "/" . $imageBaseName);

// Save the profile size image.
Gdn_UploadImage::saveImageAs(
$source,
self::DEFAULT_AVATAR_FOLDER . "/p$imageBaseName",
c("Garden.Profile.MaxHeight"),
c("Garden.Profile.MaxWidth"),
["SaveGif" => c("Garden.Thumbnail.SaveGif")]
);
if ($isSvg) {
$parts = $upload->saveAs($source, self::DEFAULT_AVATAR_FOLDER . "/" . $imageBaseName, [], true);
$upload->saveAs($source, self::DEFAULT_AVATAR_FOLDER . "/p$imageBaseName", [], true);
$upload->saveAs($source, self::DEFAULT_AVATAR_FOLDER . "/n$imageBaseName");
} else {
// Save the full size image.
$parts = Gdn_UploadImage::saveImageAs($source, self::DEFAULT_AVATAR_FOLDER . "/" . $imageBaseName);

// Save the profile size image.
Gdn_UploadImage::saveImageAs(
$source,
self::DEFAULT_AVATAR_FOLDER . "/p$imageBaseName",
c("Garden.Profile.MaxHeight"),
c("Garden.Profile.MaxWidth"),
["SaveGif" => c("Garden.Thumbnail.SaveGif")]
);

$thumbnailSize = c("Garden.Thumbnail.Size");
// Save the thumbnail size image.
Gdn_UploadImage::saveImageAs(
$source,
self::DEFAULT_AVATAR_FOLDER . "/n$imageBaseName",
$thumbnailSize,
$thumbnailSize,
$thumbOptions
);
$thumbnailSize = c("Garden.Thumbnail.Size");
// Save the thumbnail size image.
Gdn_UploadImage::saveImageAs(
$source,
self::DEFAULT_AVATAR_FOLDER . "/n$imageBaseName",
$thumbnailSize,
$thumbnailSize,
$thumbOptions
);
}
} catch (Exception $ex) {
$this->Form->addError($ex);
return false;
Expand Down
2 changes: 1 addition & 1 deletion applications/dashboard/models/DeveloperProfileModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function __construct(ConfigurationInterface $config)
$this->config = $config;
parent::__construct(self::TABLE_NAME);
$this->addPipelineProcessor(
new PruneProcessor("dateRecorded", "7 days", 100, [
new PruneProcessor("dateRecorded", "1 days", 100, [
"isTracked" => false,
])
);
Expand Down

0 comments on commit b3d1844

Please sign in to comment.