--HG--
branch : 1.x
This commit is contained in:
Bertrand Le Roy
2013-02-21 22:29:50 -08:00
21 changed files with 278 additions and 122 deletions

View File

@@ -1,7 +1,6 @@
using System.Linq;
using System.Web.Mvc;
using Orchard.Blogs.Extensions;
using Orchard.Blogs.Routing;
using Orchard.Blogs.Services;
using Orchard.Core.Feeds;
using Orchard.DisplayManagement;
@@ -20,7 +19,6 @@ namespace Orchard.Blogs.Controllers {
private readonly IOrchardServices _services;
private readonly IBlogService _blogService;
private readonly IBlogPostService _blogPostService;
private readonly IBlogPathConstraint _blogPathConstraint;
private readonly IFeedManager _feedManager;
private readonly ISiteService _siteService;
@@ -28,14 +26,12 @@ namespace Orchard.Blogs.Controllers {
IOrchardServices services,
IBlogService blogService,
IBlogPostService blogPostService,
IBlogPathConstraint blogPathConstraint,
IFeedManager feedManager,
IShapeFactory shapeFactory,
ISiteService siteService) {
_services = services;
_blogService = blogService;
_blogPostService = blogPostService;
_blogPathConstraint = blogPathConstraint;
_feedManager = feedManager;
_siteService = siteService;
Logger = NullLogger.Instance;

View File

@@ -51,11 +51,22 @@ namespace Orchard.ContentPicker.Controllers {
if (contentPickerMenuItem.Items.All(x => x.Text.ToString() != T("Recent Content").Text)) {
// the default tab should not be displayed, redirect to the next one
var root = menuItems.FirstOrDefault();
if (root == null) {
return HttpNotFound();
}
var routeData = new RouteValueDictionary(menuItems.First().RouteValues);
var firstChild = root.Items.First();
if (firstChild == null) {
return HttpNotFound();
}
var routeData = new RouteValueDictionary(firstChild.RouteValues);
var queryString = Request.QueryString;
foreach (var key in queryString.AllKeys) {
routeData[key] = queryString[key];
if (!String.IsNullOrEmpty(key)) {
routeData[key] = queryString[key];
}
}
return RedirectToRoute(routeData);

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

View File

@@ -2,7 +2,6 @@
using Orchard.Events;
using Orchard.Fields.Fields;
using Orchard.Localization;
using Orchard.Services;
using Orchard.Core.Shapes.Localization;
using System.Globalization;
@@ -14,23 +13,18 @@ namespace Orchard.Fields.Tokens {
public class FieldTokens : ITokenProvider {
private readonly IClock _clock;
private readonly IDateTimeLocalization _dateTimeLocalization;
private readonly IWorkContextAccessor _workContextAccessor;
private readonly Lazy<CultureInfo> _cultureInfo;
private readonly Lazy<TimeZoneInfo> _timeZone;
public FieldTokens(
IClock clock,
IDateTimeLocalization dateTimeLocalization,
IWorkContextAccessor workContextAccessor) {
_clock = clock;
_dateTimeLocalization = dateTimeLocalization;
_workContextAccessor = workContextAccessor;
_cultureInfo = new Lazy<CultureInfo>(() => CultureInfo.GetCultureInfo(_workContextAccessor.GetContext().CurrentCulture));
_timeZone = new Lazy<TimeZoneInfo>(() => _workContextAccessor.GetContext().CurrentTimeZone);
T = NullLocalizer.Instance;
}

View File

@@ -27,7 +27,7 @@ namespace Orchard.Projections.Providers.Filters {
}
public void ApplyFilter(FilterContext context) {
var contentTypes = Convert.ToString(context.State.ContentTypes);
var contentTypes = (string)context.State.ContentTypes;
if (!String.IsNullOrEmpty(contentTypes)) {
context.Query = context.Query.ForType(contentTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
}

View File

@@ -61,7 +61,7 @@ namespace Orchard.Search.Controllers {
}
if (!_indexManager.HasIndexProvider()) {
return HttpNotFound();
return View("NoIndex");
}
var builder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder("Search");

View File

@@ -118,6 +118,9 @@
<ItemGroup>
<Content Include="Views\DefinitionTemplates\ContentPickerSearchFieldSettings.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\ContentPicker\NoIndex.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -0,0 +1 @@
@T("You need to enable a search index module.")

View File

@@ -9,13 +9,13 @@
<h1>@Html.TitleForPage(T("Search").Text)</h1>
@if (HasText(Model.Query)) {
if (searchResults.Count() == 0) {
if (!searchResults.Any()) {
<p class="search-summary">@T.Plural("There is <em>one</em> result", "<em>zero</em> results", searchResults.Count())</p>
} else {
<p class="search-summary">@T.Plural("There is <em>one</em> result", "<em>{1} - {2}</em> of <em>{0}</em> results", Model.TotalItemCount, Model.StartPosition, Model.EndPosition)</p>
}
}
@if (searchResults != null && searchResults.Count() > 0) {
@if (searchResults != null && searchResults.Any()) {
@Display(searchResults)
@Display(Model.Pager)
}

View File

@@ -31,7 +31,8 @@ namespace Orchard.Tags.Projections {
}
public void ApplyFilter(dynamic context) {
string tags = Convert.ToString(context.State.TagIds);
var tags = (string)context.State.TagIds;
if (!String.IsNullOrEmpty(tags)) {
var ids = tags.Split(new[] { ',' }).Select(Int32.Parse).ToArray();

View File

@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.Data;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.Roles.Models;
using Orchard.Roles.Services;
using Orchard.Workflows.Models;
using Orchard.Workflows.Services;
namespace Orchard.Workflows.Activities {
public class AssignRoleActivity : Task {
private readonly IWorkContextAccessor _workContextAccessor;
private readonly IRepository<UserRolesPartRecord> _repository;
private readonly IRoleService _roleService;
public AssignRoleActivity(
IWorkContextAccessor workContextAccessor,
IRepository<UserRolesPartRecord> repository,
IRoleService roleService) {
_workContextAccessor = workContextAccessor;
_repository = repository;
_roleService = roleService;
T = NullLocalizer.Instance;
Logger = NullLogger.Instance;
}
public Localizer T { get; set; }
public ILogger Logger { get; set; }
public override string Name {
get { return "AssignRole"; }
}
public override LocalizedString Category {
get { return T("User"); }
}
public override LocalizedString Description {
get { return T("Assign specific roles to the current content item if it's a user."); }
}
public override string Form {
get { return "SelectRoles"; }
}
public override IEnumerable<LocalizedString> GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext) {
return new[] {T("Done")};
}
public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext) {
var user = workflowContext.Content.As<IUserRoles>();
// if the current workflow subject is not a user, use current user
if (user == null) {
user = _workContextAccessor.GetContext().CurrentUser.As<IUserRoles>();
}
var roles = GetRoles(activityContext);
if (user != null) {
foreach (var role in roles) {
if (!user.Roles.Contains(role)) {
var roleRecord = _roleService.GetRoleByName(role);
if (roleRecord != null) {
_repository.Create(new UserRolesPartRecord {UserId = user.Id, Role = roleRecord});
}
else {
Logger.Debug("Role not found: {0}", role);
}
}
}
}
yield return T("Done");
}
private IEnumerable<string> GetRoles(ActivityContext context) {
var roles = context.GetState<string>("Roles");
if (String.IsNullOrEmpty(roles)) {
return Enumerable.Empty<string>();
}
return roles.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();
}
}
}

View File

@@ -0,0 +1,53 @@
using System.Collections.Generic;
using Orchard.Comments.Models;
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.Workflows.Models;
using Orchard.Workflows.Services;
namespace Orchard.Workflows.Activities {
public class CloseCommentsActivity : Task {
public CloseCommentsActivity() {
T = NullLocalizer.Instance;
Logger = NullLogger.Instance;
}
public Localizer T { get; set; }
public ILogger Logger { get; set; }
public override string Name {
get { return "CloseComments"; }
}
public override LocalizedString Category {
get { return T("Comments"); }
}
public override LocalizedString Description {
get { return T("Closes the comments on the currently processed content item."); }
}
public override string Form {
get { return null; }
}
public override IEnumerable<LocalizedString> GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext) {
return new[] {T("Done")};
}
public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext) {
var content = workflowContext.Content;
if (content != null) {
var comments = content.As<CommentsPart>();
if (comments != null) {
comments.CommentsActive = false;
}
}
yield return T("Done");
}
}
}

View File

@@ -4,7 +4,6 @@ using System.Linq;
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Roles.Models;
using Orchard.Roles.Services;
using Orchard.Security;
using Orchard.Workflows.Models;
using Orchard.Workflows.Services;
@@ -12,13 +11,9 @@ using Orchard.Workflows.Services;
namespace Orchard.Workflows.Activities {
public class UserTaskActivity : Event {
private readonly IWorkContextAccessor _workContextAccessor;
private readonly IRoleService _roleService;
public UserTaskActivity(
IWorkContextAccessor workContextAccessor,
IRoleService roleService) {
public UserTaskActivity(IWorkContextAccessor workContextAccessor) {
_workContextAccessor = workContextAccessor;
_roleService = roleService;
T = NullLocalizer.Instance;
}
@@ -41,9 +36,7 @@ namespace Orchard.Workflows.Activities {
}
public override IEnumerable<LocalizedString> GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext) {
foreach (var action in GetActions(activityContext)) {
yield return T(action);
}
return GetActions(activityContext).Select(action => T(action));
}
public override bool CanExecute(WorkflowContext workflowContext, ActivityContext activityContext) {
@@ -103,24 +96,24 @@ namespace Orchard.Workflows.Activities {
private IEnumerable<string> GetRoles(ActivityContext context) {
string roles = context.GetState<string>("Roles");
var roles = context.GetState<string>("Roles");
if (String.IsNullOrEmpty(roles)) {
return Enumerable.Empty<string>();
}
return roles.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();
return roles.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();
}
private IEnumerable<string> GetActions(ActivityContext context) {
string actions = context.GetState<string>("Actions");
var actions = context.GetState<string>("Actions");
if (String.IsNullOrEmpty(actions)) {
return Enumerable.Empty<string>();
}
return actions.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();
return actions.Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();
}
}

View File

@@ -43,7 +43,11 @@ namespace Orchard.Workflows.Models {
}
public object GetState(string key) {
return GetState<object>(key);
if (State == null) {
return null;
}
return State[key];
}
public void SetStateFor<T>(ActivityRecord record, string key, T value) {

View File

@@ -9,4 +9,4 @@ Description: Description for the module
Features:
Orchard.Workflows:
Description: Description for feature Orchard.Workflows.
Dependencies: Orchard.Tokens, Orchard.Forms, Orchard.jQuery, Orchard.Roles
Dependencies: Orchard.Tokens, Orchard.Forms, Orchard.jQuery, Orchard.Roles, Orchard.Comments

View File

@@ -71,6 +71,7 @@
<Content Include="Scripts\jquery.jsPlumb-1.3.16-all-min.js" />
<Content Include="Scripts\orchard-workflows-serialize.js" />
<Content Include="Scripts\orchard-workflows.js" />
<Content Include="Styles\workflows-activity.css" />
<Content Include="Styles\images\cog.png" />
<Content Include="Styles\workflows-activity-delete-publish.css" />
<Content Include="Styles\workflows-activity-timer.css" />
@@ -103,6 +104,10 @@
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
<Name>Orchard.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Comments\Orchard.Comments.csproj">
<Project>{14C049FD-B35B-415A-A824-87F26B26E7FD}</Project>
<Name>Orchard.Comments</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Forms\Orchard.Forms.csproj">
<Project>{642a49d7-8752-4177-80d6-bfbbcfad3de0}</Project>
<Name>Orchard.Forms</Name>
@@ -119,6 +124,8 @@
<ItemGroup>
<Compile Include="Activities\ContentActivity.cs" />
<Compile Include="Activities\BranchActivity.cs" />
<Compile Include="Activities\AssignRoleActivity.cs" />
<Compile Include="Activities\CloseCommentsActivity.cs" />
<Compile Include="Activities\MergeBranchActivity.cs" />
<Compile Include="Activities\DeleteActivity.cs" />
<Compile Include="Activities\ExclusiveBranchActivity.cs" />

View File

@@ -20,7 +20,8 @@ namespace Orchard.Workflows {
builder.Add().DefineStyle("WorkflowsActivities-Timer").SetUrl("workflows-activity-timer.css").SetDependencies("WorkflowsAdmin");
builder.Add().DefineStyle("WorkflowsActivities-UserTask").SetUrl("workflows-activity-usertask.css").SetDependencies("WorkflowsAdmin");
builder.Add().DefineStyle("WorkflowsActivities").SetDependencies(
builder.Add().DefineStyle("WorkflowsActivities").SetUrl("workflows-activity.css")
.SetDependencies(
"WorkflowsActivities-Branch",
"WorkflowsActivities-ContentCreate",
"WorkflowsActivities-ContentPublished",

View File

@@ -17,7 +17,6 @@ namespace Orchard.Workflows.Services {
private readonly IRepository<ActivityRecord> _activityRepository;
private readonly IRepository<WorkflowRecord> _workflowRepository;
private readonly IRepository<AwaitingActivityRecord> _awaitingActivityRepository;
private readonly IRepository<WorkflowDefinitionRecord> _workflowDefinitionRepository;
private readonly ITokenizer _tokenizer;
public WorkflowManager(
@@ -25,13 +24,11 @@ namespace Orchard.Workflows.Services {
IRepository<ActivityRecord> activityRepository,
IRepository<WorkflowRecord> workflowRepository,
IRepository<AwaitingActivityRecord> awaitingActivityRepository,
IRepository<WorkflowDefinitionRecord> workflowDefinitionRepository,
ITokenizer tokenizer) {
_activitiesManager = activitiesManager;
_activityRepository = activityRepository;
_workflowRepository = workflowRepository;
_awaitingActivityRepository = awaitingActivityRepository;
_workflowDefinitionRepository = workflowDefinitionRepository;
_tokenizer = tokenizer;
Logger = NullLogger.Instance;
@@ -75,41 +72,6 @@ namespace Orchard.Workflows.Services {
return;
}
var workflowContext = new WorkflowContext {
Content = target,
Tokens = tokens
};
// evaluate processing condition
awaitingActivities = awaitingActivities.Where(a => {
var activityContext = CreateActivityContext(a.ActivityRecord, tokens);
// check the condition
try {
return activity.CanExecute(workflowContext, activityContext);
}
catch (Exception e) {
Logger.Error("Error while evaluating an activity condition on {0}: {1}", name, e.ToString());
return false;
}
}).ToList();
// evaluate processing condition
startedWorkflows = startedWorkflows.Where(a => {
var activityContext = CreateActivityContext(a, tokens);
// check the condition
try {
return activity.CanExecute(workflowContext, activityContext);
}
catch (Exception e) {
Logger.Error("Error while evaluating an activity condition on {0}: {1}", name, e.ToString());
return false;
}
}).ToList();
// if no activity record is matching the event, do nothing
if (!startedWorkflows.Any() && !awaitingActivities.Any()) {
return;
@@ -117,11 +79,57 @@ namespace Orchard.Workflows.Services {
// resume halted workflows
foreach (var awaitingActivityRecord in awaitingActivities) {
var workflowContext = new WorkflowContext {
Content = target,
Tokens = tokens,
Record = awaitingActivityRecord.WorkflowRecord
};
var activityContext = CreateActivityContext(awaitingActivityRecord.ActivityRecord, tokens);
// check the condition
try {
if (!activity.CanExecute(workflowContext, activityContext)) {
continue;
}
}
catch (Exception e) {
Logger.Error("Error while evaluating an activity condition on {0}: {1}", name, e.ToString());
continue;
}
ResumeWorkflow(awaitingActivityRecord, workflowContext, tokens);
}
// start new workflows
foreach (var activityRecord in startedWorkflows) {
var workflowContext = new WorkflowContext {
Content = target,
Tokens = tokens,
};
var workflowRecord = new WorkflowRecord {
WorkflowDefinitionRecord = activityRecord.WorkflowDefinitionRecord,
State = "{}",
ContentItemRecord = workflowContext.Content.ContentItem.Record
};
workflowContext.Record = workflowRecord;
var activityContext = CreateActivityContext(activityRecord, tokens);
// check the condition
try {
if(!activity.CanExecute(workflowContext, activityContext)) {
continue;
}
}
catch (Exception e) {
Logger.Error("Error while evaluating an activity condition on {0}: {1}", name, e.ToString());
continue;
}
StartWorkflow(workflowContext, activityRecord, tokens);
}
}
@@ -136,15 +144,6 @@ namespace Orchard.Workflows.Services {
private void StartWorkflow(WorkflowContext workflowContext, ActivityRecord activityRecord, IDictionary<string, object> tokens) {
// workflow halted, create a workflow state
var workflow = new WorkflowRecord {
WorkflowDefinitionRecord = activityRecord.WorkflowDefinitionRecord,
State = "{}",
ContentItemRecord = workflowContext.Content.ContentItem.Record
};
workflowContext.Record = workflow;
// signal every activity that the workflow is about to start
var cancellationToken = new CancellationToken();
InvokeActivities(activity => activity.OnWorkflowStarting(workflowContext, cancellationToken));
@@ -165,11 +164,12 @@ namespace Orchard.Workflows.Services {
}
else {
// workflow halted, create a workflow state
_workflowRepository.Create(workflow);
_workflowRepository.Create(workflowContext.Record);
foreach (var blocking in blockedOn) {
workflow.AwaitingActivities.Add(new AwaitingActivityRecord {
workflowContext.Record.AwaitingActivities.Add(new AwaitingActivityRecord {
ActivityRecord = blocking,
WorkflowRecord = workflowContext.Record
});
}
}

View File

@@ -2,41 +2,42 @@
@using Orchard.Workflows.Models
<h1>@Html.TitleForPage(T("Running workflows").ToString()) </h1>
<fieldset>
<table class="items">
<thead>
<tr>
<th scope="col" class="checkbox">&nbsp;&darr;</th>
<th scope="col">@T("Worfklow Definition")</th>
<th scope="col">Blocking activities</th>
<th scope="col" class="actions">&nbsp;</th>
</tr>
</thead>
@if (Model.Workflows.Count == 0) {
@T("No workflows associated with this content item.")
}
@foreach (WorkflowRecord workflow in Model.Workflows) {
<tr>
<td>
&nbsp;
</td>
<td>
@Html.ActionLink(workflow.WorkflowDefinitionRecord.Name, "Edit", new { id = workflow.WorkflowDefinitionRecord.Id })
</td>
<td>
@foreach (AwaitingActivityRecord awaiting in workflow.AwaitingActivities) {
@awaiting.ActivityRecord.Name.CamelFriendly()
<br/>
}
&nbsp;
</td>
<td>
@Html.ActionLink(T("Status").ToString(), "Edit", new { id = workflow.WorkflowDefinitionRecord.Id, workflowId = workflow.Id, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl }) |
@Html.ActionLink(T("Delete").ToString(), "DeleteWorkflow", new { id = workflow.Id }, new { itemprop = "RemoveUrl UnsafeUrl", ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl })
</td>
</tr>
}
</table>
</fieldset>
@using (Html.BeginFormAntiForgeryPost()) {
<fieldset>
<table class="items">
<thead>
<tr>
<th scope="col" class="checkbox">&nbsp;&darr;</th>
<th scope="col">@T("Worfklow Definition")</th>
<th scope="col">Blocking activities</th>
<th scope="col" class="actions">&nbsp;</th>
</tr>
</thead>
@if (Model.Workflows.Count == 0) {
@T("No workflows associated with this content item.")
}
@foreach (WorkflowRecord workflow in Model.Workflows) {
<tr>
<td>
&nbsp;
</td>
<td>
@Html.ActionLink(workflow.WorkflowDefinitionRecord.Name, "Edit", new {id = workflow.WorkflowDefinitionRecord.Id})
</td>
<td>
@foreach (AwaitingActivityRecord awaiting in workflow.AwaitingActivities) {
@awaiting.ActivityRecord.Name.CamelFriendly()
<br/>
}
&nbsp;
</td>
<td>
@Html.ActionLink(T("Status").ToString(), "Edit", new {id = workflow.WorkflowDefinitionRecord.Id, workflowId = workflow.Id, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl}) |
@Html.ActionLink(T("Delete").ToString(), "DeleteWorkflow", new {id = workflow.Id}, new {itemprop = "RemoveUrl UnsafeUrl", ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl})
</td>
</tr>
}
</table>
</fieldset>
}

View File

@@ -137,7 +137,7 @@ namespace Orchard.FileSystems.AppData {
var destinationFileName = CombineToPhysicalPath(destinationPath);
MakeDestinationFileNameAvailable(destinationFileName);
File.Copy(sourceFileName, destinationFileName);
File.Copy(sourceFileName, destinationFileName, true);
}
public void DeleteFile(string path) {