Implementing RssPart

This commit is contained in:
Sebastien Ros
2014-02-28 14:39:01 -08:00
parent 4546c0627c
commit b2d7fa7fde
9 changed files with 338 additions and 5 deletions

View File

@@ -9,7 +9,6 @@ using Orchard.ContentManagement;
using Orchard.Core.Feeds.Models;
using Orchard.Mvc.Extensions;
using Orchard.Services;
using Orchard.Utility.Extensions;
namespace Orchard.Core.Feeds.StandardBuilders {
[UsedImplicitly]
@@ -35,9 +34,7 @@ namespace Orchard.Core.Feeds.StandardBuilders {
_contentManager.GetItemMetadata(feedItem.Item),
_htmlFilters);
// TODO: author
// author is intentionally left empty as it could result in unwanted spam
// add to known formats
if (context.Format == "rss") {

View File

@@ -0,0 +1,19 @@
using Orchard.ContentManagement.MetaData;
using Orchard.Core.Contents.Extensions;
using Orchard.Data.Migration;
namespace Orchard.Tokens {
public class Migrations : DataMigrationImpl {
public int Create() {
ContentDefinitionManager.AlterPartDefinition("RssPart",
cfg => cfg
.Attachable()
.WithDescription("Attach to a content type to provide custom values in RSS feeds.")
);
return 1;
}
}
}

View File

@@ -0,0 +1,6 @@
using Orchard.ContentManagement;
namespace Orchard.Tokens.Models {
public class RssPart : ContentPart {
}
}

View File

@@ -9,4 +9,5 @@ Features:
Orchard.Tokens:
Name: Tokens
Description: Provides a system for performing string replacements with common site values.
Category: Content
Category: Content
Dependencies: Core

View File

@@ -77,6 +77,8 @@
<Content Include="Styles\orchard-tokens-admin.css" />
<Content Include="Styles\Images\tokensPopup.gif" />
<Content Include="Web.config" />
<Compile Include="Migrations.cs" />
<Compile Include="Models\RssPart.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Content Include="Module.txt" />
<Content Include="Views\TokenHint.cshtml" />
@@ -94,12 +96,15 @@
<ItemGroup>
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Providers\ContentTokens.cs" />
<Compile Include="Providers\RssPartFeedItemBuilder.cs" />
<Compile Include="Providers\RequestTokens.cs" />
<Compile Include="Providers\DateTokens.cs" />
<Compile Include="Providers\ShapeTokens.cs" />
<Compile Include="Providers\TextTokens.cs" />
<Compile Include="Providers\UserTokens.cs" />
<Compile Include="ReplaceOptions.cs" />
<Compile Include="RssPartDriver.cs" />
<Compile Include="Settings\RssPartSettings.cs" />
<Compile Include="TokenDescriptor.cs" />
<Compile Include="DescribeContext.cs" />
<Compile Include="DescribeFor.cs" />
@@ -122,6 +127,9 @@
<ItemGroup>
<Folder Include="Views\Admin\" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\DefinitionTemplates\RssPartSettings.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -0,0 +1,202 @@
using System;
using System.Linq;
using System.Xml.Linq;
using Orchard.ContentManagement;
using Orchard.Core.Feeds;
using Orchard.Core.Feeds.Models;
using Orchard.Tokens.Models;
using Orchard.Tokens.Settings;
namespace Orchard.Tokens.Providers {
public class RssPartFeedItemBuilder : IFeedItemBuilder {
private readonly ITokenizer _tokenizer;
public RssPartFeedItemBuilder(
ITokenizer tokenizer) {
_tokenizer = tokenizer;
}
public void Populate(FeedContext context) {
foreach (var feedItem in context.Response.Items.OfType<FeedItem<ContentItem>>()) {
var rssPart = feedItem.Item.As<RssPart>();
if (rssPart == null) {
continue;
}
var settings = rssPart.TypePartDefinition.Settings.GetModel<RssPartSettings>();
// add to known formats
if (context.Format == "rss") {
if (!String.IsNullOrWhiteSpace(settings.Title)) {
var title = feedItem.Element.Element("title");
if (settings.Title == "-") {
if (title != null) {
title.Remove();
}
}
else {
if (title == null) {
feedItem.Element.Add(title = new XElement("title"));
}
FeedItem<ContentItem> item = feedItem;
context.Response.Contextualize(requestContext => {
title.Value = _tokenizer.Replace(settings.Title, new { Content = item.Item, Text = title.Value });
});
}
}
if (!String.IsNullOrWhiteSpace(settings.Author)) {
var author = feedItem.Element.Element("author");
if (settings.Author == "-") {
if (author != null) {
author.Remove();
}
}
else {
if (author == null) {
feedItem.Element.Add(author = new XElement("author"));
}
FeedItem<ContentItem> item = feedItem;
context.Response.Contextualize(requestContext => {
author.Value = _tokenizer.Replace(settings.Title, new { Content = item.Item, Text = author.Value });
});
}
}
if (!String.IsNullOrWhiteSpace(settings.Description)) {
var description = feedItem.Element.Element("description");
if (settings.Description == "-") {
if (description != null) {
description.Remove();
}
}
else {
if (description == null) {
feedItem.Element.Add(description = new XElement("description"));
}
FeedItem<ContentItem> item = feedItem;
context.Response.Contextualize(requestContext => {
description.Value = _tokenizer.Replace(settings.Description, new { Content = item.Item, Text = description.Value });
});
}
}
if (!String.IsNullOrWhiteSpace(settings.Enclosure)) {
var enclosure = feedItem.Element.Element("enclosure");
if (settings.Enclosure == "-") {
if (enclosure != null) {
enclosure.Remove();
}
}
else {
if (enclosure == null) {
feedItem.Element.Add(enclosure = new XElement("enclosure"));
}
FeedItem<ContentItem> item = feedItem;
context.Response.Contextualize(requestContext => {
enclosure.Value = _tokenizer.Replace(settings.Enclosure, new { Content = item.Item, Text = enclosure.Value });
});
}
}
if (!String.IsNullOrWhiteSpace(settings.Link)) {
var link = feedItem.Element.Element("link");
if (settings.Link == "-") {
if (link != null) {
link.Remove();
}
}
else {
if (link == null) {
feedItem.Element.Add(link = new XElement("link"));
}
FeedItem<ContentItem> item = feedItem;
context.Response.Contextualize(requestContext => {
link.Value = _tokenizer.Replace(settings.Link, new { Content = item.Item, Text = link.Value });
});
}
}
if (!String.IsNullOrWhiteSpace(settings.PubDate)) {
var pubDate = feedItem.Element.Element("pubDate");
if (settings.PubDate == "-") {
if (pubDate != null) {
pubDate.Remove();
}
}
else {
if (pubDate == null) {
feedItem.Element.Add(pubDate = new XElement("pubDate"));
}
FeedItem<ContentItem> item = feedItem;
context.Response.Contextualize(requestContext => {
pubDate.Value = _tokenizer.Replace(settings.PubDate, new { Content = item.Item, Text = pubDate.Value });
});
}
}
if (!String.IsNullOrWhiteSpace(settings.Source)) {
var source = feedItem.Element.Element("source");
if (settings.Source == "-") {
if (source != null) {
source.Remove();
}
}
else {
if (source == null) {
feedItem.Element.Add(source = new XElement("source"));
}
FeedItem<ContentItem> item = feedItem;
context.Response.Contextualize(requestContext => {
source.Value = _tokenizer.Replace(settings.Source, new { Content = item.Item, Text = source.Value });
});
}
}
if (!String.IsNullOrWhiteSpace(settings.Category)) {
var categories = feedItem.Element.Elements("category").ToArray();
var currentValue = String.Join(",", categories.Select(x => x.Value).ToArray());
if (settings.Category == "-") {
foreach (var category in categories) {
category.Remove();
}
}
else {
foreach (var category in categories) {
category.Remove();
}
FeedItem<ContentItem> item = feedItem;
context.Response.Contextualize(requestContext => {
var newValue = _tokenizer.Replace(settings.Category, new { Content = item.Item, Text = currentValue });
foreach (var value in newValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) {
feedItem.Element.Add(new XElement("category", value));
}
});
}
}
}
}
}
}
}

View File

@@ -0,0 +1,7 @@
using Orchard.ContentManagement.Drivers;
using Orchard.Tokens.Models;
namespace Orchard.Tokens {
public class RssPartDriver : ContentPartDriver<RssPart> {
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.Tokens.Settings {
public class RssPartSettings {
public string Title { get; set; }
public string Link { get; set; }
public string Description { get; set; }
public string Author { get; set; }
public string Category { get; set; }
public string Enclosure { get; set; }
public string PubDate { get; set; }
public string Source { get; set; }
}
public class RssPartSettingsEvents : ContentDefinitionEditorEventsBase {
public override IEnumerable<TemplateViewModel> TypePartEditor(ContentTypePartDefinition definition) {
if (definition.PartDefinition.Name == "RssPart") {
var model = definition.Settings.GetModel<RssPartSettings>();
yield return DefinitionTemplate(model);
}
}
public override IEnumerable<TemplateViewModel> TypePartEditorUpdate(ContentTypePartDefinitionBuilder builder, IUpdateModel upOwnerModel) {
if (builder.Name == "RssPart") {
var model = new RssPartSettings();
if (upOwnerModel.TryUpdateModel(model, "RssPartSettings", null, null)) {
builder.WithSetting("RssPartSettings.Title", model.Title);
builder.WithSetting("RssPartSettings.Link", model.Link);
builder.WithSetting("RssPartSettings.Description", model.Description);
builder.WithSetting("RssPartSettings.Author", model.Author);
builder.WithSetting("RssPartSettings.Category", model.Category);
builder.WithSetting("RssPartSettings.Enclosure", model.Enclosure);
builder.WithSetting("RssPartSettings.PubDate", model.PubDate);
builder.WithSetting("RssPartSettings.Source", model.Source);
}
yield return DefinitionTemplate(model);
}
}
}
}

View File

@@ -0,0 +1,46 @@
@model Orchard.Tokens.Settings.RssPartSettings
<fieldset>
<span class="hint">@T(" Use '-' to remove the tag, leave empty to keep untouched, or use the 'Text' text token for the current value.")</span>
<div>
<label for="@Html.FieldIdFor(m => m.Title)">@T("Title")</label>
@Html.TextBoxFor(m => m.Title, new { @class = "tokenized text medium" })
<span class="hint">@T("The title field of the RSS item.")</span>
</div>
<div>
<label for="@Html.FieldIdFor(m => m.Link)">@T("Link")</label>
@Html.TextBoxFor(m => m.Link, new { @class = "tokenized text medium" })
<span class="hint">@T("The link field of the RSS item")</span>
</div>
<div>
<label for="@Html.FieldIdFor(m => m.Description)">@T("Description")</label>
@Html.TextBoxFor(m => m.Description, new { @class = "tokenized text medium" })
<span class="hint">@T("The description field of the RSS item")</span>
</div>
<div>
<label for="@Html.FieldIdFor(m => m.Author)">@T("Author")</label>
@Html.TextBoxFor(m => m.Author, new { @class = "tokenized text medium" })
<span class="hint">@T("The author field of the RSS item")</span>
</div>
<div>
<label for="@Html.FieldIdFor(m => m.Category)">@T("Category")</label>
@Html.TextBoxFor(m => m.Category, new { @class = "tokenized text medium" })
<span class="hint">@T("The category field of the RSS item")</span>
</div>
<div>
<label for="@Html.FieldIdFor(m => m.Enclosure)">@T("Enclosure")</label>
@Html.TextBoxFor(m => m.Enclosure, new { @class = "tokenized text medium" })
<span class="hint">@T("The enclosure field of the RSS item. This is usually a html tag like <img>")</span>
</div>
<div>
<label for="@Html.FieldIdFor(m => m.PubDate)">@T("PubDate")</label>
@Html.TextBoxFor(m => m.PubDate, new { @class = "tokenized text medium" })
<span class="hint">@T("The pubDate field of the RSS item")</span>
</div>
<div>
<label for="@Html.FieldIdFor(m => m.Source)">@T("Source")</label>
@Html.TextBoxFor(m => m.Source, new { @class = "tokenized text medium" })
<span class="hint">@T("The source field of the RSS item")</span>
</div>
</fieldset>