Skip to content

Commit

Permalink
Merge branch 'main' into ma/RecyclableMemoryStream
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeAlhayek authored Nov 7, 2024
2 parents 511317a + 5a14fb7 commit fefc90d
Show file tree
Hide file tree
Showing 20 changed files with 225 additions and 125 deletions.
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -3222,6 +3222,15 @@
"contributions": [
"code"
]
},
{
"login": "mohit-naroliya",
"name": "Mohit Naroliya",
"avatar_url": "https://avatars.githubusercontent.com/u/151342309?v=4",
"profile": "https://github.com/mohit-naroliya",
"contributions": [
"code"
]
}
],
"skipCi": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@ public async Task<string> GetTextAsync(string path, Stream fileStream)
// https://github.com/UglyToad/PdfPig/blob/master/src/UglyToad.PdfPig.Core/StreamInputBytes.cs#L45.
// Thus if it isn't, which is the case with e.g. Azure Blob Storage, we need to copy it to a new, seekable
// Stream.
RecyclableMemoryStream seekableStream = null;
FileStream seekableStream = null;
try
{
if (!fileStream.CanSeek)
{
// Since fileStream.Length might not be supported either, we can't preconfigure the capacity of the
// MemoryStream.
seekableStream = MemoryStreamFactory.GetStream();
// While this involves loading the file into memory, we don't really have a choice.
seekableStream = new FileStream(Path.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 4096, FileOptions.DeleteOnClose);

await fileStream.CopyToAsync(seekableStream);

seekableStream.Position = 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public SqlGrammar() : base(false)

// Create Index.
orderList.Rule = MakePlusRule(orderList, comma, orderMember);
orderMember.Rule = Id + orderDirOptional;
orderMember.Rule = Id + (orderDirOptional | "(" + functionArguments + ")");
orderDirOptional.Rule = Empty | "ASC" | "DESC";

// Select stmt.
Expand Down
27 changes: 22 additions & 5 deletions src/OrchardCore.Modules/OrchardCore.Queries/Sql/SqlParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,20 +246,37 @@ private void EvaluateOrderClause(ParseTreeNode parseTreeNode)
var idList = parseTreeNode.ChildNodes[2];

_modes.Push(FormattingModes.SelectClause);

for (var i = 0; i < idList.ChildNodes.Count; i++)
{
var id = idList.ChildNodes[i].ChildNodes[0];

if (i > 0)
{
_builder.Append(", ");
}

var id = idList.ChildNodes[i].ChildNodes[0];

// RANDOM() is a special case where we need to use the dialect's random function.
if (id.ChildNodes[0].Token != null && id.ChildNodes[0].Token.ValueString.Equals("RANDOM", StringComparison.OrdinalIgnoreCase))
{
var funArgs = idList.ChildNodes[i].ChildNodes[1].ChildNodes[0];

// "RANDOM" + {funArgs} + no arguments?
if (funArgs.Term.Name == "funArgs" && funArgs.ChildNodes.Count == 0)
{
_builder.Append(_dialect.RandomOrderByClause);

continue;
}
}

EvaluateId(id);

if (idList.ChildNodes[i].ChildNodes[1].ChildNodes.Count > 0)
var orderDirOpt = idList.ChildNodes[i].ChildNodes[1].ChildNodes[0];

if (orderDirOpt.Term.Name == "orderDirOpt" && orderDirOpt.ChildNodes.Count > 0)
{
_builder.Append(' ').Append(idList.ChildNodes[i].ChildNodes[1].ChildNodes[0].Term.Name);
_builder.Append(' ').Append(orderDirOpt.ChildNodes[0].Term.Name);
}
}

Expand Down Expand Up @@ -805,7 +822,7 @@ private void EvaluateOverClauseOptional(ParseTreeNode overClauseOpt)
var orderMember = orderList.ChildNodes[i];
var id = orderMember.ChildNodes[0];
EvaluateSelectId(id);
var orderDirOpt = orderMember.ChildNodes[1];
var orderDirOpt = orderMember.ChildNodes[1].ChildNodes[0];
if (orderDirOpt.ChildNodes.Count > 0)
{
_builder.Append(' ').Append(orderDirOpt.ChildNodes[0].Term.Name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,26 +164,7 @@ public async Task<IActionResult> CreatePost(TemplateViewModel model, string subm

if (ModelState.IsValid)
{
if (string.IsNullOrWhiteSpace(model.Name))
{
ModelState.AddModelError(nameof(TemplateViewModel.Name), S["The name is mandatory."]);
}
else if (string.IsNullOrWhiteSpace(model.Content))
{
ModelState.AddModelError(nameof(TemplateViewModel.Content), S["The content is mandatory."]);
}
else
{
var templatesDocument = model.AdminTemplates
? await _adminTemplatesManager.GetTemplatesDocumentAsync()
: await _templatesManager.GetTemplatesDocumentAsync()
;

if (templatesDocument.Templates.ContainsKey(model.Name))
{
ModelState.AddModelError(nameof(TemplateViewModel.Name), S["A template with the same name already exists."]);
}
}
await ValidateModelAsync(model);
}

if (ModelState.IsValid)
Expand Down Expand Up @@ -265,18 +246,7 @@ public async Task<IActionResult> Edit(string sourceName, TemplateViewModel model

if (ModelState.IsValid)
{
if (string.IsNullOrWhiteSpace(model.Name))
{
ModelState.AddModelError(nameof(TemplateViewModel.Name), S["The name is mandatory."]);
}
else if (!model.Name.Equals(sourceName, StringComparison.OrdinalIgnoreCase) && templatesDocument.Templates.ContainsKey(model.Name))
{
ModelState.AddModelError(nameof(TemplateViewModel.Name), S["A template with the same name already exists."]);
}
else if (string.IsNullOrWhiteSpace(model.Content))
{
ModelState.AddModelError(nameof(TemplateViewModel.Content), S["The content is mandatory."]);
}
await ValidateModelAsync(model, templatesDocument, sourceName);
}

if (!templatesDocument.Templates.ContainsKey(sourceName))
Expand Down Expand Up @@ -395,4 +365,34 @@ private IActionResult RedirectToReturnUrlOrIndex(string returnUrl)
return RedirectToAction(nameof(Index));
}
}

private async Task ValidateModelAsync(TemplateViewModel model, TemplatesDocument templatesDocument = null, string sourceName = null)
{
if (string.IsNullOrWhiteSpace(model.Name))
{
ModelState.AddModelError(nameof(TemplateViewModel.Name), S["The name is mandatory."]);
}
else
{
templatesDocument ??= model.AdminTemplates
? await _adminTemplatesManager.GetTemplatesDocumentAsync()
: await _templatesManager.GetTemplatesDocumentAsync();

if (!model.Name.Equals(sourceName, StringComparison.OrdinalIgnoreCase) &&
templatesDocument.Templates.ContainsKey(model.Name))
{
ModelState.AddModelError(nameof(TemplateViewModel.Name), S["A template with the same name already exists."]);
}
}

if (string.IsNullOrWhiteSpace(model.Content))
{
var placementsLink = Url.ActionLink("Index", "Admin", new { area = "OrchardCore.Placements" });
var docsLink = "https://docs.orchardcore.net/en/main/reference/modules/Placements/";

await _notifier.WarningAsync(H["If you left the content empty because you want to hide the shape, use <a href=\"{0}\">Placements</a> instead. See <a href=\"{1}\">the docs</a> for more info about this feature.", placementsLink, docsLink]);

ModelState.AddModelError(nameof(TemplateViewModel.Content), S["The content is mandatory."]);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<label asp-for="Content" class="form-label">@T["Content"]</label>
<div id="@Html.IdFor(x => x.Content)_editor" asp-for="Text" style="min-height: 600px;" class="form-control" dir="@culture.GetLanguageDirection()"></div>
<textarea asp-for="Content" class="content-preview-text" hidden>@Html.Raw(Model.Content)</textarea>
<span asp-validation-for="Content"></span>
<span class="hint">@T["The Liquid template."]</span>
</div>
</form>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,12 @@
using OrchardCore.DisplayManagement.Views;
using OrchardCore.Users.Models;
using OrchardCore.Users.TimeZone.Models;
using OrchardCore.Users.TimeZone.Services;
using OrchardCore.Users.TimeZone.ViewModels;

namespace OrchardCore.Users.TimeZone.Drivers;

public sealed class UserTimeZoneDisplayDriver : SectionDisplayDriver<User, UserTimeZone>
{
private readonly IUserTimeZoneService _userTimeZoneService;

public UserTimeZoneDisplayDriver(IUserTimeZoneService userTimeZoneService)
{
_userTimeZoneService = userTimeZoneService;
}

public override IDisplayResult Edit(User user, UserTimeZone userTimeZone, BuildEditorContext context)
{
return Initialize<UserTimeZoneViewModel>("UserTimeZone_Edit", model =>
Expand All @@ -30,10 +22,8 @@ public override async Task<IDisplayResult> UpdateAsync(User user, UserTimeZone u
var model = new UserTimeZoneViewModel();

await context.Updater.TryUpdateModelAsync(model, Prefix);
userTimeZone.TimeZoneId = model.TimeZoneId;

// Remove the cache entry, don't update it, as the form might still fail validation for other reasons.
await _userTimeZoneService.UpdateAsync(user);
userTimeZone.TimeZoneId = model.TimeZoneId;

return await EditAsync(user, userTimeZone, context);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,20 @@ public interface IUserTimeZoneService
/// Gets the time zone for the given user.
/// </summary>
/// <param name="user">The <see cref="IUser"/>.</param>
[Obsolete("This method is deprecated and will be removed in a future release. Please use GetAsync(userName) instead..")]
ValueTask<ITimeZone> GetAsync(IUser user);

/// <summary>
/// Updates the time zone for the given user.
/// </summary>
/// <param name="user">The <see cref="IUser"/>.</param>
[Obsolete("This method is obsolete and will be removed in a future release. Cache invalidation is now handled automatically.")]
ValueTask UpdateAsync(IUser user);

/// <summary>
/// Gets the time zone for the given user.
/// </summary>
/// <param name="userName">The user name.</param>
ValueTask<ITimeZone> GetAsync(string userName)
=> ValueTask.FromResult<ITimeZone>(null);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using OrchardCore.Modules;

namespace OrchardCore.Users.TimeZone.Services;
Expand All @@ -10,29 +9,31 @@ namespace OrchardCore.Users.TimeZone.Services;
public class UserTimeZoneSelector : ITimeZoneSelector
{
private readonly IUserTimeZoneService _userTimeZoneService;
private readonly UserManager<IUser> _userManager;
private readonly IHttpContextAccessor _httpContextAccessor;

public UserTimeZoneSelector(
IUserTimeZoneService userTimeZoneService,
UserManager<IUser> userManager,
IHttpContextAccessor httpContextAccessor)
{
_userTimeZoneService = userTimeZoneService;
_userManager = userManager;
_httpContextAccessor = httpContextAccessor;
}

public async Task<TimeZoneSelectorResult> GetTimeZoneAsync()
public Task<TimeZoneSelectorResult> GetTimeZoneAsync()
{
var currentUser = await _userManager.GetUserAsync(_httpContextAccessor.HttpContext.User);

return currentUser == null
var result = !_httpContextAccessor.HttpContext.User.Identity.IsAuthenticated
? null
: new TimeZoneSelectorResult
{
Priority = 100,
TimeZoneId = async () => (await _userTimeZoneService.GetAsync(currentUser))?.TimeZoneId
TimeZoneId = async () =>
{
var timeZone = await _userTimeZoneService.GetAsync(_httpContextAccessor.HttpContext.User.Identity.Name);
return timeZone?.TimeZoneId;
},
};

return Task.FromResult(result);
}
}
Loading

0 comments on commit fefc90d

Please sign in to comment.