- @// todo: make these real (including markup)
-
-
-
-
-
- ", ResolveUrl("~/Media/" + Model.RelativePath + "/" + Model.Name), 500, 375)" />
- @T("Copy this html to add this image to your site.")
-
-
-
- *@
- }
+ }
+
\ No newline at end of file
From b77e52244bfc118c0d5e8a32778c962744a80171 Mon Sep 17 00:00:00 2001
From: Andre Rodrigues
Date: Wed, 24 Nov 2010 13:45:49 -0800
Subject: [PATCH 2/4] Moving permissions to initial validations. Removing
if/else for form post and using annotation instead.
--HG--
branch : dev
---
.../Controllers/AdminController.cs | 114 +++++++++++-------
1 file changed, 68 insertions(+), 46 deletions(-)
diff --git a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs
index f5b2fe736..45eeea110 100644
--- a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs
+++ b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs
@@ -3,15 +3,12 @@ using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.Mvc;
-using JetBrains.Annotations;
-using Orchard.ContentManagement;
+using Orchard.Core.Contents.Controllers;
using Orchard.Localization;
using Orchard.Media.Models;
using Orchard.Media.Services;
using Orchard.Media.ViewModels;
-using Orchard.Settings;
using Orchard.UI.Notify;
-using Orchard.Utility.Extensions;
namespace Orchard.Media.Controllers {
[ValidateInput(false)]
@@ -56,11 +53,13 @@ namespace Orchard.Media.Controllers {
[HttpPost]
public ActionResult Create() {
+ if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't create media folder")))
+ return new HttpUnauthorizedResult();
+
var viewModel = new MediaFolderCreateViewModel();
try {
UpdateModel(viewModel);
- if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't create media folder")))
- return new HttpUnauthorizedResult();
+
_mediaService.CreateFolder(viewModel.MediaPath, viewModel.Name);
return RedirectToAction("Index");
}
@@ -109,24 +108,16 @@ namespace Orchard.Media.Controllers {
return View(model);
}
- [HttpPost]
- public ActionResult EditProperties() {
+ [HttpPost, ActionName("EditProperties")]
+ [FormValueRequired("submit.Delete")]
+ public ActionResult EditPropertiesDeletePOST() {
var viewModel = new MediaFolderEditPropertiesViewModel();
try {
UpdateModel(viewModel);
- //TODO: There may be better ways to do this.
- // Delete
- if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) {
- if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media folder")))
- return new HttpUnauthorizedResult();
- _mediaService.DeleteFolder(viewModel.MediaPath);
- }
- // Save
- else {
- if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't rename media folder")))
- return new HttpUnauthorizedResult();
- _mediaService.RenameFolder(viewModel.MediaPath, viewModel.Name);
- }
+
+ if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media folder")))
+ return new HttpUnauthorizedResult();
+ _mediaService.DeleteFolder(viewModel.MediaPath);
return RedirectToAction("Index");
}
@@ -136,6 +127,25 @@ namespace Orchard.Media.Controllers {
}
}
+ [HttpPost, ActionName("EditProperties")]
+ [FormValueRequired("submit.Save")]
+ public ActionResult EditProperties() {
+ if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't rename media folder")))
+ return new HttpUnauthorizedResult();
+
+ var viewModel = new MediaFolderEditPropertiesViewModel();
+ try {
+ UpdateModel(viewModel);
+
+ _mediaService.RenameFolder(viewModel.MediaPath, viewModel.Name);
+
+ return RedirectToAction("Index");
+ } catch (Exception exception) {
+ Services.Notifier.Error(T("Modifying Folder Properties failed: {0}", exception.Message));
+ return View(viewModel);
+ }
+ }
+
public ActionResult Add(string folderName, string mediaPath) {
var model = new MediaItemAddViewModel { FolderName = folderName, MediaPath = mediaPath };
return View(model);
@@ -143,11 +153,12 @@ namespace Orchard.Media.Controllers {
[HttpPost]
public ActionResult Add() {
+ if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles, T("Couldn't upload media file")))
+ return new HttpUnauthorizedResult();
+
var viewModel = new MediaItemAddViewModel();
try {
UpdateModel(viewModel);
- if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles, T("Couldn't upload media file")))
- return new HttpUnauthorizedResult();
if(String.IsNullOrWhiteSpace(Request.Files[0].FileName)) {
ModelState.AddModelError("File", T("Select a file to upload").ToString());
@@ -180,11 +191,12 @@ namespace Orchard.Media.Controllers {
[HttpPost]
public ContentResult AddFromClient() {
+ if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles))
+ return Content(string.Format("", T("ERROR: You don't have permission to upload media files")));
+
var viewModel = new MediaItemAddViewModel();
try {
UpdateModel(viewModel);
- if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles))
- return Content(string.Format("", T("ERROR: You don't have permission to upload media files")));
if (Request.Files.Count < 1 || Request.Files[0].ContentLength == 0)
return Content(string.Format("", T("HEY: You didn't give me a file to upload")));
@@ -220,32 +232,42 @@ namespace Orchard.Media.Controllers {
return View(model);
}
- [HttpPost]
- public ActionResult EditMedia(FormCollection input) {
+ [HttpPost, ActionName("EditMedia")]
+ [FormValueRequired("submit.Delete")]
+ public ActionResult EditMediaDeletePOST(FormCollection input) {
+ if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media file")))
+ return new HttpUnauthorizedResult();
+
var viewModel = new MediaItemEditViewModel();
try {
UpdateModel(viewModel);
- if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't modify media file")))
- return new HttpUnauthorizedResult();
- // Delete
- if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) {
- if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media file")))
- return new HttpUnauthorizedResult();
- _mediaService.DeleteFile(viewModel.Name, viewModel.MediaPath);
- return RedirectToAction("Edit", new { name = viewModel.FolderName, mediaPath = viewModel.MediaPath });
- }
- // Save and Rename
+
+ _mediaService.DeleteFile(viewModel.Name, viewModel.MediaPath);
+ return RedirectToAction("Edit", new { name = viewModel.FolderName, mediaPath = viewModel.MediaPath });
+ } catch (Exception exception) {
+ Services.Notifier.Error(T("Removing media file failed: {0}", exception.Message));
+ return View(viewModel);
+ }
+ }
+
+ [HttpPost, ActionName("EditMedia")]
+ [FormValueRequired("submit.Save")]
+ public ActionResult EditMedia(FormCollection input) {
+ if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't modify media file")))
+ return new HttpUnauthorizedResult();
+
+ var viewModel = new MediaItemEditViewModel();
+ try {
+ UpdateModel(viewModel);
+ string viewModelName = viewModel.Name;
+
+ // Rename
if (!String.Equals(viewModel.Name, input["NewName"], StringComparison.OrdinalIgnoreCase)) {
_mediaService.RenameFile(viewModel.Name, input["NewName"], viewModel.MediaPath);
- return RedirectToAction("EditMedia", new { name = input["NewName"],
- caption = viewModel.Caption,
- lastUpdated = viewModel.LastUpdated,
- size = viewModel.Size,
- folderName = viewModel.FolderName,
- mediaPath = viewModel.MediaPath });
+ viewModelName = input["NewName"];
}
- // Save
- return RedirectToAction("EditMedia", new { name = viewModel.Name,
+
+ return RedirectToAction("EditMedia", new { name = viewModelName,
caption = viewModel.Caption,
lastUpdated = viewModel.LastUpdated,
size = viewModel.Size,
@@ -258,4 +280,4 @@ namespace Orchard.Media.Controllers {
}
}
}
-}
+}
\ No newline at end of file
From 26524253782d271f8d6e597f3b1f10e598511e26 Mon Sep 17 00:00:00 2001
From: Andre Rodrigues
Date: Wed, 24 Nov 2010 14:10:33 -0800
Subject: [PATCH 3/4] #16864 Making invalid rename to fail.
--HG--
branch : dev
---
.../Modules/Orchard.Media/Controllers/AdminController.cs | 5 +++--
.../Modules/Orchard.Media/Services/MediaService.cs | 6 ++++--
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs
index 45eeea110..ba6b08c0d 100644
--- a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs
+++ b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs
@@ -111,12 +111,13 @@ namespace Orchard.Media.Controllers {
[HttpPost, ActionName("EditProperties")]
[FormValueRequired("submit.Delete")]
public ActionResult EditPropertiesDeletePOST() {
+ if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media folder")))
+ return new HttpUnauthorizedResult();
+
var viewModel = new MediaFolderEditPropertiesViewModel();
try {
UpdateModel(viewModel);
- if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media folder")))
- return new HttpUnauthorizedResult();
_mediaService.DeleteFolder(viewModel.MediaPath);
return RedirectToAction("Index");
diff --git a/src/Orchard.Web/Modules/Orchard.Media/Services/MediaService.cs b/src/Orchard.Web/Modules/Orchard.Media/Services/MediaService.cs
index e990545bb..459264f0e 100644
--- a/src/Orchard.Web/Modules/Orchard.Media/Services/MediaService.cs
+++ b/src/Orchard.Web/Modules/Orchard.Media/Services/MediaService.cs
@@ -83,9 +83,11 @@ namespace Orchard.Media.Services {
}
public void RenameFile(string name, string newName, string folderName) {
- if (FileAllowed(newName, false)) {
- _storageProvider.RenameFile(_storageProvider.Combine(folderName, name), _storageProvider.Combine(folderName, newName));
+ if (!FileAllowed(newName, false)) {
+ throw new ArgumentException("New file name " + newName + " not allowed.");
}
+
+ _storageProvider.RenameFile(_storageProvider.Combine(folderName, name), _storageProvider.Combine(folderName, newName));
}
public string UploadMediaFile(string folderName, HttpPostedFileBase postedFile) {
From 67a45f1c09993dc959571687c862e9394f177b1c Mon Sep 17 00:00:00 2001
From: Sebastien Ros
Date: Wed, 24 Nov 2010 15:24:11 -0800
Subject: [PATCH 4/4] Validating content type names, and displaying technical
names
Work Item: 16471
--HG--
branch : dev
---
src/Orchard.Specs/ContentTypes.feature | 84 ++++++
src/Orchard.Specs/ContentTypes.feature.cs | 276 ++++++++++++++++++
src/Orchard.Specs/Orchard.Specs.csproj | 9 +
.../Controllers/AdminController.cs | 23 +-
.../Services/ContentDefinitionService.cs | 33 ++-
.../Services/IContentDefinitionService.cs | 4 +-
.../ViewModels/CreateTypeViewModel.cs | 1 +
.../Views/Admin/Create.cshtml | 32 +-
.../Views/Admin/Edit.cshtml | 2 +-
9 files changed, 446 insertions(+), 18 deletions(-)
create mode 100644 src/Orchard.Specs/ContentTypes.feature
create mode 100644 src/Orchard.Specs/ContentTypes.feature.cs
diff --git a/src/Orchard.Specs/ContentTypes.feature b/src/Orchard.Specs/ContentTypes.feature
new file mode 100644
index 000000000..cb994d201
--- /dev/null
+++ b/src/Orchard.Specs/ContentTypes.feature
@@ -0,0 +1,84 @@
+Feature: Content Types
+ In order to add new types to my site
+ As an adminitrator
+ I want to create create content types
+
+Scenario: I can create a new content type
+ Given I have installed Orchard
+ And I have installed "Orchard.ContentTypes"
+ When I go to "Admin/ContentTypes"
+ Then I should see "]*>.*?Create new type"
+ When I go to "Admin/ContentTypes/Create"
+ And I fill in
+ | name | value |
+ | DisplayName | Event |
+ | Name | Event |
+ And I hit "Create"
+ And I go to "Admin/ContentTypes/"
+ Then I should see "Event"
+
+Scenario: I can't create a content type with an already existing name
+ Given I have installed Orchard
+ And I have installed "Orchard.ContentTypes"
+ When I go to "Admin/ContentTypes/Create"
+ And I fill in
+ | name | value |
+ | DisplayName | Event |
+ | Name | Event |
+ And I hit "Create"
+ And I go to "Admin/ContentTypes/"
+ Then I should see "Event"
+ When I go to "Admin/ContentTypes/Create"
+ And I fill in
+ | name | value |
+ | DisplayName | Event |
+ | Name | Event-2 |
+ And I hit "Create"
+ Then I should see "
]*>.*?New Content Type.*?
"
+ And I should see "validation-summary-errors"
+
+Scenario: I can't create a content type with an already existing technical name
+ Given I have installed Orchard
+ And I have installed "Orchard.ContentTypes"
+ When I go to "Admin/ContentTypes/Create"
+ And I fill in
+ | name | value |
+ | DisplayName | Dinner |
+ | Name | Dinner |
+ And I hit "Create"
+ And I go to "Admin/ContentTypes/"
+ Then I should see "Dinner"
+ When I go to "Admin/ContentTypes/Create"
+ And I fill in
+ | name | value |
+ | DisplayName | Dinner2 |
+ | Name | Dinner |
+ And I hit "Create"
+ Then I should see "
]*>.*?New Content Type.*?
"
+ And I should see "validation-summary-errors"
+
+Scenario: I can't rename a content type with an already existing name
+ Given I have installed Orchard
+ And I have installed "Orchard.ContentTypes"
+ When I go to "Admin/ContentTypes/Create"
+ And I fill in
+ | name | value |
+ | DisplayName | Dinner |
+ | Name | Dinner |
+ And I hit "Create"
+ And I go to "Admin/ContentTypes/"
+ Then I should see "Dinner"
+ When I go to "Admin/ContentTypes/Create"
+ And I fill in
+ | name | value |
+ | DisplayName | Event |
+ | Name | Event |
+ And I hit "Create"
+ And I go to "Admin/ContentTypes/"
+ Then I should see "Event"
+ When I go to "Admin/ContentTypes/Edit/Dinner"
+ And I fill in
+ | name | value |
+ | DisplayName | Event |
+ And I hit "Save"
+ Then I should see "validation-summary-errors"
diff --git a/src/Orchard.Specs/ContentTypes.feature.cs b/src/Orchard.Specs/ContentTypes.feature.cs
new file mode 100644
index 000000000..1d5dc2ee1
--- /dev/null
+++ b/src/Orchard.Specs/ContentTypes.feature.cs
@@ -0,0 +1,276 @@
+// ------------------------------------------------------------------------------
+//
+// This code was generated by SpecFlow (http://www.specflow.org/).
+// SpecFlow Version:1.3.0.0
+// Runtime Version:4.0.30319.1
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+#region Designer generated code
+namespace Orchard.Specs
+{
+ using TechTalk.SpecFlow;
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.3.0.0")]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [NUnit.Framework.TestFixtureAttribute()]
+ [NUnit.Framework.DescriptionAttribute("Content Types")]
+ public partial class ContentTypesFeature
+ {
+
+ private static TechTalk.SpecFlow.ITestRunner testRunner;
+
+#line 1 "ContentTypes.feature"
+#line hidden
+
+ [NUnit.Framework.TestFixtureSetUpAttribute()]
+ public virtual void FeatureSetup()
+ {
+ testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
+ TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Content Types", "In order to add new types to my site\r\nAs an adminitrator\r\nI want to create create" +
+ " content types", ((string[])(null)));
+ testRunner.OnFeatureStart(featureInfo);
+ }
+
+ [NUnit.Framework.TestFixtureTearDownAttribute()]
+ public virtual void FeatureTearDown()
+ {
+ testRunner.OnFeatureEnd();
+ testRunner = null;
+ }
+
+ public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
+ {
+ testRunner.OnScenarioStart(scenarioInfo);
+ }
+
+ [NUnit.Framework.TearDownAttribute()]
+ public virtual void ScenarioTearDown()
+ {
+ testRunner.OnScenarioEnd();
+ }
+
+ [NUnit.Framework.TestAttribute()]
+ [NUnit.Framework.DescriptionAttribute("I can create a new content type")]
+ public virtual void ICanCreateANewContentType()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can create a new content type", ((string[])(null)));
+#line 6
+this.ScenarioSetup(scenarioInfo);
+#line 7
+testRunner.Given("I have installed Orchard");
+#line 8
+testRunner.And("I have installed \"Orchard.ContentTypes\"");
+#line 9
+testRunner.When("I go to \"Admin/ContentTypes\"");
+#line 10
+testRunner.Then("I should see \"]*>.*?Create new type\"");
+#line 11
+testRunner.When("I go to \"Admin/ContentTypes/Create\"");
+#line hidden
+ TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] {
+ "name",
+ "value"});
+ table1.AddRow(new string[] {
+ "DisplayName",
+ "Event"});
+ table1.AddRow(new string[] {
+ "Name",
+ "Event"});
+#line 12
+testRunner.And("I fill in", ((string)(null)), table1);
+#line 16
+testRunner.And("I hit \"Create\"");
+#line 17
+testRunner.And("I go to \"Admin/ContentTypes/\"");
+#line 18
+testRunner.Then("I should see \"Event\"");
+#line hidden
+ testRunner.CollectScenarioErrors();
+ }
+
+ [NUnit.Framework.TestAttribute()]
+ [NUnit.Framework.DescriptionAttribute("I can\'t create a content type with an already existing name")]
+ public virtual void ICanTCreateAContentTypeWithAnAlreadyExistingName()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can\'t create a content type with an already existing name", ((string[])(null)));
+#line 20
+this.ScenarioSetup(scenarioInfo);
+#line 21
+testRunner.Given("I have installed Orchard");
+#line 22
+testRunner.And("I have installed \"Orchard.ContentTypes\"");
+#line 23
+testRunner.When("I go to \"Admin/ContentTypes/Create\"");
+#line hidden
+ TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] {
+ "name",
+ "value"});
+ table2.AddRow(new string[] {
+ "DisplayName",
+ "Event"});
+ table2.AddRow(new string[] {
+ "Name",
+ "Event"});
+#line 24
+testRunner.And("I fill in", ((string)(null)), table2);
+#line 28
+testRunner.And("I hit \"Create\"");
+#line 29
+testRunner.And("I go to \"Admin/ContentTypes/\"");
+#line 30
+testRunner.Then("I should see \"Event\"");
+#line 31
+testRunner.When("I go to \"Admin/ContentTypes/Create\"");
+#line hidden
+ TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] {
+ "name",
+ "value"});
+ table3.AddRow(new string[] {
+ "DisplayName",
+ "Event"});
+ table3.AddRow(new string[] {
+ "Name",
+ "Event-2"});
+#line 32
+testRunner.And("I fill in", ((string)(null)), table3);
+#line 36
+testRunner.And("I hit \"Create\"");
+#line 37
+testRunner.Then("I should see \"
]*>.*?New Content Type.*?
\"");
+#line 38
+testRunner.And("I should see \"validation-summary-errors\"");
+#line hidden
+ testRunner.CollectScenarioErrors();
+ }
+
+ [NUnit.Framework.TestAttribute()]
+ [NUnit.Framework.DescriptionAttribute("I can\'t create a content type with an already existing technical name")]
+ public virtual void ICanTCreateAContentTypeWithAnAlreadyExistingTechnicalName()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can\'t create a content type with an already existing technical name", ((string[])(null)));
+#line 40
+this.ScenarioSetup(scenarioInfo);
+#line 41
+testRunner.Given("I have installed Orchard");
+#line 42
+testRunner.And("I have installed \"Orchard.ContentTypes\"");
+#line 43
+testRunner.When("I go to \"Admin/ContentTypes/Create\"");
+#line hidden
+ TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] {
+ "name",
+ "value"});
+ table4.AddRow(new string[] {
+ "DisplayName",
+ "Dinner"});
+ table4.AddRow(new string[] {
+ "Name",
+ "Dinner"});
+#line 44
+testRunner.And("I fill in", ((string)(null)), table4);
+#line 48
+testRunner.And("I hit \"Create\"");
+#line 49
+testRunner.And("I go to \"Admin/ContentTypes/\"");
+#line 50
+testRunner.Then("I should see \"Dinner\"");
+#line 51
+testRunner.When("I go to \"Admin/ContentTypes/Create\"");
+#line hidden
+ TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] {
+ "name",
+ "value"});
+ table5.AddRow(new string[] {
+ "DisplayName",
+ "Dinner2"});
+ table5.AddRow(new string[] {
+ "Name",
+ "Dinner"});
+#line 52
+testRunner.And("I fill in", ((string)(null)), table5);
+#line 56
+testRunner.And("I hit \"Create\"");
+#line 57
+testRunner.Then("I should see \"
]*>.*?New Content Type.*?
\"");
+#line 58
+testRunner.And("I should see \"validation-summary-errors\"");
+#line hidden
+ testRunner.CollectScenarioErrors();
+ }
+
+ [NUnit.Framework.TestAttribute()]
+ [NUnit.Framework.DescriptionAttribute("I can\'t rename a content type with an already existing name")]
+ public virtual void ICanTRenameAContentTypeWithAnAlreadyExistingName()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can\'t rename a content type with an already existing name", ((string[])(null)));
+#line 60
+this.ScenarioSetup(scenarioInfo);
+#line 61
+testRunner.Given("I have installed Orchard");
+#line 62
+testRunner.And("I have installed \"Orchard.ContentTypes\"");
+#line 63
+testRunner.When("I go to \"Admin/ContentTypes/Create\"");
+#line hidden
+ TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] {
+ "name",
+ "value"});
+ table6.AddRow(new string[] {
+ "DisplayName",
+ "Dinner"});
+ table6.AddRow(new string[] {
+ "Name",
+ "Dinner"});
+#line 64
+testRunner.And("I fill in", ((string)(null)), table6);
+#line 68
+testRunner.And("I hit \"Create\"");
+#line 69
+testRunner.And("I go to \"Admin/ContentTypes/\"");
+#line 70
+testRunner.Then("I should see \"Dinner\"");
+#line 71
+testRunner.When("I go to \"Admin/ContentTypes/Create\"");
+#line hidden
+ TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] {
+ "name",
+ "value"});
+ table7.AddRow(new string[] {
+ "DisplayName",
+ "Event"});
+ table7.AddRow(new string[] {
+ "Name",
+ "Event"});
+#line 72
+testRunner.And("I fill in", ((string)(null)), table7);
+#line 76
+testRunner.And("I hit \"Create\"");
+#line 77
+testRunner.And("I go to \"Admin/ContentTypes/\"");
+#line 78
+testRunner.Then("I should see \"Event\"");
+#line 79
+testRunner.When("I go to \"Admin/ContentTypes/Edit/Dinner\"");
+#line hidden
+ TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] {
+ "name",
+ "value"});
+ table8.AddRow(new string[] {
+ "DisplayName",
+ "Event"});
+#line 80
+testRunner.And("I fill in", ((string)(null)), table8);
+#line 83
+testRunner.And("I hit \"Save\"");
+#line 84
+testRunner.Then("I should see \"validation-summary-errors\"");
+#line hidden
+ testRunner.CollectScenarioErrors();
+ }
+ }
+}
+#endregion
diff --git a/src/Orchard.Specs/Orchard.Specs.csproj b/src/Orchard.Specs/Orchard.Specs.csproj
index 748a34584..ef1f40764 100644
--- a/src/Orchard.Specs/Orchard.Specs.csproj
+++ b/src/Orchard.Specs/Orchard.Specs.csproj
@@ -142,6 +142,11 @@
TrueTrue
+
+ ContentTypes.feature
+ True
+ True
+ SiteCompilation.feature
@@ -228,6 +233,10 @@
SpecFlowSingleFileGeneratorContentRights.feature.cs
+
+ SpecFlowSingleFileGenerator
+ ContentTypes.feature.cs
+ SpecFlowSingleFileGeneratorSiteCompilation.feature.cs
diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs
index f4d408d2e..61cc18316 100644
--- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs
+++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs
@@ -47,8 +47,12 @@ namespace Orchard.ContentTypes.Controllers {
if(String.IsNullOrWhiteSpace(viewModel.DisplayName)) {
ModelState.AddModelError("DisplayName", T("The Content Type name can't be empty.").ToString());
}
+
+ if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.Name.Trim(), viewModel.Name.Trim(), StringComparison.OrdinalIgnoreCase)) ) {
+ ModelState.AddModelError("Name", T("A type with the same technical name already exists.").ToString());
+ }
- if(_contentDefinitionService.GetTypes().Any(t => t.DisplayName == viewModel.DisplayName)) {
+ if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), viewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase)) ) {
ModelState.AddModelError("DisplayName", T("A type with the same name already exists.").ToString());
}
@@ -57,13 +61,19 @@ namespace Orchard.ContentTypes.Controllers {
return View(viewModel);
}
- var typeViewModel = _contentDefinitionService.AddType(viewModel);
+ var contentTypeDefinition = _contentDefinitionService.AddType(viewModel.Name, viewModel.DisplayName);
+ var typeViewModel = new EditTypeViewModel(contentTypeDefinition);
+
Services.Notifier.Information(T("The \"{0}\" content type has been created.", typeViewModel.DisplayName));
return RedirectToAction("Edit", new { id = typeViewModel.Name });
}
+ public ActionResult ContentTypeName(string displayName) {
+ return Json(_contentDefinitionService.GenerateName(displayName));
+ }
+
public ActionResult Edit(string id) {
if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a content type.")))
return new HttpUnauthorizedResult();
@@ -90,9 +100,18 @@ namespace Orchard.ContentTypes.Controllers {
TryUpdateModel(edited);
typeViewModel.DisplayName = edited.DisplayName;
+ if ( String.IsNullOrWhiteSpace(typeViewModel.DisplayName) ) {
+ ModelState.AddModelError("DisplayName", T("The Content Type name can't be empty.").ToString());
+ }
+
+ if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), typeViewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase) && !String.Equals(t.Name, id)) ) {
+ ModelState.AddModelError("DisplayName", T("A type with the same name already exists.").ToString());
+ }
+
if (!ModelState.IsValid)
return View(typeViewModel);
+
_contentDefinitionService.AlterType(typeViewModel, this);
if (!ModelState.IsValid) {
diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs
index 9c3d936af..de42386e3 100644
--- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs
+++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs
@@ -65,18 +65,24 @@ namespace Orchard.ContentTypes.Services {
return viewModel;
}
- public EditTypeViewModel AddType(CreateTypeViewModel typeViewModel) {
- var name = GenerateName(typeViewModel.DisplayName);
+ public ContentTypeDefinition AddType(string name, string displayName) {
+ if(String.IsNullOrWhiteSpace(displayName)) {
+ throw new ArgumentException("displayName");
+ }
- while (_contentDefinitionManager.GetTypeDefinition(name) != null)
+ if(String.IsNullOrWhiteSpace(name)) {
+ name = GenerateName(displayName);
+ }
+
+ while ( _contentDefinitionManager.GetTypeDefinition(name) != null )
name = VersionName(name);
- var contentTypeDefinition = new ContentTypeDefinition(name, typeViewModel.DisplayName);
+ var contentTypeDefinition = new ContentTypeDefinition(name, displayName);
_contentDefinitionManager.StoreTypeDefinition(contentTypeDefinition);
_contentDefinitionManager.AlterTypeDefinition(name,
cfg => cfg.Creatable().Draftable());
- return new EditTypeViewModel(contentTypeDefinition);
+ return contentTypeDefinition;
}
public void AlterType(EditTypeViewModel typeViewModel, IUpdateModel updateModel) {
@@ -210,20 +216,21 @@ namespace Orchard.ContentTypes.Services {
}
//gratuitously stolen from the RoutableService
- private static string GenerateName(string displayName) {
- if (string.IsNullOrWhiteSpace(displayName))
- return "";
+ public string GenerateName(string name) {
+ if ( string.IsNullOrWhiteSpace(name) )
+ return String.Empty;
- var name = displayName;
- //todo: might need to be made more restrictive depending on how name is used (like as an XML node name, for instance)
- var dissallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s]+");
+ var dissallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s\""<>]+");
- name = dissallowed.Replace(name, "-");
- name = name.Trim('-');
+ name = dissallowed.Replace(name, String.Empty);
+ name = name.Trim();
if (name.Length > 128)
name = name.Substring(0, 128);
+ while ( _contentDefinitionManager.GetTypeDefinition(name) != null )
+ name = VersionName(name);
+
return name;
}
diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/IContentDefinitionService.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/IContentDefinitionService.cs
index 70c59e4a7..44fc6b8ae 100644
--- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/IContentDefinitionService.cs
+++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/IContentDefinitionService.cs
@@ -1,17 +1,19 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
+using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentTypes.ViewModels;
namespace Orchard.ContentTypes.Services {
public interface IContentDefinitionService : IDependency {
IEnumerable GetTypes();
EditTypeViewModel GetType(string name);
- EditTypeViewModel AddType(CreateTypeViewModel typeViewModel);
+ ContentTypeDefinition AddType(string name, string displayName);
void AlterType(EditTypeViewModel typeViewModel, IUpdateModel updater);
void RemoveType(string name);
void AddPartToType(string partName, string typeName);
void RemovePartFromType(string partName, string typeName);
+ string GenerateName(string displayName);
IEnumerable GetParts();
EditPartViewModel GetPart(string name);
diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/ViewModels/CreateTypeViewModel.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/ViewModels/CreateTypeViewModel.cs
index 29a57e6e6..a53768699 100644
--- a/src/Orchard.Web/Modules/Orchard.ContentTypes/ViewModels/CreateTypeViewModel.cs
+++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/ViewModels/CreateTypeViewModel.cs
@@ -1,5 +1,6 @@
namespace Orchard.ContentTypes.ViewModels {
public class CreateTypeViewModel {
public string DisplayName { get; set; }
+ public string Name { get; set; }
}
}
diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Create.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Create.cshtml
index fe3758232..847f21fa9 100644
--- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Create.cshtml
+++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Create.cshtml
@@ -1,10 +1,40 @@
@model Orchard.ContentTypes.ViewModels.CreateTypeViewModel
+
@Html.TextBoxFor(m => m.DisplayName, new {@class = "textMedium", autofocus = "autofocus"})
+
+ @Html.TextBoxFor(m => m.Name, new {@class = "text"})
-
}
\ No newline at end of file
+ }
+
+@using(Script.Foot()){
+
+}
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml
index 22520e69c..7e50efb4b 100644
--- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml
+++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml
@@ -12,7 +12,7 @@
@Html.ValidationSummary()
- @Html.TextBoxFor(m => m.DisplayName, new { @class = "textMedium" })
+ @Html.TextBoxFor(m => m.DisplayName, new { @class = "textMedium" }) @T("Technical name: {0}", Model.Name)
@* todo: if we continue to go down the midrodata route, some helpers would be nice *@
@* has unintended consequences (renamging the type) - changing the name creates a new type of that name *@