/Modules/Orchard.Tokens/Providers/ContentTokens.cs

http://eking.codeplex.com · C# · 154 lines · 129 code · 20 blank · 5 comment · 16 complexity · d813d4149668c15b2de6582fda51f7f7 MD5 · raw file

  1. using System.Linq;
  2. using System.Web;
  3. using System.Web.Mvc;
  4. using Orchard.ContentManagement;
  5. using Orchard.ContentManagement.Aspects;
  6. using Orchard.ContentManagement.MetaData.Models;
  7. using Orchard.Core.Common.Fields;
  8. using Orchard.Localization;
  9. using Orchard.ContentManagement.FieldStorage;
  10. using Orchard.Mvc.Extensions;
  11. namespace Orchard.Tokens.Providers {
  12. public class ContentTokens : ITokenProvider {
  13. private readonly IContentManager _contentManager;
  14. private readonly IWorkContextAccessor _workContextAccessor;
  15. public ContentTokens(IContentManager contentManager, IWorkContextAccessor workContextAccessor) {
  16. _contentManager = contentManager;
  17. _workContextAccessor = workContextAccessor;
  18. T = NullLocalizer.Instance;
  19. }
  20. public Localizer T { get; set; }
  21. public void Describe(DescribeContext context) {
  22. context.For("Content", T("Content Items"), T("Content Items"))
  23. .Token("Id", T("Content Id"), T("Numeric primary key value of content."))
  24. .Token("Author", T("Content Author"), T("Person in charge of the content."), "User")
  25. .Token("Date", T("Content Date"), T("Date the content was created."), "DateTime")
  26. .Token("Identity", T("Identity"), T("Identity of the content."))
  27. .Token("ContentType", T("Content Type"), T("The name of the item Content Type."), "TypeDefinition")
  28. .Token("DisplayText", T("Display Text"), T("Title of the content."),"Text")
  29. .Token("DisplayUrl", T("Display Url"), T("Url to display the content."), "Url")
  30. .Token("EditUrl", T("Edit Url"), T("Url to edit the content."), "Url")
  31. .Token("Container", T("Container"), T("The container Content Item."), "Content")
  32. ;
  33. // Token descriptors for fields
  34. foreach(var typeDefinition in _contentManager.GetContentTypeDefinitions()) {
  35. foreach (var typePart in typeDefinition.Parts) {
  36. if(!typePart.PartDefinition.Fields.Any()) {
  37. continue;
  38. }
  39. var partContext = context.For("Content");
  40. foreach (var partField in typePart.PartDefinition.Fields) {
  41. var field = partField;
  42. var tokenName = "Fields." + typePart.PartDefinition.Name + "." + field.Name;
  43. // the token is chained with the technical name
  44. partContext.Token(tokenName, T("{0} {1}", typePart.PartDefinition.Name, field.Name), T("The content of the {0} field.", partField.DisplayName), field.Name);
  45. }
  46. }
  47. }
  48. context.For("TextField", T("Text Field"), T("Tokens for Text Fields"))
  49. .Token("Length", T("Length"), T("The length of the field."));
  50. context.For("Url", T("Url"), T("Tokens for Urls"))
  51. .Token("Absolute", T("Absolute"), T("Absolute url."));
  52. context.For("TypeDefinition", T("Type Definition"), T("Tokens for Content Types"))
  53. .Token("Name", T("Name"), T("Name of the content type."))
  54. .Token("DisplayName", T("Display Name"), T("Display name of the content type."), "Text")
  55. .Token("Parts", T("Parts"), T("List of the attached part names."))
  56. .Token("Fields", T("Fields"), T("Fields for each of the attached parts. For example, Fields.Page.Approved."));
  57. }
  58. public void Evaluate(EvaluateContext context) {
  59. context.For<IContent>("Content")
  60. .Token("Id", content => content.Id)
  61. .Token("Author", AuthorName)
  62. .Chain("Author", "User", content => content.As<ICommonPart>().Owner)
  63. .Token("Date", content => content.As<ICommonPart>().CreatedUtc)
  64. .Chain("Date", "Date", content => content.As<ICommonPart>().CreatedUtc)
  65. .Token("Identity", content => _contentManager.GetItemMetadata(content).Identity.ToString())
  66. .Token("ContentType", content => content.ContentItem.TypeDefinition.DisplayName)
  67. .Chain("ContentType", "TypeDefinition", content => content.ContentItem.TypeDefinition)
  68. .Token("DisplayText", content => _contentManager.GetItemMetadata(content).DisplayText)
  69. .Chain("DisplayText", "Text", content => _contentManager.GetItemMetadata(content).DisplayText)
  70. .Token("DisplayUrl", content => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).RouteUrl(_contentManager.GetItemMetadata(content).DisplayRouteValues))
  71. .Chain("DisplayUrl", "Url", content => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).RouteUrl(_contentManager.GetItemMetadata(content).DisplayRouteValues))
  72. .Token("EditUrl", content => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).RouteUrl(_contentManager.GetItemMetadata(content).EditorRouteValues))
  73. .Chain("EditUrl", "Url", content => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).RouteUrl(_contentManager.GetItemMetadata(content).EditorRouteValues))
  74. .Token("Container", content => {
  75. var container = Container(content);
  76. if(container == null) {
  77. return string.Empty;
  78. }
  79. return _contentManager.GetItemMetadata(container).DisplayText;
  80. })
  81. .Chain("Container", "Content", content => Container(content))
  82. ;
  83. if (context.Target == "Content") {
  84. var forContent = context.For<IContent>("Content");
  85. // is there a content available in the context ?
  86. if (forContent != null && forContent.Data != null && forContent.Data.ContentItem != null) {
  87. foreach (var typePart in forContent.Data.ContentItem.TypeDefinition.Parts) {
  88. var part = typePart;
  89. foreach (var partField in typePart.PartDefinition.Fields) {
  90. var field = partField;
  91. var tokenName = "Fields." + typePart.PartDefinition.Name + "." + partField.Name;
  92. forContent.Token(
  93. tokenName,
  94. content => LookupField(content, part.PartDefinition.Name, field.Name).Storage.Get<string>());
  95. forContent.Chain(
  96. tokenName,
  97. partField.FieldDefinition.Name,
  98. content => LookupField(content, part.PartDefinition.Name, field.Name));
  99. }
  100. }
  101. }
  102. }
  103. context.For<string>("Url")
  104. .Token("Absolute", url => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).MakeAbsolute(url));
  105. context.For<TextField>("TextField")
  106. .Token("Length", field => (field.Value ?? "").Length);
  107. context.For<ContentTypeDefinition>("TypeDefinition")
  108. .Token("Name", def => def.Name)
  109. .Token("DisplayName", def => def.DisplayName)
  110. .Chain("DisplayName", "Text", def => def.DisplayName)
  111. .Token("Parts", def => string.Join(", ", def.Parts.Select(x => x.PartDefinition.Name).ToArray()))
  112. .Token("Fields", def => string.Join(", ", def.Parts.SelectMany(x => x.PartDefinition.Fields.Select(x2 => x2.FieldDefinition.Name + " " + x.PartDefinition.Name + "." + x2.Name)).ToArray()));
  113. }
  114. private IHtmlString AuthorName(IContent content) {
  115. var author = content.As<ICommonPart>().Owner;
  116. // todo: encoding should be done at a higher level automatically and should be configurable via an options param
  117. // so it can be disabled
  118. return author == null ? (IHtmlString)T("Anonymous") : new HtmlString(HttpUtility.HtmlEncode(author.UserName));
  119. }
  120. private static ContentField LookupField(IContent content, string partName, string fieldName) {
  121. return content.ContentItem.Parts
  122. .Where(part => part.PartDefinition.Name == partName)
  123. .SelectMany(part => part.Fields.Where(field => field.Name == fieldName))
  124. .SingleOrDefault();
  125. }
  126. private IContent Container(IContent content) {
  127. var commonPart = content.As<ICommonPart>();
  128. if(commonPart == null) {
  129. return null;
  130. }
  131. return commonPart.Container;
  132. }
  133. }
  134. }