From aa232445c83af17a05f56347167fb286c7e51afe Mon Sep 17 00:00:00 2001 From: rpaquay Date: Thu, 12 Nov 2009 22:56:51 +0000 Subject: [PATCH] Update CMS Pages template provider to use YAML parser Also add calls to logging service when things are ignored or erroneous in the template metadata text. --HG-- extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4039982 --- .../Controllers/TemplatesControllerTests.cs | 1 + .../Orchard.CmsPages.Tests.csproj | 2 +- .../Templates/TemplateMetadataParserTests.cs | 64 +++++++++++++++++ .../Templates/TemplateProviderTests.cs | 2 +- .../Orchard.CmsPages/Orchard.CmsPages.csproj | 6 +- .../Services/Templates/MetadataEntry.cs | 4 ++ .../Templates/TemplateMetadataParser.cs | 68 +++++++++++++++++++ .../Services/Templates/TemplateProvider.cs | 9 +-- 8 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Services/Templates/TemplateMetadataParserTests.cs create mode 100644 src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/TemplateMetadataParser.cs diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Controllers/TemplatesControllerTests.cs b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Controllers/TemplatesControllerTests.cs index 9aeda57f7..a4b253107 100644 --- a/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Controllers/TemplatesControllerTests.cs +++ b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Controllers/TemplatesControllerTests.cs @@ -32,6 +32,7 @@ namespace Orchard.CmsPages.Tests.Controllers { builder.Register(); builder.Register().As(); builder.Register().As(); + builder.Register().As(); builder.Register(new StubTemplateEntryProvider()).As(); } diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Orchard.CmsPages.Tests.csproj b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Orchard.CmsPages.Tests.csproj index 81b43109e..0c793ed69 100644 --- a/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Orchard.CmsPages.Tests.csproj +++ b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Orchard.CmsPages.Tests.csproj @@ -82,7 +82,7 @@ - + diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Services/Templates/TemplateMetadataParserTests.cs b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Services/Templates/TemplateMetadataParserTests.cs new file mode 100644 index 000000000..6b8bed18b --- /dev/null +++ b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Services/Templates/TemplateMetadataParserTests.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using System.IO; +using NUnit.Framework; +using Orchard.CmsPages.Services.Templates; + +namespace Orchard.CmsPages.Tests.Services.Templates { + [TestFixture] + public class TemplateMetadataParserTests { + [Test] + public void ParserShouldReturnEmptyListForEmptyMetadata() { + var reader = new StringReader(" \r\n "); + var parser = new TemplateMetadataParser(); + IList result = parser.Parse(reader); + + Assert.That(result.Count, Is.EqualTo(0)); + } + + [Test] + public void ParserShouldIgnoreEmptyTags() { + var reader = new StringReader(" : test value \r\n "); + var parser = new TemplateMetadataParser(); + IList result = parser.Parse(reader); + + Assert.That(result.Count, Is.EqualTo(0)); + } + + [Test] + public void ParserShouldReturnMetadata() { + var reader = new StringReader("Description: test"); + var parser = new TemplateMetadataParser(); + IList result = parser.Parse(reader); + + Assert.That(result.Count, Is.EqualTo(1)); + Assert.That(result[0].Tag, Is.EqualTo("Description")); + Assert.That(result[0].Value, Is.EqualTo("test")); + } + + [Test] + public void ParserShouldReturnMultiMetadata() { + var reader = new StringReader("Description: test\r\nTag2: this is my test "); + var parser = new TemplateMetadataParser(); + IList result = parser.Parse(reader); + + Assert.That(result.Count, Is.EqualTo(2)); + Assert.That(result[0].Tag, Is.EqualTo("Description")); + Assert.That(result[0].Value, Is.EqualTo("test")); + Assert.That(result[1].Tag, Is.EqualTo("Tag2")); + Assert.That(result[1].Value, Is.EqualTo("this is my test")); + } + + [Test] + public void ParserShouldSupportMultiLineValues() { + var reader = new StringReader("Description: test Tag2 this\r\n is my test\r\nName:\r\n FooBar"); + var parser = new TemplateMetadataParser(); + IList result = parser.Parse(reader); + + Assert.That(result.Count, Is.EqualTo(2)); + Assert.That(result[0].Tag, Is.EqualTo("Description")); + Assert.That(result[0].Value, Is.EqualTo("test Tag2 this is my test")); + Assert.That(result[1].Tag, Is.EqualTo("Name")); + Assert.That(result[1].Value, Is.EqualTo("FooBar")); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Services/Templates/TemplateProviderTests.cs b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Services/Templates/TemplateProviderTests.cs index 8b421b70a..3b3650ceb 100644 --- a/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Services/Templates/TemplateProviderTests.cs +++ b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Services/Templates/TemplateProviderTests.cs @@ -10,7 +10,7 @@ namespace Orchard.CmsPages.Tests.Services.Templates { [SetUp] public void Init() { _entryProvider = new StubTemplateEntryProvider(); - _provider = new TemplateProvider(_entryProvider); + _provider = new TemplateProvider(_entryProvider, new TemplateMetadataParser()); _entryProvider.AddTemplate("test1", @" <%@Page %> <%-- diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages/Orchard.CmsPages.csproj b/src/Orchard.Web/Packages/Orchard.CmsPages/Orchard.CmsPages.csproj index ffafb30f7..56f05f4c0 100644 --- a/src/Orchard.Web/Packages/Orchard.CmsPages/Orchard.CmsPages.csproj +++ b/src/Orchard.Web/Packages/Orchard.CmsPages/Orchard.CmsPages.csproj @@ -66,6 +66,10 @@ + + False + ..\..\..\..\lib\yaml\Yaml.dll + @@ -90,7 +94,7 @@ - + diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/MetadataEntry.cs b/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/MetadataEntry.cs index 3bed0a9f5..ed610cf3e 100644 --- a/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/MetadataEntry.cs +++ b/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/MetadataEntry.cs @@ -2,5 +2,9 @@ namespace Orchard.CmsPages.Services.Templates { public class MetadataEntry { public string Tag { get; set; } public string Value { get; set; } + + public override string ToString() { + return string.Format("Tag:{0}, Value:{1}", Tag, Value); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/TemplateMetadataParser.cs b/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/TemplateMetadataParser.cs new file mode 100644 index 000000000..e905b83ce --- /dev/null +++ b/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/TemplateMetadataParser.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Orchard.Logging; +using Orchard.Utility; +using Yaml.Grammar; + +namespace Orchard.CmsPages.Services.Templates { + public interface ITemplateMetadataParser : IDependency { + IList Parse(TextReader reader); + } + + /// + /// Parse the content of a text reader into a list of metadata entries. + /// + public class TemplateMetadataParser : ITemplateMetadataParser { + public TemplateMetadataParser() { + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + private static IList EmptyList { get { return new MetadataEntry[0]; } } + + public IList Parse(TextReader reader) { + string content = reader.ReadToEnd(); + + var yamlInput = new TextInput(content); + + var parser = new YamlParser(); + + bool success; + var stream = parser.ParseYamlStream(yamlInput, out success); + if (!success) { + Logger.Error("Error parsing template metadata. Detailed YAML parsing error: {0}", parser.ErrorMessages); + return EmptyList; + } + + if (stream.Documents.Count == 0) { + Logger.Warning("No template metadata found."); + return EmptyList; + } + + if (stream.Documents.Count >= 2) { + Logger.Information("Some entries where ignored in the template metadata because the metadata text contains more than one YAML 'document'."); + } + + YamlDocument doc = stream.Documents.Single(); + + var root = doc.Root as Mapping; + if (root == null) { + Logger.Error("Invalid template metadata: The YAML root element is not a 'mapping'."); + return EmptyList; + } + + var result = root.Entities + .Where(x => x.Key is Scalar && x.Value is Scalar) + .Select(x => new MetadataEntry { Tag = ((Scalar)x.Key).Text, Value = ((Scalar)x.Value).Text }) + .ToReadOnlyCollection(); + + if (root.Entities.Count != result.Count) { + Logger.Information("Some entries were ignored in template metadata because they are not YAML 'scalars'."); + } + + return result; + } + } +} diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/TemplateProvider.cs b/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/TemplateProvider.cs index 2e95463dc..7e4d1166b 100644 --- a/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/TemplateProvider.cs +++ b/src/Orchard.Web/Packages/Orchard.CmsPages/Services/Templates/TemplateProvider.cs @@ -11,9 +11,11 @@ namespace Orchard.CmsPages.Services.Templates { public class TemplateProvider : ITemplateProvider { private readonly ITemplateEntryProvider _entryProvider; + private readonly ITemplateMetadataParser _parser; - public TemplateProvider(ITemplateEntryProvider entryProvider) { + public TemplateProvider(ITemplateEntryProvider entryProvider, ITemplateMetadataParser parser) { _entryProvider = entryProvider; + _parser = parser; } public IList List() { @@ -33,9 +35,8 @@ namespace Orchard.CmsPages.Services.Templates { .SingleOrDefault(); } - private static TemplateDescriptor CreateDescriptor(TemplateEntry entry) { - var parser = new MetadataParser(); - var metadataEntries = parser.Parse(new CommentExtractor().FirstComment(entry.Content)); + private TemplateDescriptor CreateDescriptor(TemplateEntry entry) { + var metadataEntries = _parser.Parse(new CommentExtractor().FirstComment(entry.Content)); var descriptor = new TemplateDescriptor {Name = entry.Name};