Merge updating default to dev for download convenience
@@ -89,6 +89,7 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Roles\Controllers\AdminControllerTests.cs" />
|
||||
<Compile Include="Roles\Services\RoleServiceTests.cs" />
|
||||
<Compile Include="Setup\SetupControllerTests.cs" />
|
||||
<Compile Include="Values.cs" />
|
||||
<Compile Include="Users\Controllers\AdminControllerTests.cs" />
|
||||
<Compile Include="Users\Services\MembershipServiceTests.cs" />
|
||||
@@ -113,6 +114,10 @@
|
||||
<Project>{D10AD48F-407D-4DB5-A328-173EC7CB010F}</Project>
|
||||
<Name>Orchard.Roles</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Web\Modules\Orchard.Setup\Orchard.Setup.csproj">
|
||||
<Project>{8C7FCBC2-E6E1-405E-BFB5-D8D9E67A09C4}</Project>
|
||||
<Name>Orchard.Setup</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Web\Modules\Orchard.Users\Orchard.Users.csproj">
|
||||
<Project>{79AED36E-ABD0-4747-93D3-8722B042454B}</Project>
|
||||
<Name>Orchard.Users</Name>
|
||||
|
||||
110
src/Orchard.Tests.Modules/Setup/SetupControllerTests.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Autofac;
|
||||
using Autofac.Builder;
|
||||
using JetBrains.Annotations;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Data.Builders;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Setup.Controllers;
|
||||
using Orchard.Setup.ViewModels;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace Orchard.Tests.Modules.Setup {
|
||||
[TestFixture, Ignore("this can't be made to work")]
|
||||
public class SetupControllerTests {
|
||||
private string _tempFolder;
|
||||
private IContainer _container;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
_tempFolder = Path.GetTempFileName();
|
||||
File.Delete(_tempFolder);
|
||||
Directory.CreateDirectory(_tempFolder);
|
||||
|
||||
var hostContainer = OrchardStarter.CreateHostContainer(builder => {
|
||||
builder.Register(new ControllerBuilder());
|
||||
builder.Register(new ViewEngineCollection { new WebFormViewEngine() });
|
||||
builder.Register(new RouteCollection());
|
||||
builder.Register(new ModelBinderDictionary());
|
||||
});
|
||||
|
||||
hostContainer.Resolve<IAppDataFolder>().SetBasePath(_tempFolder);
|
||||
|
||||
var host = (DefaultOrchardHost)hostContainer.Resolve<IOrchardHost>();
|
||||
_container = host.CreateShellContainer();
|
||||
_container.Build(builder => {
|
||||
builder.Register<SetupController>();
|
||||
});
|
||||
|
||||
|
||||
//var builder = new ContainerBuilder();
|
||||
//builder.Register<SetupController>();
|
||||
//builder.Register<Notifier>().As<INotifier>();
|
||||
//builder.Register<DefaultOrchardHost>().As<IOrchardHost>();
|
||||
//builder.Register<DatabaseMigrationManager>().As<IDatabaseMigrationManager>();
|
||||
//builder.Register<ShellSettingsLoader>().As<IShellSettingsLoader>();
|
||||
//builder.Register<TestAppDataFolder>().As<IAppDataFolder>();
|
||||
//_container = builder.Build();
|
||||
}
|
||||
|
||||
private string GetMessages() {
|
||||
var notifier = _container.Resolve<INotifier>();
|
||||
return notifier.List().Aggregate("", (a, b) => a + b.Message.ToString());
|
||||
}
|
||||
|
||||
private SetupViewModel GetTestSetupModel() {
|
||||
return new SetupViewModel {
|
||||
AdminUsername = "test1",
|
||||
AdminPassword = "test2",
|
||||
DatabaseOptions = true,
|
||||
SiteName = "test3"
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IndexNormallyReturnsWithDefaultAdminUsername() {
|
||||
var controller = _container.Resolve<SetupController>();
|
||||
var result = controller.Index(null);
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.TypeOf<ViewResult>());
|
||||
|
||||
var viewResult = (ViewResult)result;
|
||||
Assert.That(viewResult.ViewData.Model, Is.TypeOf<SetupViewModel>());
|
||||
|
||||
var model2 = (SetupViewModel)viewResult.ViewData.Model;
|
||||
Assert.That(model2.AdminUsername, Is.EqualTo("admin"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetupShouldCreateShellSettingsFile() {
|
||||
var model = GetTestSetupModel();
|
||||
var controller = _container.Resolve<SetupController>();
|
||||
var result = controller.IndexPOST(model);
|
||||
|
||||
Assert.That(GetMessages(), Is.StringContaining("Setup succeeded"));
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.TypeOf<RedirectResult>());
|
||||
Assert.That(File.Exists(Path.Combine(_tempFolder, "Sites\\default.txt")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuiltinDatabaseShouldCreateSQLiteFile() {
|
||||
var model = GetTestSetupModel();
|
||||
var controller = _container.Resolve<SetupController>();
|
||||
var result = controller.IndexPOST(model);
|
||||
|
||||
Assert.That(GetMessages(), Is.StringContaining("Setup succeeded"));
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.TypeOf<RedirectResult>());
|
||||
Assert.That(File.Exists(Path.Combine(_tempFolder, "Sites\\default\\orchard.db")));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
105
src/Orchard.Tests/Data/Builders/SessionFactoryBuilderTests.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System.Data.SqlClient;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Data.Builders;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Tests.Records;
|
||||
|
||||
namespace Orchard.Tests.Data.Builders {
|
||||
[TestFixture]
|
||||
public class SessionFactoryBuilderTests {
|
||||
private string _tempDataFolder;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var tempFilePath = Path.GetTempFileName();
|
||||
File.Delete(tempFilePath);
|
||||
Directory.CreateDirectory(tempFilePath);
|
||||
_tempDataFolder = tempFilePath;
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Term() {
|
||||
try { Directory.Delete(_tempDataFolder, true); }
|
||||
catch (IOException) { }
|
||||
}
|
||||
|
||||
private static void CreateSqlServerDatabase(string databasePath) {
|
||||
var databaseName = Path.GetFileNameWithoutExtension(databasePath);
|
||||
using (var connection = new SqlConnection(
|
||||
"Data Source=.\\SQLEXPRESS;Initial Catalog=tempdb;Integrated Security=true;User Instance=True;")) {
|
||||
connection.Open();
|
||||
using (var command = connection.CreateCommand()) {
|
||||
command.CommandText =
|
||||
"CREATE DATABASE " + databaseName +
|
||||
" ON PRIMARY (NAME=" + databaseName +
|
||||
", FILENAME='" + databasePath.Replace("'", "''") + "')";
|
||||
command.ExecuteNonQuery();
|
||||
|
||||
command.CommandText =
|
||||
"EXEC sp_detach_db '" + databaseName + "', 'true'";
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public void SQLiteSchemaShouldBeGeneratedAndUsable() {
|
||||
var recordDescriptors = new[] {
|
||||
new RecordDescriptor {Prefix = "Hello", Type = typeof (Foo)}
|
||||
};
|
||||
var manager = (ISessionFactoryBuilder)new SessionFactoryBuilder();
|
||||
var sessionFactory = manager.BuildSessionFactory(new SessionFactoryParameters {
|
||||
Provider = "SQLite",
|
||||
DataFolder = _tempDataFolder,
|
||||
UpdateSchema = true,
|
||||
RecordDescriptors = recordDescriptors
|
||||
});
|
||||
|
||||
|
||||
var session = sessionFactory.OpenSession();
|
||||
var foo = new Foo { Name = "hi there" };
|
||||
session.Save(foo);
|
||||
session.Flush();
|
||||
session.Close();
|
||||
|
||||
Assert.That(foo, Is.Not.EqualTo(0));
|
||||
|
||||
sessionFactory.Close();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SqlServerSchemaShouldBeGeneratedAndUsable() {
|
||||
var databasePath = Path.Combine(_tempDataFolder, "Orchard.mdf");
|
||||
CreateSqlServerDatabase(databasePath);
|
||||
|
||||
var recordDescriptors = new[] {
|
||||
new RecordDescriptor {Prefix = "Hello", Type = typeof (Foo)}
|
||||
};
|
||||
|
||||
var manager = (ISessionFactoryBuilder)new SessionFactoryBuilder();
|
||||
var sessionFactory = manager.BuildSessionFactory(new SessionFactoryParameters {
|
||||
Provider = "SQLite",
|
||||
DataFolder = _tempDataFolder,
|
||||
ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;",
|
||||
UpdateSchema = true,
|
||||
RecordDescriptors = recordDescriptors,
|
||||
});
|
||||
|
||||
|
||||
|
||||
var session = sessionFactory.OpenSession();
|
||||
var foo = new Foo { Name = "hi there" };
|
||||
session.Save(foo);
|
||||
session.Flush();
|
||||
session.Close();
|
||||
|
||||
Assert.That(foo, Is.Not.EqualTo(0));
|
||||
|
||||
sessionFactory.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Data.Migrations;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Tests.Records;
|
||||
|
||||
namespace Orchard.Tests.Data.Migrations {
|
||||
[TestFixture]
|
||||
public class DatabaseMigrationManagerTests {
|
||||
private string _tempDataFolder;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var tempFilePath = Path.GetTempFileName();
|
||||
File.Delete(tempFilePath);
|
||||
Directory.CreateDirectory(tempFilePath);
|
||||
_tempDataFolder = tempFilePath;
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Term() {
|
||||
try { Directory.Delete(_tempDataFolder, true); }
|
||||
catch (IOException) { }
|
||||
}
|
||||
|
||||
private static void CreateSqlServerDatabase(string databasePath) {
|
||||
var databaseName = Path.GetFileNameWithoutExtension(databasePath);
|
||||
using (var connection = new SqlConnection(
|
||||
"Data Source=.\\SQLEXPRESS;Initial Catalog=tempdb;Integrated Security=true;User Instance=True;")) {
|
||||
connection.Open();
|
||||
using (var command = connection.CreateCommand()) {
|
||||
command.CommandText =
|
||||
"CREATE DATABASE " + databaseName +
|
||||
" ON PRIMARY (NAME=" + databaseName +
|
||||
", FILENAME='" + databasePath.Replace("'", "''") + "')";
|
||||
command.ExecuteNonQuery();
|
||||
|
||||
command.CommandText =
|
||||
"EXEC sp_detach_db '" + databaseName + "', 'true'";
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MigrationManagerShouldCreateEmptySQLiteDatabaseAtGivenLocation() {
|
||||
var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager();
|
||||
var coordinator = manager.CreateCoordinator("SQLite", _tempDataFolder, "");
|
||||
|
||||
coordinator.CreateDatabase();
|
||||
|
||||
Assert.That(File.Exists(Path.Combine(_tempDataFolder, "Orchard.db")), Is.True);
|
||||
}
|
||||
|
||||
[Test, ExpectedException(typeof(NotImplementedException))]
|
||||
public void MigrationManagerShouldNotImplementTheCreationOfSqlServer() {
|
||||
var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager();
|
||||
var coordinator = manager.CreateCoordinator("SqlServer", _tempDataFolder, "");
|
||||
|
||||
coordinator.CreateDatabase();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanConnectShouldBeFalseWhenSqlServerIsInvalid() {
|
||||
var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager();
|
||||
var coordinator = manager.CreateCoordinator("SqlServer", _tempDataFolder, "Data Source=.\\SQLEXPRESS;Initial Catalog=Hello");
|
||||
Assert.That(coordinator.CanConnect(), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanConnectShouldBeTrueWhenValidSqlServerMdfIsTargetted() {
|
||||
var databasePath = Path.Combine(_tempDataFolder, "Orchard.mdf");
|
||||
CreateSqlServerDatabase(databasePath);
|
||||
|
||||
var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager();
|
||||
var coordinator = manager.CreateCoordinator("SqlServer", _tempDataFolder, "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;");
|
||||
Assert.That(coordinator.CanConnect(), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SQLiteSchemaShouldBeGeneratedAndUsable() {
|
||||
var manager = (IDatabaseMigrationManager) new DatabaseMigrationManager();
|
||||
var coordinator = manager.CreateCoordinator("SQLite", _tempDataFolder, "");
|
||||
|
||||
var recordDescriptors = new[] {
|
||||
new RecordDescriptor {Prefix = "Hello", Type = typeof (Foo)}
|
||||
};
|
||||
|
||||
coordinator.UpdateSchema(recordDescriptors);
|
||||
|
||||
var sessionFactory = coordinator.BuildSessionFactory(recordDescriptors);
|
||||
|
||||
var session = sessionFactory.OpenSession();
|
||||
var foo = new Foo {Name = "hi there"};
|
||||
session.Save(foo);
|
||||
session.Flush();
|
||||
session.Close();
|
||||
|
||||
Assert.That(foo, Is.Not.EqualTo(0));
|
||||
|
||||
sessionFactory.Close();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SqlServerSchemaShouldBeGeneratedAndUsable() {
|
||||
var databasePath = Path.Combine(_tempDataFolder, "Orchard.mdf");
|
||||
CreateSqlServerDatabase(databasePath);
|
||||
|
||||
var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager();
|
||||
var coordinator = manager.CreateCoordinator("SqlServer", _tempDataFolder, "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;");
|
||||
|
||||
var recordDescriptors = new[] {
|
||||
new RecordDescriptor {Prefix = "Hello", Type = typeof (Foo)}
|
||||
};
|
||||
|
||||
coordinator.UpdateSchema(recordDescriptors);
|
||||
|
||||
var sessionFactory = coordinator.BuildSessionFactory(recordDescriptors);
|
||||
|
||||
var session = sessionFactory.OpenSession();
|
||||
var foo = new Foo { Name = "hi there" };
|
||||
session.Save(foo);
|
||||
session.Flush();
|
||||
session.Close();
|
||||
|
||||
Assert.That(foo, Is.Not.EqualTo(0));
|
||||
|
||||
sessionFactory.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ using FluentNHibernate.Cfg.Db;
|
||||
using NHibernate;
|
||||
using NHibernate.Tool.hbm2ddl;
|
||||
using Orchard.Data;
|
||||
using Orchard.Data.Builders;
|
||||
using Orchard.Environment;
|
||||
|
||||
namespace Orchard.Tests {
|
||||
@@ -18,7 +19,7 @@ namespace Orchard.Tests {
|
||||
//var persistenceModel = AutoMap.Source(new Types(types))
|
||||
// .Alterations(alt => AddAlterations(alt, types))
|
||||
// .Conventions.AddFromAssemblyOf<DataModule>();
|
||||
var persistenceModel = HackSessionLocator.CreatePersistenceModel(types.Select(t => new RecordDescriptor { Prefix = "Test", Type = t }));
|
||||
var persistenceModel = AbstractBuilder.CreatePersistenceModel(types.Select(t => new RecordDescriptor { Prefix = "Test", Type = t }));
|
||||
|
||||
return Fluently.Configure()
|
||||
.Database(SQLiteConfiguration.Standard.UsingFile(fileName).ShowSql())
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Environment.Configuration;
|
||||
|
||||
namespace Orchard.Tests.Environment.Configuration {
|
||||
[TestFixture]
|
||||
public class AppDataFolderTests {
|
||||
private string _tempFolder;
|
||||
private IAppDataFolder _appDataFolder;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
_tempFolder = Path.GetTempFileName();
|
||||
File.Delete(_tempFolder);
|
||||
Directory.CreateDirectory(Path.Combine(_tempFolder, "alpha"));
|
||||
File.WriteAllText(Path.Combine(_tempFolder, "alpha\\beta.txt"), "beta-content");
|
||||
File.WriteAllText(Path.Combine(_tempFolder, "alpha\\gamma.txt"), "gamma-content");
|
||||
Directory.CreateDirectory(Path.Combine(_tempFolder, "alpha\\omega"));
|
||||
|
||||
_appDataFolder = new AppDataFolder();
|
||||
_appDataFolder.SetBasePath(_tempFolder);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Term() {
|
||||
Directory.Delete(_tempFolder, true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ListFilesShouldContainSubPathAndFileName() {
|
||||
var files = _appDataFolder.ListFiles("alpha");
|
||||
Assert.That(files.Count(), Is.EqualTo(2));
|
||||
Assert.That(files, Has.Some.EqualTo("alpha\\beta.txt"));
|
||||
Assert.That(files, Has.Some.EqualTo("alpha\\gamma.txt"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NonExistantFolderShouldListAsEmptyCollection() {
|
||||
var files = _appDataFolder.ListFiles("delta");
|
||||
Assert.That(files.Count(), Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PhysicalPathAddsToBasePathAndDoesNotNeedToExist() {
|
||||
var physicalPath = _appDataFolder.MapPath("delta\\epsilon.txt");
|
||||
Assert.That(physicalPath, Is.EqualTo(Path.Combine(_tempFolder, "delta\\epsilon.txt")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ListSubdirectoriesShouldContainFullSubpath() {
|
||||
var files = _appDataFolder.ListDirectories("alpha");
|
||||
Assert.That(files.Count(), Is.EqualTo(1));
|
||||
Assert.That(files, Has.Some.EqualTo("alpha\\omega"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ListSubdirectoriesShouldWorkInRoot() {
|
||||
var files = _appDataFolder.ListDirectories("");
|
||||
Assert.That(files.Count(), Is.EqualTo(1));
|
||||
Assert.That(files, Has.Some.EqualTo("alpha"));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void NonExistantFolderShouldListDirectoriesAsEmptyCollection() {
|
||||
var files = _appDataFolder.ListDirectories("delta");
|
||||
Assert.That(files.Count(), Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateFileWillCauseDirectoryToBeCreated() {
|
||||
Assert.That(Directory.Exists(Path.Combine(_tempFolder, "alpha\\omega\\foo")), Is.False);
|
||||
_appDataFolder.CreateFile("alpha\\omega\\foo\\bar.txt", "quux");
|
||||
Assert.That(Directory.Exists(Path.Combine(_tempFolder, "alpha\\omega\\foo")), Is.True);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Test, Ignore("Can't be made to work until module settings and infrastructres implemented")]
|
||||
public void FactoryShouldCreateContainerThatProvidesShell() {
|
||||
|
||||
var factory = new SafeModeShellContainerFactory(_hostContainer);
|
||||
@@ -33,7 +33,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
Assert.That(shell, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Test, Ignore("Can't be made to work until module settings and infrastructres implemented")]
|
||||
public void ShellContainerShouldProvideLayoutViewEngine() {
|
||||
var factory = new SafeModeShellContainerFactory(_hostContainer);
|
||||
var shellContainer = factory.CreateContainer(null);
|
||||
|
||||
@@ -135,9 +135,10 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="DataUtility.cs" />
|
||||
<Compile Include="Data\Migrations\DatabaseMigrationManagerTests.cs" />
|
||||
<Compile Include="Data\Builders\SessionFactoryBuilderTests.cs" />
|
||||
<Compile Include="Data\RepositoryTests.cs" />
|
||||
<Compile Include="Data\StubLocator.cs" />
|
||||
<Compile Include="Environment\Configuration\AppDataFolderTests.cs" />
|
||||
<Compile Include="Environment\DefaultCompositionStrategyTests.cs" />
|
||||
<Compile Include="Environment\DefaultOrchardHostTests.cs" />
|
||||
<Compile Include="Environment\DefaultOrchardShellTests.cs" />
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using NUnit.Framework;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
using Orchard.Tests.Stubs;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.Tests.UI.Navigation {
|
||||
@@ -13,7 +13,7 @@ namespace Orchard.Tests.UI.Navigation {
|
||||
public class NavigationManagerTests {
|
||||
[Test]
|
||||
public void EmptyMenuIfNameDoesntMatch() {
|
||||
var manager = new NavigationManager(new[] { new StubProvider() }, new StubAuth());
|
||||
var manager = new NavigationManager(new[] { new StubProvider() }, new StubAuth(), new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())));
|
||||
|
||||
var menuItems = manager.BuildMenu("primary");
|
||||
Assert.That(menuItems.Count(), Is.EqualTo(0));
|
||||
@@ -30,7 +30,7 @@ namespace Orchard.Tests.UI.Navigation {
|
||||
|
||||
[Test]
|
||||
public void NavigationManagerShouldUseProvidersToBuildNamedMenu() {
|
||||
var manager = new NavigationManager(new[] { new StubProvider() }, new StubAuth());
|
||||
var manager = new NavigationManager(new[] { new StubProvider() }, new StubAuth(), new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())));
|
||||
|
||||
var menuItems = manager.BuildMenu("admin");
|
||||
Assert.That(menuItems.Count(), Is.EqualTo(2));
|
||||
@@ -42,7 +42,7 @@ namespace Orchard.Tests.UI.Navigation {
|
||||
|
||||
[Test]
|
||||
public void NavigationManagerShouldMergeAndOrderNavigation() {
|
||||
var manager = new NavigationManager(new INavigationProvider[] { new StubProvider(), new Stub2Provider() }, new StubAuth());
|
||||
var manager = new NavigationManager(new INavigationProvider[] { new StubProvider(), new Stub2Provider() }, new StubAuth(), new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData())));
|
||||
|
||||
var menuItems = manager.BuildMenu("admin");
|
||||
Assert.That(menuItems.Count(), Is.EqualTo(3));
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
<add name="WebPageTrace"/>
|
||||
</listeners>
|
||||
</source>
|
||||
<source name="Orchard.Data.SessionLocator" switchValue="Information">
|
||||
<listeners>
|
||||
<add name="OrchardDebugTextLog" />
|
||||
<add name="WebPageTrace"/>
|
||||
</listeners>
|
||||
</source>
|
||||
</sources>
|
||||
<sharedListeners>
|
||||
<add name="OrchardDebugTextLog" type="System.Diagnostics.TextWriterTraceListener" initializeData="c:\logs\orchard-debug.txt" />
|
||||
|
||||
57
src/Orchard.Web/Core/HomePage/Controllers/HomeController.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
using Orchard.Services;
|
||||
using Orchard.Settings;
|
||||
|
||||
namespace Orchard.Core.HomePage.Controllers {
|
||||
[HandleError]
|
||||
public class HomeController : Controller {
|
||||
private readonly IEnumerable<IHomePageProvider> _homePageProviders;
|
||||
|
||||
public HomeController(IEnumerable<IHomePageProvider> homePageProviders) {
|
||||
_homePageProviders = homePageProviders;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
|
||||
|
||||
public ActionResult Index() {
|
||||
try {
|
||||
string homepage = CurrentSite.HomePage;
|
||||
if (String.IsNullOrEmpty(homepage)) {
|
||||
return View(new BaseViewModel());
|
||||
}
|
||||
|
||||
string[] homePageParameters = homepage.Split(';');
|
||||
if (homePageParameters.Length != 2) {
|
||||
return View(new BaseViewModel());
|
||||
}
|
||||
string providerName = homePageParameters[0];
|
||||
int item = Int32.Parse(homePageParameters[1]);
|
||||
|
||||
foreach (var provider in _homePageProviders) {
|
||||
if (String.Equals(provider.GetProviderName(), providerName)) {
|
||||
ActionResult result = provider.GetHomePage(item);
|
||||
if (result is ViewResultBase) {
|
||||
ViewResultBase resultBase = result as ViewResultBase;
|
||||
ViewData.Model = resultBase.ViewData.Model;
|
||||
resultBase.ViewData = ViewData;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return View(new BaseViewModel());
|
||||
}
|
||||
catch {
|
||||
return View(new BaseViewModel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1
src/Orchard.Web/Core/HomePage/Module.txt
Normal file
@@ -0,0 +1 @@
|
||||
name: HomePage
|
||||
36
src/Orchard.Web/Core/HomePage/Routes.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Orchard.Mvc.Routes;
|
||||
|
||||
namespace Orchard.Core.HomePage {
|
||||
public class Routes : IRouteProvider {
|
||||
public void GetRoutes(ICollection<RouteDescriptor> routes) {
|
||||
foreach (var routeDescriptor in GetRoutes())
|
||||
routes.Add(routeDescriptor);
|
||||
}
|
||||
|
||||
public IEnumerable<RouteDescriptor> GetRoutes() {
|
||||
return new[] {
|
||||
new RouteDescriptor {
|
||||
Priority = 20,
|
||||
Route = new Route(
|
||||
"",
|
||||
new RouteValueDictionary {
|
||||
{"area", "HomePage"},
|
||||
{"controller", "Home"},
|
||||
{"action", "Index"}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"area", "HomePage"},
|
||||
{"controller", "Home"},
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"area", "HomePage"}
|
||||
},
|
||||
new MvcRouteHandler())
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ namespace Orchard.Core.Navigation {
|
||||
public string MenuName { get { return "admin"; } }
|
||||
|
||||
public void GetNavigation(NavigationBuilder builder) {
|
||||
builder.Add("Navigation", "12",
|
||||
builder.Add("Site", "12",
|
||||
menu => menu
|
||||
.Add("Manage Main Menu", "2.0", item => item.Action("Index", "Admin", new { area = "Navigation" }).Permission(Permissions.ManageMainMenu)));
|
||||
.Add("Manage Main Menu", "6.0", item => item.Action("Index", "Admin", new { area = "Navigation" }).Permission(Permissions.ManageMainMenu)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,125 @@
|
||||
using System.Web.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Navigation.Drivers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Core.Navigation.Services;
|
||||
using Orchard.Core.Navigation.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.Attributes;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.Utility;
|
||||
using MenuItem=Orchard.Core.Navigation.Models.MenuItem;
|
||||
|
||||
namespace Orchard.Core.Navigation.Controllers {
|
||||
[ValidateInput(false)]
|
||||
public class AdminController : Controller {
|
||||
public IOrchardServices Services { get; private set; }
|
||||
public class AdminController : Controller, IUpdateModel {
|
||||
private readonly IMenuService _menuService;
|
||||
private readonly IOrchardServices _services;
|
||||
private readonly INavigationManager _navigationManager;
|
||||
|
||||
public AdminController(IOrchardServices services) {
|
||||
Services = services;
|
||||
public AdminController(IMenuService menuService, IOrchardServices services, INavigationManager navigationManager) {
|
||||
_menuService = menuService;
|
||||
_services = services;
|
||||
_navigationManager = navigationManager;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
private Localizer T { get; set; }
|
||||
|
||||
public ActionResult Index() {
|
||||
return View(new NavigationIndexViewModel());
|
||||
public ActionResult Index(NavigationManagementViewModel model) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Not allowed to manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
if (model == null)
|
||||
model = new NavigationManagementViewModel();
|
||||
|
||||
if (model.MenuItemEntries == null || model.MenuItemEntries.Count() < 1)
|
||||
model.MenuItemEntries = _menuService.Get().Select(menuPart => CreateMenuItemEntries(menuPart)).OrderBy(menuPartEntry => menuPartEntry.MenuItem.Position, new PositionComparer()).ToList();
|
||||
|
||||
return View("Index", model);
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("Index")]
|
||||
public ActionResult IndexPOST(IList<MenuItemEntry> menuItemEntries) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
foreach (var menuItemEntry in menuItemEntries) {
|
||||
MenuPart menuPart = _menuService.Get(menuItemEntry.MenuItemId);
|
||||
|
||||
menuPart.MenuText = menuItemEntry.MenuItem.Text;
|
||||
menuPart.MenuPosition = menuItemEntry.MenuItem.Position;
|
||||
if (menuPart.Is<MenuItem>())
|
||||
menuPart.As<MenuItem>().Url = menuItemEntry.MenuItem.Url;
|
||||
|
||||
_services.ContentManager.UpdateEditorModel(menuPart, this);
|
||||
}
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
private MenuItemEntry CreateMenuItemEntries(MenuPart menuPart) {
|
||||
return new MenuItemEntry {
|
||||
MenuItem = new UI.Navigation.MenuItem {
|
||||
Text = menuPart.MenuText,
|
||||
Position = menuPart.MenuPosition,
|
||||
Url = menuPart.Is<MenuItem>()
|
||||
? menuPart.As<MenuItem>().Url
|
||||
: _navigationManager.GetUrl(null, _services.ContentManager.GetItemMetadata(menuPart).DisplayRouteValues)
|
||||
},
|
||||
MenuItemId = menuPart.Id,
|
||||
IsMenuItem = menuPart.Is<MenuItem>()
|
||||
};
|
||||
}
|
||||
|
||||
public ActionResult Create() {
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Create(CreateMenuItemViewModel model) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var menuPart = _services.ContentManager.New<MenuPart>(MenuItemDriver.ContentType.Name);
|
||||
model.MenuItem = _services.ContentManager.UpdateEditorModel(menuPart, this);
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
_services.TransactionManager.Cancel();
|
||||
return Index(new NavigationManagementViewModel {NewMenuItem = model});
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(menuPart.MenuPosition))
|
||||
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu("main"));
|
||||
menuPart.OnMainMenu = true;
|
||||
|
||||
_services.ContentManager.Create(model.MenuItem.Item.ContentItem);
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[ValidateAntiForgeryTokenOrchard]
|
||||
public ActionResult Delete(int id) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
MenuPart menuPart = _menuService.Get(id);
|
||||
|
||||
if (menuPart != null)
|
||||
_menuService.Delete(menuPart);
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
|
||||
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
|
||||
}
|
||||
|
||||
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
|
||||
ModelState.AddModelError(key, errorMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
42
src/Orchard.Web/Core/Navigation/Drivers/MenuItemDriver.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.Core.Navigation.Drivers {
|
||||
[UsedImplicitly]
|
||||
public class MenuItemDriver : ContentItemDriver<MenuItem> {
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
|
||||
public readonly static ContentType ContentType = new ContentType {
|
||||
Name = "menuitem",
|
||||
DisplayName = "Menu Item"
|
||||
};
|
||||
|
||||
public MenuItemDriver(IAuthorizationService authorizationService) {
|
||||
_authorizationService = authorizationService;
|
||||
}
|
||||
|
||||
public virtual IUser CurrentUser { get; set; }
|
||||
|
||||
protected override ContentType GetContentType() {
|
||||
return ContentType;
|
||||
}
|
||||
|
||||
protected override string Prefix { get { return ""; } }
|
||||
|
||||
protected override string GetDisplayText(MenuItem item) {
|
||||
return item.Url;
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(MenuItem item, IUpdateModel updater) {
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, CurrentUser, item))
|
||||
return null;
|
||||
|
||||
updater.TryUpdateModel(item, Prefix, null, null);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,20 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.Utility;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
namespace Orchard.Core.Navigation.Drivers {
|
||||
[UsedImplicitly]
|
||||
public class MenuPartDriver : ContentPartDriver<MenuPart> {
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly INavigationManager _navigationManager;
|
||||
|
||||
public MenuPartDriver(IAuthorizationService authorizationService) {
|
||||
public MenuPartDriver(IAuthorizationService authorizationService, INavigationManager navigationManager) {
|
||||
_authorizationService = authorizationService;
|
||||
_navigationManager = navigationManager;
|
||||
}
|
||||
|
||||
public virtual IUser CurrentUser { get; set; }
|
||||
@@ -25,8 +30,11 @@ namespace Orchard.Core.Navigation.Models {
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, CurrentUser, part))
|
||||
return null;
|
||||
|
||||
if (string.IsNullOrEmpty(part.MenuPosition))
|
||||
part.MenuPosition = Position.GetNext(_navigationManager.BuildMenu("main"));
|
||||
|
||||
updater.TryUpdateModel(part, Prefix, null, null);
|
||||
return ContentPartTemplate(part, "Parts/Navigation.EditMenuPart").Location("primary", "9");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using Orchard.Mvc.Filters;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.Core.Navigation.Services {
|
||||
namespace Orchard.Core.Navigation.Filters {
|
||||
public class MainMenuFilter : FilterProvider, IResultFilter {
|
||||
private readonly INavigationManager _navigationManager;
|
||||
|
||||
@@ -20,11 +20,10 @@ namespace Orchard.Core.Navigation.Services {
|
||||
if (baseViewModel == null)
|
||||
return;
|
||||
|
||||
baseViewModel.Menu = _navigationManager.BuildMenu("mainmenu");
|
||||
baseViewModel.Menu = _navigationManager.BuildMenu("main");
|
||||
}
|
||||
|
||||
public void OnResultExecuted(ResultExecutedContext filterContext) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Orchard.Core.Navigation.Records;
|
||||
using Orchard.Core.Navigation.Drivers;
|
||||
using Orchard.Core.Navigation.Records;
|
||||
using Orchard.Data;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Web.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Navigation.Records;
|
||||
|
||||
@@ -7,6 +8,7 @@ namespace Orchard.Core.Navigation.Models {
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public int Id { get { return ContentItem.Id; } }
|
||||
|
||||
[Required]
|
||||
public string Url {
|
||||
get { return Record.Url; }
|
||||
set { Record.Url = value; }
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
|
||||
namespace Orchard.Core.Navigation.Models {
|
||||
[UsedImplicitly]
|
||||
public class MenuItemDriver : ContentItemDriver<MenuItem> {
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
|
||||
public readonly static ContentType ContentType = new ContentType {
|
||||
Name = "menuitem",
|
||||
DisplayName = "Menu Item"
|
||||
};
|
||||
|
||||
public MenuItemDriver(IOrchardServices orchardServices) {
|
||||
_orchardServices = orchardServices;
|
||||
}
|
||||
|
||||
protected override ContentType GetContentType() {
|
||||
return ContentType;
|
||||
}
|
||||
|
||||
protected override string Prefix { get { return ""; } }
|
||||
|
||||
protected override string GetDisplayText(MenuItem item) {
|
||||
return item.Url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Web.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Navigation.Records;
|
||||
|
||||
@@ -12,12 +13,12 @@ namespace Orchard.Core.Navigation.Models {
|
||||
set { Record.OnMainMenu = value; }
|
||||
}
|
||||
|
||||
[Required]
|
||||
public string MenuText {
|
||||
get { return Record.MenuText; }
|
||||
set { Record.MenuText = value; }
|
||||
}
|
||||
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public string MenuPosition {
|
||||
get { return Record.MenuPosition; }
|
||||
set { Record.MenuPosition = value; }
|
||||
|
||||
@@ -6,14 +6,26 @@ using Orchard.UI.Navigation;
|
||||
using MenuItem=Orchard.Core.Navigation.Models.MenuItem;
|
||||
|
||||
namespace Orchard.Core.Navigation.Services {
|
||||
public class MainMenu : INavigationProvider {
|
||||
public class MainMenu : INavigationProvider, IMenuService {
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public MainMenu(IContentManager contentManager) {
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
public string MenuName { get { return "mainmenu"; } }
|
||||
public string MenuName { get { return "main"; } }
|
||||
|
||||
public IEnumerable<MenuPart> Get() {
|
||||
return _contentManager.Query<MenuPart, MenuPartRecord>().Where(x => x.OnMainMenu).List();
|
||||
}
|
||||
|
||||
public MenuPart Get(int menuPartId) {
|
||||
return _contentManager.Get<MenuPart>(menuPartId);
|
||||
}
|
||||
|
||||
public void Delete(MenuPart menuPart) {
|
||||
_contentManager.Remove(menuPart.ContentItem);
|
||||
}
|
||||
|
||||
public void GetNavigation(NavigationBuilder builder) {
|
||||
IEnumerable<MenuPart> menuParts = _contentManager.Query<MenuPart, MenuPartRecord>().Where(x => x.OnMainMenu).List();
|
||||
@@ -22,21 +34,22 @@ namespace Orchard.Core.Navigation.Services {
|
||||
MenuPart part = menuPart;
|
||||
|
||||
if (part.Is<MenuItem>())
|
||||
builder.Add(menu => menu.Add(part.MenuText, part.MenuPosition, part.As<MenuItem>().Url));
|
||||
builder.Add(
|
||||
menu => menu.Add(part.MenuText, part.MenuPosition, nib => nib.Url(part.As<MenuItem>().Url)));
|
||||
else
|
||||
builder.Add(
|
||||
menu =>
|
||||
menu.Add(part.MenuText, part.MenuPosition,
|
||||
nib =>
|
||||
nib.Action(
|
||||
part.ContentItem.ContentManager.GetItemMetadata(part.ContentItem).
|
||||
DisplayRouteValues["action"] as string,
|
||||
part.ContentItem.ContentManager.GetItemMetadata(part.ContentItem).
|
||||
DisplayRouteValues["controller"] as string,
|
||||
part.ContentItem.ContentManager.GetItemMetadata(part.ContentItem).
|
||||
DisplayRouteValues)));
|
||||
nib.Action(_contentManager.GetItemMetadata(part.ContentItem).DisplayRouteValues)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IMenuService : IDependency {
|
||||
IEnumerable<MenuPart> Get();
|
||||
MenuPart Get(int menuPartId);
|
||||
void Delete(MenuPart menuPart);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class CreateMenuItemViewModel : AdminViewModel {
|
||||
public ContentItemViewModel<MenuPart> MenuItem { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class MenuItemEntry {
|
||||
public MenuItem MenuItem { get; set; }
|
||||
public int MenuItemId { get; set; }
|
||||
public bool IsMenuItem { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
using Orchard.Mvc.ViewModels;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class NavigationIndexViewModel : AdminViewModel {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
|
||||
namespace Orchard.Core.Navigation.ViewModels {
|
||||
public class NavigationManagementViewModel : AdminViewModel {
|
||||
public NavigationManagementViewModel() {
|
||||
MenuItemEntries = Enumerable.Empty<MenuItemEntry>().ToList();
|
||||
}
|
||||
|
||||
public CreateMenuItemViewModel NewMenuItem { get; set; }
|
||||
public IList<MenuItemEntry> MenuItemEntries { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,66 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<NavigationIndexViewModel>" %>
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<NavigationManagementViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.ContentManagement"%>
|
||||
<%@ Import Namespace="Orchard.Core.Navigation.Models"%>
|
||||
<%@ Import Namespace="Orchard.Core.Navigation.ViewModels"%>
|
||||
<h1><%=Html.TitleForPage(T("Edit Main Menu").ToString())%></h1><%
|
||||
<h1><%=Html.TitleForPage(T("Manage Main Menu").ToString())%></h1><%
|
||||
using (Html.BeginFormAntiForgeryPost()) { %>
|
||||
<table>
|
||||
<table class="items">
|
||||
<colgroup>
|
||||
<col id="Text" />
|
||||
<col id="Position" />
|
||||
<col id="Url" />
|
||||
<col id="Actions" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Text</td>
|
||||
<td>Position</td>
|
||||
<td>Url</td>
|
||||
<td></td>
|
||||
<td scope="col"><%=_Encoded("Text") %></td>
|
||||
<td scope="col"><%=_Encoded("Position") %></td>
|
||||
<td scope="col"><%=_Encoded("Url") %></td>
|
||||
<td scope="col"></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%-- loop over menu items --%>
|
||||
<tbody><%
|
||||
var menuPartEntryIndex = 0;
|
||||
foreach (var menuPartEntry in Model.MenuItemEntries) {
|
||||
var i = menuPartEntryIndex; %>
|
||||
<tr>
|
||||
<td><input type="text" name="text" /></td>
|
||||
<td><input type="text" name="position" /></td>
|
||||
<td><input type="text" name="url" /></td>
|
||||
<td>Delete Button</td>
|
||||
</tr>
|
||||
<%-- end loop --%>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Update All Button</td>
|
||||
</tr>
|
||||
<td><input type="text" name="<%=Html.NameOf(m => m.MenuItemEntries[i].MenuItem.Text) %>" value="<%=menuPartEntry.MenuItem.Text %>" /></td>
|
||||
<td><input type="text" name="<%=Html.NameOf(m => m.MenuItemEntries[i].MenuItem.Position) %>" value="<%=menuPartEntry.MenuItem.Position %>" /></td>
|
||||
<td><% if (!menuPartEntry.IsMenuItem) { %><input type="text" disabled="disabled" value="<%=menuPartEntry.MenuItem.Url %>" /><% } else { %><input type="text" name="<%=Html.NameOf(m => m.MenuItemEntries[i].MenuItem.Url) %>" value="<%=menuPartEntry.MenuItem.Url %>" /><% } %></td>
|
||||
<td><input type="hidden" name="<%=Html.NameOf(m => m.MenuItemEntries[i].MenuItemId) %>" value="<%=menuPartEntry.MenuItemId %>" /><a href="<%=Url.Action("Delete", new {id = menuPartEntry.MenuItemId, __RequestVerificationToken = Html.AntiForgeryTokenValueOrchard()}) %>" class="remove button">delete</a></td>
|
||||
</tr><%
|
||||
++menuPartEntryIndex;
|
||||
} %>
|
||||
</tbody>
|
||||
</table><%
|
||||
</table>
|
||||
<fieldset class="actions"><button type="submit"><%=_Encoded("Update All") %></button></fieldset><%
|
||||
}
|
||||
%>
|
||||
|
||||
using (Html.BeginFormAntiForgeryPost()) { %>
|
||||
<table>
|
||||
<h2><%=_Encoded("Add New Item") %></h2><%
|
||||
using (Html.BeginFormAntiForgeryPost("/admin/navigation/create", FormMethod.Post)) { %>
|
||||
<table class="menu items">
|
||||
<colgroup>
|
||||
<col id="AddText" />
|
||||
<col id="AddPosition" />
|
||||
<col id="AddUrl" />
|
||||
<col id="AddActions" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><input type="text" name="addtext" /></td>
|
||||
<td><input type="text" name="addposition" /></td>
|
||||
<td><input type="text" name="addurl" /></td>
|
||||
<td>Add Button</td>
|
||||
<td>
|
||||
<label for="MenuText"><%=_Encoded("Text") %></label>
|
||||
<%=Html.EditorFor(nmvm => nmvm.NewMenuItem.MenuItem.Item.As<MenuPart>().MenuText) %>
|
||||
</td>
|
||||
<td>
|
||||
<label for="MenuPosition"><%=_Encoded("Position")%></label>
|
||||
<%=Html.EditorFor(nmvm => nmvm.NewMenuItem.MenuItem.Item.As<MenuPart>().MenuPosition) %>
|
||||
</td>
|
||||
<td>
|
||||
<label for="Url"><%=_Encoded("Url")%></label>
|
||||
<%=Html.EditorFor(nmvm => nmvm.NewMenuItem.MenuItem.Item.As<Orchard.Core.Navigation.Models.MenuItem>().Url)%>
|
||||
</td>
|
||||
<td><button class="add" type="submit"><%=_Encoded("Add") %></button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table><%
|
||||
|
||||
@@ -102,20 +102,24 @@
|
||||
<Compile Include="Feeds\Models\FeedResponse.cs" />
|
||||
<Compile Include="Feeds\Rss\RssFeedBuilder.cs" />
|
||||
<Compile Include="Feeds\Rss\RssResult.cs" />
|
||||
<Compile Include="HomePage\Controllers\HomeController.cs" />
|
||||
<Compile Include="HomePage\Routes.cs" />
|
||||
<Compile Include="Navigation\AdminMenu.cs" />
|
||||
<Compile Include="Navigation\Controllers\AdminController.cs" />
|
||||
<Compile Include="Navigation\Models\MenuItem.cs" />
|
||||
<Compile Include="Navigation\Models\MenuItemDriver.cs" />
|
||||
<Compile Include="Navigation\Models\MenuItemHandler.cs" />
|
||||
<Compile Include="Navigation\Drivers\MenuItemDriver.cs" />
|
||||
<Compile Include="Navigation\Handlers\MenuItemHandler.cs" />
|
||||
<Compile Include="Navigation\Models\MenuPart.cs" />
|
||||
<Compile Include="Navigation\Models\MenuPartDriver.cs" />
|
||||
<Compile Include="Navigation\Models\MenuPartHandler.cs" />
|
||||
<Compile Include="Navigation\Drivers\MenuPartDriver.cs" />
|
||||
<Compile Include="Navigation\Handlers\MenuPartHandler.cs" />
|
||||
<Compile Include="Navigation\Permissions.cs" />
|
||||
<Compile Include="Navigation\Records\MenuItemRecord.cs" />
|
||||
<Compile Include="Navigation\Records\MenuPartRecord.cs" />
|
||||
<Compile Include="Navigation\Services\MainMenu.cs" />
|
||||
<Compile Include="Navigation\Services\MainMenuFilter.cs" />
|
||||
<Compile Include="Navigation\ViewModels\NavigationIndexViewModel.cs" />
|
||||
<Compile Include="Navigation\Filters\MainMenuFilter.cs" />
|
||||
<Compile Include="Navigation\ViewModels\CreateMenuItemViewModel.cs" />
|
||||
<Compile Include="Navigation\ViewModels\MenuItemEntry.cs" />
|
||||
<Compile Include="Navigation\ViewModels\NavigationManagementViewModel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Scheduling\Records\ScheduledTaskRecord.cs" />
|
||||
<Compile Include="Scheduling\Services\PublishingTaskHandler.cs" />
|
||||
@@ -216,6 +220,7 @@
|
||||
<Content Include="Themes\Views\Web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="HomePage\Module.txt" />
|
||||
<Content Include="Navigation\Views\Admin\Index.ascx" />
|
||||
<Content Include="Navigation\Views\EditorTemplates\Parts\Navigation.EditMenuPart.ascx" />
|
||||
<Content Include="Navigation\Views\Web.config" />
|
||||
@@ -259,9 +264,8 @@
|
||||
<IISUrl>
|
||||
</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
</CustomServerUrl>
|
||||
<UseCustomServer>True</UseCustomServer>
|
||||
<CustomServerUrl>http://orchard.codeplex.com</CustomServerUrl>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Orchard.Core.Settings {
|
||||
public string MenuName { get { return "admin"; } }
|
||||
|
||||
public void GetNavigation(NavigationBuilder builder) {
|
||||
builder.Add("Settings", "11",
|
||||
builder.Add("Site", "11",
|
||||
menu => menu
|
||||
.Add("Manage Settings", "2.0", item => item.Action("Index", "Admin", new { area = "Settings" }).Permission(Permissions.ManageSettings)));
|
||||
}
|
||||
|
||||
@@ -24,5 +24,9 @@ namespace Orchard.Core.Settings.Models {
|
||||
get { return Record.SuperUser; }
|
||||
set { Record.SuperUser = value; }
|
||||
}
|
||||
public string HomePage {
|
||||
get { return Record.HomePage; }
|
||||
set { Record.HomePage = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,6 @@ namespace Orchard.Core.Settings.Records {
|
||||
public virtual string SiteName { get; set; }
|
||||
public virtual string SuperUser { get; set; }
|
||||
public virtual string PageTitleSeparator { get; set; }
|
||||
public virtual string HomePage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,6 @@
|
||||
<%= Html.EditorForItem(Model.ViewModel) %>
|
||||
<fieldset>
|
||||
<%=Html.EditorFor(s => s.Id) %>
|
||||
<input class="button" type="submit" value="<%=_Encoded("Save") %>" />
|
||||
<input class="button primaryAction" type="submit" value="<%=_Encoded("Save") %>" />
|
||||
</fieldset>
|
||||
<% } %>
|
||||
@@ -5,9 +5,9 @@ namespace Orchard.Core.Themes {
|
||||
public string MenuName { get { return "admin"; } }
|
||||
|
||||
public void GetNavigation(NavigationBuilder builder) {
|
||||
builder.Add("Themes", "11",
|
||||
builder.Add("Site", "11",
|
||||
menu => menu
|
||||
.Add("Manage Themes", "2.0", item => item.Action("Index", "Admin", new { area = "Themes" })
|
||||
.Add("Manage Themes", "4.0", item => item.Action("Index", "Admin", new { area = "Themes" })
|
||||
.Permission(Permissions.ManageThemes).Permission(Permissions.ApplyTheme)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
%><br /><%=Html.ActionLink(T("Install a new Theme").ToString(), "Install") %></p><%
|
||||
} else {
|
||||
%><h3><%=_Encoded("Current Theme")%> - <%=Html.Encode(Model.CurrentTheme.DisplayName) %></h3>
|
||||
<p>
|
||||
<%=Html.Image(Html.ThemePath(Model.CurrentTheme, "/Theme.png"), Html.Encode(Model.CurrentTheme.DisplayName), null)%><br />
|
||||
<%=_Encoded("By") %> <%=Html.Encode(Model.CurrentTheme.Author) %><br />
|
||||
<%=Html.Encode(Model.CurrentTheme.Version) %><br />
|
||||
|
||||
<%=Html.Image(Html.ThemePath(Model.CurrentTheme, "/Theme.png"), Html.Encode(Model.CurrentTheme.DisplayName), null)%>
|
||||
<h5><%=_Encoded("By") %> <%=Html.Encode(Model.CurrentTheme.Author) %></h5>
|
||||
|
||||
<p>
|
||||
<%=_Encoded("Version:") %> <%=Html.Encode(Model.CurrentTheme.Version) %><br />
|
||||
<%=Html.Encode(Model.CurrentTheme.Description) %><br />
|
||||
<%=Html.Encode(Model.CurrentTheme.HomePage) %><br />
|
||||
<%=Html.ActionLink(T("Install a new Theme").ToString(), "Install") %>
|
||||
@@ -21,32 +23,38 @@
|
||||
<ul class="templates">
|
||||
<% foreach (var theme in Model.Themes) {
|
||||
if (Model.CurrentTheme == null || theme.ThemeName != Model.CurrentTheme.ThemeName) {
|
||||
%> <li>
|
||||
%> <li>
|
||||
<div>
|
||||
<h3><%=Html.Encode(theme.DisplayName) %></h3>
|
||||
<p>
|
||||
<%=Html.Image(Html.ThemePath(theme, "/Theme.png"), Html.Encode(theme.DisplayName), null)%><br />
|
||||
<%=_Encoded("By") %> <%=Html.Encode(theme.Author) %><br />
|
||||
<%=Html.Encode(theme.Version) %><br />
|
||||
<%=Html.Encode(theme.Description) %><br />
|
||||
<%=Html.Encode(theme.HomePage) %>
|
||||
</p>
|
||||
<div>
|
||||
<% using(Html.BeginFormAntiForgeryPost(Url.Action("Preview"), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<fieldset>
|
||||
<button type="submit" title="<%=_Encoded("Preview") %>" name="themeName" value="<%=theme.ThemeName %>"><%=_Encoded("Preview") %></button>
|
||||
</fieldset>
|
||||
<% } %>
|
||||
<% using(Html.BeginFormAntiForgeryPost(Url.Action("Activate"), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<%=Html.Image(Html.ThemePath(theme, "/Theme.png"), Html.Encode(theme.DisplayName), null)%>
|
||||
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.Action("Activate"), FormMethod.Post, new { @class = "inline" }))
|
||||
{ %>
|
||||
<fieldset>
|
||||
<button type="submit" title="<%=_Encoded("Activate") %>" name="themeName" value="<%=theme.ThemeName %>"><%=_Encoded("Activate") %></button>
|
||||
</fieldset>
|
||||
<% } %>
|
||||
<% using(Html.BeginFormAntiForgeryPost(Url.Action("Uninstall"), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.Action("Preview"), FormMethod.Post, new { @class = "inline" }))
|
||||
{ %>
|
||||
<fieldset>
|
||||
<button type="submit" class="remove" title="<%=_Encoded("Uninstall") %>" name="themeName" value="<%=theme.ThemeName %>"><%=_Encoded("Uninstall")%></button>
|
||||
<button type="submit" title="<%=_Encoded("Preview") %>" name="themeName" value="<%=theme.ThemeName %>"><%=_Encoded("Preview") %></button>
|
||||
</fieldset>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<h5><%=_Encoded("By") %> <%=Html.Encode(theme.Author) %></h5>
|
||||
<p>
|
||||
<%=_Encoded("Version:") %> <%=Html.Encode(theme.Version) %><br />
|
||||
<%=Html.Encode(theme.Description) %><br />
|
||||
<%=Html.Encode(theme.HomePage) %>
|
||||
</p>
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.Action("Uninstall"), FormMethod.Post, new { @class = "inline" }))
|
||||
{ %>
|
||||
<fieldset>
|
||||
<button type="submit" class="linkButton" title="<%=_Encoded("Uninstall") %>" name="themeName" value="<%=theme.ThemeName %>"><%=_Encoded("Uninstall")%></button>
|
||||
</fieldset>
|
||||
<% } %>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<% }
|
||||
} %>
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<BaseViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
|
||||
<% var menu = Model.Menu.FirstOrDefault();
|
||||
<%@ Import Namespace="Orchard.Mvc.ViewModels"%><%
|
||||
var menu = Model.Menu.FirstOrDefault();
|
||||
if (menu != null && menu.Items.Count() > 0) { %>
|
||||
<div id="menucontainer">
|
||||
<%-- todo: (heskew) *really* need a better way of doing this. ...and this is really, really ugly :) --%>
|
||||
<ul id="menu">
|
||||
<%
|
||||
<%-- TODO: (erikpo) Really need a partial for rendering lists (and it should be templatable) to fix the above todo :) --%>
|
||||
<ul id="menu"><%
|
||||
int counter = 0, count = menu.Items.Count() - 1;
|
||||
foreach (var menuItem in menu.Items) {
|
||||
var sbClass = new StringBuilder(10);
|
||||
if (counter == 0)
|
||||
sbClass.Append("first ");
|
||||
if (counter == count)
|
||||
sbClass.Append("last ");%>
|
||||
<li class="<%=sbClass.ToString().TrimEnd() %>"><%=!string.IsNullOrEmpty(menuItem.Url)
|
||||
? Html.Link(menuItem.Text, ResolveUrl(menuItem.Url))
|
||||
: Html.ActionLink(menuItem.Text, (string)menuItem.RouteValues["action"], menuItem.RouteValues).ToHtmlString() %></li>
|
||||
<%
|
||||
sbClass.Append("last ");
|
||||
|
||||
if (string.Equals(menuItem.Href, Request.Url.AbsolutePath, StringComparison.InvariantCultureIgnoreCase))
|
||||
sbClass.Append("current ");
|
||||
%>
|
||||
<li class="<%=sbClass.ToString().TrimEnd() %>"><%=Html.Link(menuItem.Text, menuItem.Href) %></li><%
|
||||
++counter;
|
||||
} %>
|
||||
</ul>
|
||||
</div>
|
||||
<% } %>
|
||||
</div><%
|
||||
} %>
|
||||
@@ -1,9 +1,11 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<object>" %>
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<BaseViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
|
||||
<div id="logindisplay">
|
||||
<% if (Request.IsAuthenticated) { %>
|
||||
<%=_Encoded("Welcome")%> <strong><%=Html.Encode(Page.User.Identity.Name) %></strong>!
|
||||
[<%=Html.ActionLink(T("Log Off").ToString(), "LogOff", new { Controller = "Account", Area = "Orchard.Users" })%>]
|
||||
<%=T("Welcome, <strong>{0}</strong>!", Html.Encode(Page.User.Identity.Name)) %>
|
||||
<%=Html.Link(T("Admin").ToString(), "/admin/blogs") %> /
|
||||
<%=Html.ActionLink(T("Log Off").ToString(), "LogOff", new { Controller = "Account", Area = "Orchard.Users" }) %>
|
||||
<% } else { %>
|
||||
[<%=Html.ActionLink(T("Log On").ToString(), "LogOn", new { Controller = "Account", Area = "Orchard.Users", ReturnUrl = Context.Request.RawUrl })%>]
|
||||
<%=Html.ActionLink(T("Log On").ToString(), "LogOn", new { Controller = "Account", Area = "Orchard.Users", ReturnUrl = Context.Request.RawUrl }) %>
|
||||
<% } %>
|
||||
</div>
|
||||
@@ -27,7 +27,9 @@ namespace Orchard.Web {
|
||||
protected void Application_Start() {
|
||||
// This is temporary until MVC2 is officially released.
|
||||
// We want to avoid running against an outdated preview installed in the GAC
|
||||
CheckMvcVersion(new Version("2.0.41211.0")/*MVC2 RC file version #*/);
|
||||
CheckMvcVersion(
|
||||
new Version("2.0.50129.0")/*MVC2 RC2 file version #*/,
|
||||
new Version("2.0.41211.0")/*MVC2 RC file version #*/);
|
||||
RegisterRoutes(RouteTable.Routes);
|
||||
|
||||
_host = OrchardStarter.CreateHost(MvcSingletons);
|
||||
@@ -36,11 +38,21 @@ namespace Orchard.Web {
|
||||
//TODO: what's the failed initialization story - IoC failure in app start can leave you with a zombie appdomain
|
||||
}
|
||||
|
||||
private void CheckMvcVersion(Version requiredVersion) {
|
||||
protected void Application_BeginRequest() {
|
||||
Context.Items["originalHttpContext"] = Context;
|
||||
|
||||
_host.BeginRequest();
|
||||
}
|
||||
|
||||
protected void Application_EndRequest() {
|
||||
_host.EndRequest();
|
||||
}
|
||||
|
||||
private void CheckMvcVersion(Version requiredVersion, Version requiredVersion2) {
|
||||
Assembly loadedMvcAssembly = typeof(System.Web.Mvc.Controller).Assembly;
|
||||
Version loadedMvcVersion = ReadAssemblyFileVersion(loadedMvcAssembly);
|
||||
|
||||
if (loadedMvcVersion != requiredVersion) {
|
||||
if (loadedMvcVersion != requiredVersion && loadedMvcVersion != requiredVersion2) {
|
||||
string message;
|
||||
if (loadedMvcAssembly.GlobalAssemblyCache) {
|
||||
message = string.Format(
|
||||
@@ -49,8 +61,8 @@ namespace Orchard.Web {
|
||||
"This implies that Orchard will not be able to run properly in this machine configuration.\r\n" +
|
||||
"Please un-install MVC from the GAC or install a more recent version.",
|
||||
loadedMvcAssembly.GetName().Name,
|
||||
loadedMvcVersion,
|
||||
requiredVersion);
|
||||
requiredVersion,
|
||||
loadedMvcVersion);
|
||||
}
|
||||
else {
|
||||
message = string.Format(
|
||||
@@ -58,11 +70,11 @@ namespace Orchard.Web {
|
||||
"but the version deployed with the application is {2}.\r\n" +
|
||||
"This probably implies that Orchard is deployed with a newer version " +
|
||||
"and the source code hasn't been updated accordingly.\r\n" +
|
||||
"Update the Orchard.Web application source code (look for \"CheckMvcVersion\") to " +
|
||||
"Update the Orchard.Web application source code (look for \"CheckMvcVersion\") to " +
|
||||
"specify the correct file version number.\r\n",
|
||||
loadedMvcAssembly.GetName().Name,
|
||||
loadedMvcVersion,
|
||||
requiredVersion);
|
||||
requiredVersion,
|
||||
loadedMvcVersion);
|
||||
}
|
||||
|
||||
throw new HttpException(500, message);
|
||||
@@ -81,9 +93,6 @@ namespace Orchard.Web {
|
||||
return new Version(attribute.Version);
|
||||
}
|
||||
|
||||
protected void Application_EndRequest() {
|
||||
_host.EndRequest();
|
||||
}
|
||||
|
||||
protected void MvcSingletons(ContainerBuilder builder) {
|
||||
builder.Register(ControllerBuilder.Current);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Blogs.Extensions;
|
||||
using Orchard.Blogs.Models;
|
||||
using Orchard.Blogs.Services;
|
||||
@@ -10,6 +12,7 @@ using Orchard.Data;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.Results;
|
||||
using Orchard.Security;
|
||||
using Orchard.Settings;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace Orchard.Blogs.Controllers {
|
||||
@@ -33,6 +36,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
}
|
||||
|
||||
private Localizer T { get; set; }
|
||||
protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
|
||||
|
||||
public ActionResult Create() {
|
||||
//TODO: (erikpo) Might think about moving this to an ActionFilter/Attribute
|
||||
@@ -100,12 +104,17 @@ namespace Orchard.Blogs.Controllers {
|
||||
return new NotFoundResult();
|
||||
|
||||
var model = new BlogEditViewModel {
|
||||
Blog = _services.ContentManager.UpdateEditorModel(blog, this)
|
||||
Blog = _services.ContentManager.UpdateEditorModel(blog, this),
|
||||
};
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
return View(model);
|
||||
|
||||
string setAsHomePage = input["PromoteToHomePage"];
|
||||
if (!String.IsNullOrEmpty(setAsHomePage) && !setAsHomePage.Equals("false")) {
|
||||
CurrentSite.HomePage = "BlogHomePageProvider;" + model.Blog.Item.Id;
|
||||
}
|
||||
|
||||
_notifier.Information(T("Blog information updated"));
|
||||
|
||||
return Redirect(Url.BlogsForAdmin());
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
<Compile Include="Permissions.cs" />
|
||||
<Compile Include="Routing\IsArchiveConstraint.cs" />
|
||||
<Compile Include="Routing\IsBlogConstraint.cs" />
|
||||
<Compile Include="Services\BlogHomePageProvider.cs" />
|
||||
<Compile Include="Services\BlogService.cs" />
|
||||
<Compile Include="Controllers\BlogController.cs" />
|
||||
<Compile Include="Models\Blog.cs" />
|
||||
@@ -110,6 +111,11 @@
|
||||
<Compile Include="ViewModels\BlogEditViewModel.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Content\Admin\images\draft.gif" />
|
||||
<Content Include="Content\Admin\images\offline.gif" />
|
||||
<Content Include="Content\Admin\images\online.gif" />
|
||||
<Content Include="Content\Admin\images\published.gif" />
|
||||
<Content Include="Content\Admin\images\scheduled.gif" />
|
||||
<Content Include="Module.txt" />
|
||||
<Content Include="Scripts\archives.js" />
|
||||
<Content Include="Scripts\jquery.ui.core.js" />
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Blogs.Extensions;
|
||||
using Orchard.Blogs.Models;
|
||||
using Orchard.Blogs.ViewModels;
|
||||
using Orchard.Mvc.Results;
|
||||
using Orchard.Services;
|
||||
using Orchard.Core.Feeds;
|
||||
|
||||
namespace Orchard.Blogs.Services {
|
||||
public class BlogHomePageProvider : IHomePageProvider {
|
||||
private readonly IBlogService _blogService;
|
||||
private readonly IFeedManager _feedManager;
|
||||
|
||||
public BlogHomePageProvider(IOrchardServices services, IBlogService blogService, IFeedManager feedManager) {
|
||||
Services = services;
|
||||
_feedManager = feedManager;
|
||||
_blogService = blogService;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; private set; }
|
||||
|
||||
#region Implementation of IHomePageProvider
|
||||
|
||||
public string GetProviderName() {
|
||||
return "BlogHomePageProvider";
|
||||
}
|
||||
|
||||
public ActionResult GetHomePage(int itemId) {
|
||||
Blog blog = _blogService.Get().Where(x => x.Id == itemId).FirstOrDefault();
|
||||
|
||||
if (blog == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
var model = new BlogViewModel {
|
||||
Blog = Services.ContentManager.BuildDisplayModel(blog, "Detail")
|
||||
};
|
||||
|
||||
_feedManager.Register(blog);
|
||||
|
||||
return new ViewResult {
|
||||
ViewName = "~/Modules/Orchard.Blogs/Views/Blog/Item.ascx",
|
||||
ViewData = new ViewDataDictionary<BlogViewModel>(model)
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,6 @@ using Orchard.Mvc.ViewModels;
|
||||
namespace Orchard.Blogs.ViewModels {
|
||||
public class BlogEditViewModel : AdminViewModel {
|
||||
public ContentItemViewModel<Blog> Blog { get; set; }
|
||||
public bool PromoteToHomePage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,7 @@
|
||||
<% using (Html.BeginFormAntiForgeryPost()) { %>
|
||||
<%=Html.ValidationSummary() %>
|
||||
<%=Html.EditorForItem(m => m.Blog) %>
|
||||
<%=Html.EditorFor(m => m.PromoteToHomePage) %>
|
||||
<label for="PromoteToHomePage" class="forcheckbox"><%=_Encoded("Set as home page") %></label>
|
||||
<fieldset><input class="button" type="submit" value="<%=_Encoded("Save") %>" /></fieldset><%
|
||||
} %>
|
||||
@@ -5,19 +5,19 @@
|
||||
<h1 class="withActions">
|
||||
<a href="<%=Url.BlogForAdmin(Model.Item.Slug) %>"><%=Html.TitleForPage(Model.Item.Name) %></a>
|
||||
</h1>
|
||||
<ul class="actions">
|
||||
<li class="construct">
|
||||
<a href="<%=Url.BlogEdit(Model.Item.Slug) %>" class="ibutton edit" title="<%=_Encoded("Edit Blog") %>"></a>
|
||||
</li>
|
||||
<li class="destruct">
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.BlogDelete(Model.Item.Slug), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<fieldset>
|
||||
<button type="submit" class="ibutton remove" title="<%=_Encoded("Remove Blog") %>"><%=_Encoded("Remove Blog") %></button>
|
||||
</fieldset><%
|
||||
} %>
|
||||
</li>
|
||||
</ul>
|
||||
<p><%=Html.Encode(Model.Item.Description) %></p>
|
||||
|
||||
<%--<form>
|
||||
<fieldset class="actions bulk">
|
||||
<label for="filterResults"><%=_Encoded("Filter:")%></label>
|
||||
<select id="filterResults" name="">
|
||||
<option value="">All Posts</option>
|
||||
<option value="">Published Posts</option>
|
||||
</select>
|
||||
<input class="button" type="submit" name="submit.Filter" value="<%=_Encoded("Apply") %>"/>
|
||||
</fieldset>
|
||||
</form>--%>
|
||||
|
||||
|
||||
<div class="actions"><a href="<%=Url.BlogPostCreate(Model.Item.Slug) %>" class="add button"><%=_Encoded("New Post")%></a></div>
|
||||
<% Html.Zone("primary");
|
||||
Html.ZonesAny(); %>
|
||||
@@ -6,26 +6,69 @@
|
||||
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
|
||||
<%@ Import Namespace="Orchard.Blogs.Extensions"%>
|
||||
<%@ Import Namespace="Orchard.Blogs.Models"%>
|
||||
<h2><%=Html.Link(Html.Encode(Model.Item.Title), Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Id)) %></h2>
|
||||
<div class="meta"><%=Html.PublishedState(Model.Item) %> | <%Html.Zone("meta");%></div>
|
||||
<div class="content"><%=Model.Item.As<BodyAspect>().Text ?? string.Format("<p><em>{0}</em></p>", _Encoded("there's no content for this blog post"))%></div>
|
||||
<ul class="actions">
|
||||
<li class="construct">
|
||||
<a href="<%=Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Id) %>" class="ibutton edit" title="<%=_Encoded("Edit Post")%>"><%=_Encoded("Edit Post")%></a>
|
||||
<a href="<%=Url.BlogPost(Model.Item.Blog.Slug, Model.Item.Slug) %>" class="ibutton view" title="<%=_Encoded("View Post")%>"><%=_Encoded("View Post")%></a><%
|
||||
if (Model.Item.ContentItem.VersionRecord.Published == false) { // todo: (heskew) be smart about this and maybe have other contextual actions - including view/preview for view up there ^^
|
||||
using (Html.BeginFormAntiForgeryPost(Url.BlogPostPublish(Model.Item.Blog.Slug, Model.Item.Id), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<fieldset>
|
||||
<button type="submit" class="ibutton publish" title="<%=_Encoded("Publish Post Now") %>"><%=_Encoded("Publish Post Now")%></button>
|
||||
</fieldset><%
|
||||
}
|
||||
} %>
|
||||
|
||||
<ul>
|
||||
<li class="properties">
|
||||
<h3><%=Html.Link(Html.Encode(Model.Item.Title), Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Id))%></h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<%if (Model.IsPublished)
|
||||
{ %>
|
||||
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Blogs/Content/Admin/images/online.gif") %>" alt="<%=_Encoded("Online") %>" title="<%=_Encoded("The page is currently online") %>" /><%=_Encoded(" Published")%>
|
||||
<% }
|
||||
else
|
||||
{ %>
|
||||
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Blogs/Content/Admin/images/offline.gif") %>" alt="<%=_Encoded("Offline") %>" title="<%=_Encoded("The page is currently offline") %>" /><%=_Encoded(" Not Published")%>
|
||||
<% } %>
|
||||
|
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<% if (Model.IsDraft) { %>
|
||||
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Blogs/Content/Admin/images/draft.gif") %>" alt="<%=_Encoded("Draft") %>" title="<%=_Encoded("The post has a draft") %>" /><%=Html.PublishedState(Model.Item)%>
|
||||
<% }
|
||||
else
|
||||
{ %>
|
||||
<%=_Encoded("No draft")%>
|
||||
<% } %>
|
||||
|
|
||||
</li>
|
||||
|
||||
<%--This should show publised date, last modified, or scheduled.
|
||||
<li>
|
||||
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Blogs/Content/Admin/images/scheduled.gif") %>" alt="<%=_Encoded("Scheduled") %>" title="<%=_Encoded("The post is scheduled for publishing") %>" /><%=_Encoded("Scheduled")%>
|
||||
|
|
||||
</li>--%>
|
||||
|
||||
<li>
|
||||
<%=_Encoded("By {0}", Model.Item.Creator.UserName)%>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="destruct">
|
||||
|
||||
<li class="related">
|
||||
|
||||
<%if (Model.IsPublished){ %>
|
||||
<a href="<%=Url.BlogPost(Model.Item.Blog.Slug, Model.Item.Slug) %>" title="<%=_Encoded("View Post")%>"><%=_Encoded("View")%></a><%=_Encoded(" | ")%>
|
||||
<% } %>
|
||||
|
||||
<a href="<%=Url.BlogPostEdit(Model.Item.Blog.Slug, Model.Item.Id) %>" title="<%=_Encoded("Edit Post")%>"><%=_Encoded("Edit")%></a><%=_Encoded(" | ")%>
|
||||
|
||||
<%if (Model.Item.ContentItem.VersionRecord.Published == false) { // todo: (heskew) be smart about this and maybe have other contextual actions - including view/preview for view up there ^^
|
||||
using (Html.BeginFormAntiForgeryPost(Url.BlogPostPublish(Model.Item.Blog.Slug, Model.Item.Id), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
|
||||
<button type="submit" class="linkButton" title="<%=_Encoded("Publish") %>"><%=_Encoded("Publish")%></button><%=_Encoded(" | ")%><%
|
||||
}
|
||||
} %>
|
||||
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.BlogPostDelete(Model.Item.Blog.Slug, Model.Item.Id), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<fieldset>
|
||||
<button type="submit" class="ibutton remove" title="<%=_Encoded("Remove Post") %>"><%=_Encoded("Remove Post") %></button>
|
||||
</fieldset><%
|
||||
} %>
|
||||
<button type="submit" class="linkButton" title="<%=_Encoded("Delete") %>"><%=_Encoded("Delete") %></button>
|
||||
<%
|
||||
} %>
|
||||
|
||||
<br /><%Html.Zone("meta");%>
|
||||
</li>
|
||||
|
||||
<li style="clear:both;"></li>
|
||||
</ul>
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="secondary">
|
||||
<% Html.Zone("secondary");%>
|
||||
<fieldset>
|
||||
<input class="button" type="submit" name="submit.Save" value="<%=_Encoded("Save") %>"/>
|
||||
<input class="button primaryAction" type="submit" name="submit.Save" value="<%=_Encoded("Save") %>"/>
|
||||
<% if (Model.IsDraft) { %>
|
||||
<%=Html.ActionLink(T("Discard Draft").ToString(), "DiscardDraft", new { Area = "Orchard.Blogs", Controller = "BlogPostAdmin", id=Model.Item.Id }, new { @class = "button" })%>
|
||||
<% } %>
|
||||
|
||||
@@ -5,7 +5,6 @@ namespace Orchard.Comments.ViewModels {
|
||||
public class CommentsCreateViewModel : AdminViewModel {
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
[Required]
|
||||
public string Email { get; set; }
|
||||
public string SiteName { get; set; }
|
||||
public string CommentText { get; set; }
|
||||
|
||||
@@ -1,42 +1,60 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<HasComments>" %>
|
||||
<%@ Import Namespace="Orchard.Comments.Models"%>
|
||||
<h2 id="comments"><%=_Encoded("{0} Comment{1}", Model.Comments.Count, Model.Comments.Count == 1 ? "" : "s")%></h2><%
|
||||
if (Model.Comments.Count > 0) { Html.RenderPartial("ListOfComments", Model.Comments); }
|
||||
if (Model.CommentsActive == false) { %>
|
||||
<p><%=_Encoded("Comments have been disabled for this content.") %></p><%
|
||||
} else { %>
|
||||
<% using(Html.BeginForm("Create", "Comment", new { area = "Orchard.Comments" }, FormMethod.Post, new { @class = "comment" })) { %>
|
||||
<%=Html.ValidationSummary() %>
|
||||
<%
|
||||
<%@ Import Namespace="Orchard.Security" %>
|
||||
<%@ Import Namespace="Orchard.Comments.Models" %>
|
||||
<h2 id="comments">
|
||||
<%=_Encoded("{0} Comment{1}", Model.Comments.Count, Model.Comments.Count == 1 ? "" : "s")%></h2>
|
||||
<%
|
||||
if (Model.Comments.Count > 0) { Html.RenderPartial("ListOfComments", Model.Comments); }
|
||||
if (Model.CommentsActive == false) { %>
|
||||
<p>
|
||||
<%=_Encoded("Comments have been disabled for this content.") %></p>
|
||||
<%
|
||||
}
|
||||
else { %>
|
||||
<% using (Html.BeginForm("Create", "Comment", new { area = "Orchard.Comments" }, FormMethod.Post, new { @class = "comment" })) { %>
|
||||
<%=Html.ValidationSummary() %>
|
||||
<%
|
||||
if (!Request.IsAuthenticated) { %>
|
||||
<fieldset class="who">
|
||||
<div>
|
||||
<label for="Name"><%=_Encoded("Name") %></label>
|
||||
<input id="Name" class="text" name="Name" type="text" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Email"><%=_Encoded("Email") %></label>
|
||||
<input id="Email" class="text" name="Email" type="text" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="SiteName"><%=_Encoded("Url") %></label>
|
||||
<input id="SiteName" class="text" name="SiteName" type="text" />
|
||||
</div>
|
||||
</fieldset><%
|
||||
<fieldset class="who">
|
||||
<div>
|
||||
<label for="Name">
|
||||
<%=_Encoded("Name") %></label>
|
||||
<input id="Name" class="text" name="Name" type="text" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Email">
|
||||
<%=_Encoded("Email") %></label>
|
||||
<input id="Email" class="text" name="Email" type="text" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="SiteName">
|
||||
<%=_Encoded("Url") %></label>
|
||||
<input id="SiteName" class="text" name="SiteName" type="text" />
|
||||
</div>
|
||||
</fieldset>
|
||||
<%
|
||||
}
|
||||
else {
|
||||
var currentUser = Html.Resolve<IAuthenticationService>().GetAuthenticatedUser();
|
||||
%>
|
||||
<%=Html.Hidden("Name", currentUser.UserName ?? "")%>
|
||||
<%=Html.Hidden("Email", currentUser.Email ?? "")%>
|
||||
<%
|
||||
}%>
|
||||
<fieldset class="what">
|
||||
<div>
|
||||
<label for="CommentText">
|
||||
<% if (Request.IsAuthenticated) { %><%=T("Hi, {0}!", Html.Encode(Page.User.Identity.Name)) %><br />
|
||||
<% } %><%=_Encoded("Leave a comment") %></label>
|
||||
<textarea id="CommentText" rows="10" cols="30" name="CommentText"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" class="button" value="<%=_Encoded("Submit Comment") %>" />
|
||||
<%=Html.Hidden("CommentedOn", Model.ContentItem.Id) %>
|
||||
<%=Html.Hidden("ReturnUrl", Context.Request.Url) %>
|
||||
<%=Html.AntiForgeryTokenOrchard() %>
|
||||
</div>
|
||||
</fieldset>
|
||||
<%
|
||||
}
|
||||
} %>
|
||||
<fieldset class="what">
|
||||
<div>
|
||||
<label for="CommentText"><% if (Request.IsAuthenticated) { %><%=T("Hi, {0}!", Html.Encode(Page.User.Identity.Name)) %><br /><% } %><%=_Encoded("Leave a comment") %></label>
|
||||
<textarea id="CommentText" rows="10" cols="30" name="CommentText"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" class="button" value="<%=_Encoded("Submit Comment") %>" />
|
||||
<%=Html.Hidden("CommentedOn", Model.ContentItem.Id) %>
|
||||
<%=Html.Hidden("ReturnUrl", Context.Request.Url) %>
|
||||
<%=Html.AntiForgeryTokenOrchard() %>
|
||||
</div>
|
||||
</fieldset><%
|
||||
}
|
||||
} %>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 379 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 642 B |
@@ -3,12 +3,14 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Web.Mvc;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Localization;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Mvc.Results;
|
||||
using Orchard.Pages.Models;
|
||||
using Orchard.Pages.Services;
|
||||
using Orchard.Pages.ViewModels;
|
||||
using Orchard.Settings;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace Orchard.Pages.Controllers {
|
||||
@@ -22,6 +24,7 @@ namespace Orchard.Pages.Controllers {
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
|
||||
public IOrchardServices Services { get; private set; }
|
||||
private Localizer T { get; set; }
|
||||
|
||||
@@ -189,6 +192,9 @@ namespace Orchard.Pages.Controllers {
|
||||
case "PublishNow":
|
||||
_pageService.Publish(model.Page.Item);
|
||||
Services.Notifier.Information(T("Page has been published"));
|
||||
if (model.PromoteToHomePage) {
|
||||
CurrentSite.HomePage = "PagesHomePageProvider;" + model.Page.Item.Id;
|
||||
}
|
||||
break;
|
||||
case "PublishLater":
|
||||
_pageService.Publish(model.Page.Item, model.Page.Item.ScheduledPublishUtc.Value);
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
<Compile Include="Security\Authorization.cs" />
|
||||
<Compile Include="Services\IPageService.cs" />
|
||||
<Compile Include="Services\PageService.cs" />
|
||||
<Compile Include="Services\PagesHomePageProvider.cs" />
|
||||
<Compile Include="Services\SlugConstraint.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.Results;
|
||||
using Orchard.Pages.Models;
|
||||
using Orchard.Pages.ViewModels;
|
||||
using Orchard.Services;
|
||||
|
||||
namespace Orchard.Pages.Services {
|
||||
public class PagesHomePageProvider : IHomePageProvider {
|
||||
private readonly IPageService _pageService;
|
||||
private readonly ISlugConstraint _slugConstraint;
|
||||
|
||||
public PagesHomePageProvider(IOrchardServices services, IPageService pageService, ISlugConstraint slugConstraint) {
|
||||
Services = services;
|
||||
_slugConstraint = slugConstraint;
|
||||
_pageService = pageService;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; private set; }
|
||||
private Localizer T { get; set; }
|
||||
|
||||
#region Implementation of IHomePageProvider
|
||||
|
||||
public string GetProviderName() {
|
||||
return "PagesHomePageProvider";
|
||||
}
|
||||
|
||||
public ActionResult GetHomePage(int itemId) {
|
||||
Page page = _pageService.Get(itemId);
|
||||
var correctedSlug = _slugConstraint.LookupPublishedSlug(page.Slug);
|
||||
if (correctedSlug == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
page = _pageService.Get(correctedSlug);
|
||||
if (page == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
var model = new PageViewModel {
|
||||
Page = Services.ContentManager.BuildDisplayModel(page, "Detail")
|
||||
};
|
||||
|
||||
return new ViewResult {
|
||||
ViewName = "~/Modules/Orchard.Pages/Views/Page/Item.ascx",
|
||||
ViewData = new ViewDataDictionary<PageViewModel>(model)
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,6 @@ using Orchard.Mvc.ViewModels;
|
||||
namespace Orchard.Pages.ViewModels {
|
||||
public class PageEditViewModel : AdminViewModel {
|
||||
public ContentItemViewModel<Page> Page { get; set; }
|
||||
public bool PromoteToHomePage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,8 @@
|
||||
<h1><%=Html.TitleForPage(T("Edit Page").ToString()) %></h1>
|
||||
<% using (Html.BeginFormAntiForgeryPost()) { %>
|
||||
<%=Html.ValidationSummary() %>
|
||||
<%=Html.EditorForItem(m => m.Page) %><%
|
||||
<%=Html.EditorForItem(m => m.Page) %>
|
||||
<%=Html.EditorFor(m => m.PromoteToHomePage) %>
|
||||
<label for="PromoteToHomePage" class="forcheckbox"><%=_Encoded("Set as home page") %></label>
|
||||
<%
|
||||
} %>
|
||||
@@ -26,81 +26,82 @@
|
||||
</select>
|
||||
<input class="button" type="submit" name="submit.Filter" value="<%=_Encoded("Apply") %>"/>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<table class="items" summary="<%=_Encoded("This is a table of the PageEntries currently available for use in your application.") %>">
|
||||
<colgroup>
|
||||
<col id="Actions" />
|
||||
<col id="Status" />
|
||||
<col id="Title" />
|
||||
<col id="Author" />
|
||||
<col id="LastUpdated" />
|
||||
<col id="Draft" />
|
||||
<col id="Timer" />
|
||||
<col id="Edit" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"> ↓<%-- todo: (heskew) something more appropriate for "this applies to the bulk actions --%></th>
|
||||
<th scope="col"><%=_Encoded("Status")%></th>
|
||||
<th scope="col"><%=_Encoded("Title")%></th>
|
||||
<th scope="col"><%=_Encoded("Slug")%></th>
|
||||
<th scope="col"><%=_Encoded("Author")%></th>
|
||||
<th scope="col"><%=_Encoded("Draft")%></th>
|
||||
<th scope="col"><%=_Encoded("Scheduled")%></th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<fieldset>
|
||||
<ul class="contentItems" style="margin-top:0;">
|
||||
<%
|
||||
int pageIndex = 0;
|
||||
foreach (var pageEntry in Model.PageEntries)
|
||||
{
|
||||
var pi = pageIndex; %>
|
||||
<tr>
|
||||
<td>
|
||||
<li style="padding:1em .5em;">
|
||||
<div style="float:left;">
|
||||
<input type="hidden" value="<%=Model.PageEntries[pageIndex].PageId %>" name="<%=Html.NameOf(m => m.PageEntries[pi].PageId) %>"/>
|
||||
<input type="checkbox" value="true" name="<%=Html.NameOf(m => m.PageEntries[pi].IsChecked) %>"/>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<h3 style="border-bottom:none; margin:0; padding:0; display:inline;"><%=Html.Encode(pageEntry.Page.Title ?? T("(no title)").ToString())%></h3>
|
||||
|
||||
<p style="margin:.5em 0;">
|
||||
|
||||
<%--Published or not--%>
|
||||
<% if (pageEntry.Page.HasPublished)
|
||||
{ %>
|
||||
<img src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/online.gif") %>" alt="<%=_Encoded("Online") %>" title="<%=_Encoded("The page is currently online") %>" />
|
||||
<img src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/online.gif") %>" alt="<%=_Encoded("Online") %>" title="<%=_Encoded("The page is currently online") %>" style="<%=_Encoded("margin:0 0 -2px 0;") %>" /><%=_Encoded(" Published |") %>
|
||||
<% }
|
||||
else
|
||||
{ %>
|
||||
<img src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/offline.gif") %>" alt="<%=_Encoded("Offline") %>" title="<%=_Encoded("The page is currently offline") %>" />
|
||||
<img src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/offline.gif") %>" alt="<%=_Encoded("Offline") %>" title="<%=_Encoded("The page is currently offline") %>" style="margin:0 0 -2px 0;" /><%=_Encoded(" Not Published |")%>
|
||||
<% } %>
|
||||
</td>
|
||||
<td><%=Html.Encode(pageEntry.Page.Title ?? T("(no title)").ToString())%></td>
|
||||
<td><% if (pageEntry.Page.HasPublished)
|
||||
{ %>
|
||||
<%=Html.ActionLink(!string.IsNullOrEmpty(pageEntry.Page.Slug) ? pageEntry.Page.Slug : T("(no slug)").ToString(), "Item", new { controller = "Page", slug = pageEntry.Page.PublishedSlug })%>
|
||||
|
||||
<%--Does the page have a draft--%>
|
||||
<% if (pageEntry.Page.HasDraft)
|
||||
{ %>
|
||||
<img src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/draft.gif") %>" alt="<%=_Encoded("Draft") %>" title="<%=_Encoded("The page has a draft") %>" style="margin:0 0 -2px 0;" /><%=_Encoded(" Draft")%>
|
||||
<% }
|
||||
else
|
||||
{%>
|
||||
<%=Html.Encode(pageEntry.Page.Slug ?? T("(no slug)").ToString())%>
|
||||
<% } %>
|
||||
</td>
|
||||
<td><%=_Encoded("By {0}", pageEntry.Page.Creator.UserName)%></td>
|
||||
<td>
|
||||
<% if (pageEntry.Page.HasDraft)
|
||||
{ %>
|
||||
<img src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/draft.gif") %>" alt="<%=_Encoded("Draft") %>" title="<%=_Encoded("The page has a draft") %>" />
|
||||
else
|
||||
{ %>
|
||||
<%=_Encoded("No Draft")%>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<%--Scheduled--%>
|
||||
<% if (!pageEntry.Page.IsPublished)
|
||||
{ %>
|
||||
<%=pageEntry.Page.ScheduledPublishUtc != null
|
||||
? string.Format("{0:d}<br />{0:t}", pageEntry.Page.ScheduledPublishUtc.Value)
|
||||
: ""%>
|
||||
<% } %>
|
||||
</td>
|
||||
<td><%=Html.ActionLink(T("Edit").ToString(), "Edit", new { id = pageEntry.PageId })%></td>
|
||||
</tr>
|
||||
<%if (pageEntry.Page.ScheduledPublishUtc != null) { %>
|
||||
<%=" | " %>
|
||||
<img src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/scheduled.gif") %>" alt="<%=_Encoded("Scheduled") %>" title="<%=_Encoded("The page is scheduled for publishing") %>" style="margin:0 0 -2px 0;" />
|
||||
<%=string.Format("Scheduled: {0:d}", pageEntry.Page.ScheduledPublishUtc.Value) %>
|
||||
<% }%>
|
||||
<% } %>
|
||||
|
||||
<%--Author--%>
|
||||
<%=_Encoded(" | By {0}", pageEntry.Page.Creator.UserName)%>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="float:right;">
|
||||
<span style="margin:0; text-align:right; font-size:1.4em;">
|
||||
<% if (pageEntry.Page.HasPublished)
|
||||
{ %>
|
||||
<%=Html.ActionLink("View", "Item", new { controller = "Page", slug = pageEntry.Page.PublishedSlug })%>
|
||||
<%=_Encoded("|")%>
|
||||
<% }
|
||||
else
|
||||
{%>
|
||||
<%=""%>
|
||||
<% } %>
|
||||
|
||||
|
||||
<%=Html.ActionLink(T("Edit").ToString(), "Edit", new { id = pageEntry.PageId })%>
|
||||
|
||||
|
||||
</span>
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
</li>
|
||||
<%
|
||||
pageIndex++;
|
||||
} %>
|
||||
</table>
|
||||
</ul>
|
||||
</fieldset>
|
||||
<% } %>
|
||||
<div class="manage"><%=Html.ActionLink(T("Add a page").ToString(), "Create", new { }, new { @class = "button" })%></div>
|
||||
|
||||
|
||||
<div class="manage"><%=Html.ActionLink(T("Add a page").ToString(), "Create", new { }, new { @class = "button" })%></div>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="secondary">
|
||||
<% Html.Zone("secondary");%>
|
||||
<fieldset>
|
||||
<input class="button" type="submit" name="submit.Save" value="<%=_Encoded("Save") %>"/>
|
||||
<input class="button primaryAction" type="submit" name="submit.Save" value="<%=_Encoded("Save") %>"/>
|
||||
<% if (Model.IsDraft) { %>
|
||||
<%=Html.ActionLink(T("Discard Draft").ToString(), "DiscardDraft", new { Area = "Orchard.Pages", Controller = "Admin", Model.Item.Id }, new { @class = "button" })%>
|
||||
<% } %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<PageViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Mvc.Html"%>
|
||||
<%@ Import Namespace="Orchard.Pages.ViewModels"%>
|
||||
<%=Html.DisplayForItem(m=>m.Page) %>
|
||||
<%=Html.DisplayForItem(m=>m.Page) %>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Comments.Models;
|
||||
using Orchard.ContentManagement;
|
||||
@@ -7,48 +6,49 @@ using Orchard.Core.Common.Models;
|
||||
using Orchard.Core.Navigation.Models;
|
||||
using Orchard.Core.Settings.Models;
|
||||
using Orchard.Data;
|
||||
using Orchard.Data.Migrations;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Security;
|
||||
using Orchard.Settings;
|
||||
using Orchard.Setup.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.UI.Notify;
|
||||
using MenuItem=Orchard.Core.Navigation.Models.MenuItem;
|
||||
|
||||
namespace Orchard.Setup.Controllers {
|
||||
public class SetupController : Controller {
|
||||
private readonly INotifier _notifier;
|
||||
private readonly IDatabaseMigrationManager _databaseMigrationManager;
|
||||
private readonly IOrchardHost _orchardHost;
|
||||
private readonly IShellSettingsLoader _shellSettingsLoader;
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
|
||||
public SetupController(
|
||||
INotifier notifier,
|
||||
IDatabaseMigrationManager databaseMigrationManager,
|
||||
IOrchardHost orchardHost,
|
||||
IShellSettingsLoader shellSettingsLoader) {
|
||||
IOrchardHost orchardHost,
|
||||
IShellSettingsLoader shellSettingsLoader,
|
||||
IAppDataFolder appDataFolder) {
|
||||
_notifier = notifier;
|
||||
_databaseMigrationManager = databaseMigrationManager;
|
||||
_orchardHost = orchardHost;
|
||||
_shellSettingsLoader = shellSettingsLoader;
|
||||
_appDataFolder = appDataFolder;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
private Localizer T { get; set; }
|
||||
|
||||
public ActionResult Index(SetupViewModel model) {
|
||||
private ActionResult IndexViewResult(SetupViewModel model) {
|
||||
string message = "";
|
||||
if(!CanWriteTo(Server.MapPath("~/App_Data"), out message)) {
|
||||
if (!CanWriteToAppDataFolder(out message)) {
|
||||
_notifier.Error(
|
||||
T(
|
||||
"Hey, it looks like I can't write to the App_Data folder in the root of this application and that's where I need to save some of the information you're about to enter.\r\n\r\nPlease give me (the machine account this application is running under) write access to App_Data so I can get this app all set up for you.\r\n\r\nThanks!\r\n\r\n----\r\n{0}",
|
||||
message));
|
||||
}
|
||||
|
||||
return View(model ?? new SetupViewModel { AdminUsername = "admin" });
|
||||
return View(model);
|
||||
}
|
||||
|
||||
public ActionResult Index() {
|
||||
return IndexViewResult(new SetupViewModel { AdminUsername = "admin" });
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("Index")]
|
||||
@@ -58,28 +58,25 @@ namespace Orchard.Setup.Controllers {
|
||||
ModelState.AddModelError("DatabaseConnectionString", "A SQL connection string is required");
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
return Index(model);
|
||||
return IndexViewResult(model);
|
||||
}
|
||||
|
||||
try {
|
||||
var shellSettings = new ShellSettings {
|
||||
Name = "default",
|
||||
DataProvider = model.DatabaseOptions ? "SQLite" : "SqlServer",
|
||||
DataConnectionString = model.DatabaseConnectionString
|
||||
};
|
||||
|
||||
// initialize the database:
|
||||
// provider: SqlServer or SQLite
|
||||
// dataFolder: physical path (map before calling). Builtin database will be created in this location
|
||||
// connectionString: optional - if provided the dataFolder is essentially ignored, but should still be passed in
|
||||
_databaseMigrationManager.CreateCoordinator(shellSettings.DataProvider, Server.MapPath("~/App_Data"), shellSettings.DataConnectionString);
|
||||
Name = "Default",
|
||||
DataProvider = model.DatabaseOptions ? "SQLite" : "SqlServer",
|
||||
DataConnectionString = model.DatabaseConnectionString
|
||||
};
|
||||
|
||||
// creating a standalone environment.
|
||||
// in theory this environment can be used to resolve any normal components by interface, and those
|
||||
// components will exist entirely in isolation - no crossover between the safemode container currently in effect
|
||||
using (var finiteEnvironment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) {
|
||||
try {
|
||||
var contentManager = finiteEnvironment.Resolve<IContentManager>();
|
||||
// initialize database before the transaction is created
|
||||
var sessionFactoryHolder = finiteEnvironment.Resolve<ISessionFactoryHolder>();
|
||||
sessionFactoryHolder.CreateDatabase();
|
||||
|
||||
|
||||
// create superuser
|
||||
var membershipService = finiteEnvironment.Resolve<IMembershipService>();
|
||||
@@ -88,6 +85,7 @@ namespace Orchard.Setup.Controllers {
|
||||
String.Empty, String.Empty, String.Empty,
|
||||
true));
|
||||
|
||||
|
||||
// set site name and settings
|
||||
var siteService = finiteEnvironment.Resolve<ISiteService>();
|
||||
var siteSettings = siteService.GetSiteSettings().As<SiteSettings>();
|
||||
@@ -96,26 +94,29 @@ namespace Orchard.Setup.Controllers {
|
||||
siteSettings.Record.SuperUser = model.AdminUsername;
|
||||
siteSettings.Record.PageTitleSeparator = " - ";
|
||||
|
||||
|
||||
var contentManager = finiteEnvironment.Resolve<IContentManager>();
|
||||
|
||||
// create home page as a CMS page
|
||||
var page = contentManager.Create("page");
|
||||
page.As<BodyAspect>().Text = "Welcome to Orchard";
|
||||
page.As<BodyAspect>().Text = "<p>Welcome to Orchard!</p><p>Congratulations, you've successfully set-up your Orchard site.</p><p>This is the home page of your new site. We've taken the liberty to write here about a few things you could look at next in order to get familiar with the application. Once you feel confident you don't need this anymore, just click [Edit] to go into edit mode and replace this with whatever you want on your home page to make it your own.</p><p>One thing you could do (but you don't have to) is go into [Manage Settings] (follow the [Admin] link and then look for it under \"Settings\" in the menu on the left) and check that everything is configured the way you want.</p><p>You probably want to make the site your own. One of the ways you can do that is by clicking [Manage Themes] in the admin menu. A theme is a packaged look and feel that affects the whole site. We have installed a few themes already, but you'll also be able to browse through an online gallery of themes created by other users of Orchard.</p><p>Next, you can start playing with the content types that we installed. For example, go ahead and click [Add New Page] in the admin menu and create an \"about\" page. Then, add it to the navigation menu by going to [Manage Navigation]. You can also click [Add New Blog] and start posting by clicking [Add New Post].</p><p>Finally, Orchard has been designed to be extended. It comes with a few built-in modules such as pages and blogs but you can install new ones by going to [Manage Themes] and clicking [Install a new Theme]. Like for themes, modules are created by other users of Orchard just like you so if you feel up to it, please [consider participating].</p><p>--The Orchard Crew</p>";
|
||||
page.As<RoutableAspect>().Slug = "";
|
||||
page.As<RoutableAspect>().Title = model.SiteName;
|
||||
page.As<RoutableAspect>().Title = T("Home").ToString();
|
||||
page.As<HasComments>().CommentsShown = false;
|
||||
page.As<CommonAspect>().Owner = user;
|
||||
contentManager.Publish(page);
|
||||
siteSettings.Record.HomePage = "PagesHomePageProvider;" + page.Id;
|
||||
|
||||
// add a menu item for the shiny new home page
|
||||
var menuItem = contentManager.Create("menuitem");
|
||||
menuItem.As<MenuPart>().MenuPosition = "1";
|
||||
menuItem.As<MenuPart>().MenuText = "Home";
|
||||
menuItem.As<MenuPart>().MenuText = T("Home").ToString();
|
||||
menuItem.As<MenuPart>().OnMainMenu = true;
|
||||
menuItem.As<MenuItem>().Url = "~/";
|
||||
|
||||
|
||||
menuItem.As<MenuItem>().Url = "";
|
||||
|
||||
var authenticationService = finiteEnvironment.Resolve<IAuthenticationService>();
|
||||
authenticationService.SignIn(user, true);
|
||||
|
||||
}
|
||||
catch {
|
||||
finiteEnvironment.Resolve<ITransactionManager>().Cancel();
|
||||
@@ -127,28 +128,24 @@ namespace Orchard.Setup.Controllers {
|
||||
|
||||
_orchardHost.Reinitialize();
|
||||
|
||||
_notifier.Information(T("Setup succeeded"));
|
||||
|
||||
// redirect to the welcome page.
|
||||
return Redirect("~/");
|
||||
}
|
||||
catch (Exception exception) {
|
||||
_notifier.Error(T("Setup failed: " + exception.Message));
|
||||
return Index(model);
|
||||
return IndexViewResult(model);
|
||||
}
|
||||
}
|
||||
|
||||
static bool CanWriteTo(string path, out string message) {
|
||||
bool CanWriteToAppDataFolder(out string message) {
|
||||
try {
|
||||
var systemCheckPath = Path.Combine(path, "_systemcheck.txt");
|
||||
|
||||
System.IO.File.WriteAllText(systemCheckPath, "Communicator check one two one two");
|
||||
System.IO.File.AppendAllText(systemCheckPath, "\r\nThis is Bones McCoy on a line to Sulu");
|
||||
System.IO.File.Delete(systemCheckPath);
|
||||
_appDataFolder.CreateFile("_systemcheck.txt", "Communicator check one two one two");
|
||||
_appDataFolder.DeleteFile("_systemcheck.txt");
|
||||
|
||||
message = "";
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
message = ex.Message.Replace("_systemcheck.txt", "");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -155,7 +155,6 @@
|
||||
<Content Include="Themes\TheAdmin\Styles\images\icons.png" />
|
||||
<Content Include="Themes\TheAdmin\Styles\images\tableHeaderBackgroundRed.gif" />
|
||||
<Content Include="Themes\TheAdmin\Styles\site.css" />
|
||||
<Content Include="Themes\TheAdmin\Theme.gif" />
|
||||
<Content Include="Themes\TheAdmin\Theme.txt" />
|
||||
<Content Include="Themes\TheAdmin\Views\Layout.ascx" />
|
||||
</ItemGroup>
|
||||
@@ -182,7 +181,6 @@
|
||||
<Content Include="Themes\Classic\Views\DisplayTemplates\Parts\Blogs.BlogPost.List.ascx" />
|
||||
<Content Include="Themes\Classic\Views\Footer.ascx" />
|
||||
<Content Include="Themes\Classic\Views\Layout.ascx" />
|
||||
<Content Include="Themes\Classic\Views\Menu.ascx" />
|
||||
<Content Include="Themes\Green\Content\Images\bodyBackground.gif" />
|
||||
<Content Include="Themes\Green\Content\Images\bodyBackground.png" />
|
||||
<Content Include="Themes\Green\Content\Images\commentpointer.gif" />
|
||||
@@ -205,7 +203,6 @@
|
||||
<Content Include="Themes\Green\Views\Footer.ascx" />
|
||||
<Content Include="Themes\Green\Views\Layout.ascx" />
|
||||
<Content Include="Themes\Green\Views\ListOfComments.ascx" />
|
||||
<Content Include="Themes\Green\Views\Menu.ascx" />
|
||||
<Content Include="Themes\Green\Views\User.ascx" />
|
||||
<Content Include="Themes\Orange\Theme.png" />
|
||||
<Content Include="Themes\Orange\Views\Orchard.Blogs\BlogPost\Item.ascx" />
|
||||
@@ -220,7 +217,6 @@
|
||||
<Content Include="Themes\Orchard\Theme.txt" />
|
||||
<Content Include="Themes\Orchard\Views\Footer.ascx" />
|
||||
<Content Include="Themes\Orchard\Views\Layout.ascx" />
|
||||
<Content Include="Themes\Orchard\Views\Menu.ascx" />
|
||||
<Content Include="Themes\SafeMode\Content\Images\background_content.jpg" />
|
||||
<Content Include="Themes\SafeMode\Content\Images\background_footer.jpg" />
|
||||
<Content Include="Themes\SafeMode\Content\Images\background_module.gif" />
|
||||
@@ -244,8 +240,10 @@
|
||||
<Content Include="Themes\TheAdminClassic\Views\Layout.ascx" />
|
||||
<Content Include="Themes\TheAdminClassic\Views\Menu.ascx" />
|
||||
<Content Include="Themes\TheAdminClassic\Views\User.ascx" />
|
||||
<Content Include="Themes\TheAdmin\Styles\images\backgroundGradient.gif" />
|
||||
<Content Include="Themes\TheAdmin\Styles\images\backgroundHeader.gif" />
|
||||
<Content Include="Themes\TheAdmin\Styles\images\orchardLogo.gif" />
|
||||
<Content Include="Themes\TheAdmin\Theme.png" />
|
||||
<Content Include="Themes\TheAdmin\Views\Menu.ascx" />
|
||||
<Content Include="Themes\TheAdmin\Views\User.ascx" />
|
||||
<Content Include="Themes\TheAdmin\Views\Header.ascx" />
|
||||
|
||||
|
After Width: | Height: | Size: 379 B |
|
After Width: | Height: | Size: 603 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 379 B |
|
After Width: | Height: | Size: 642 B |
@@ -1,8 +0,0 @@
|
||||
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
|
||||
<div id="menucontainer">
|
||||
<ul id="menu">
|
||||
<li><%= Html.ActionLink("Home", "Index", "Home", new {Area = ""}, new {})%></li>
|
||||
<li><%= Html.ActionLink("Blogs", "List", "Blog", new {Area = "Orchard.Blogs"}, new {})%></li>
|
||||
<li class="last"><%= Html.ActionLink("Admin", "List", new {Area = "Orchard.Blogs", Controller = "BlogAdmin"})%></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -275,11 +275,11 @@ colgroup
|
||||
color:#35550b;
|
||||
}
|
||||
|
||||
#menucontainer ul li.tabon {
|
||||
#menucontainer ul li.current {
|
||||
background:url(../Content/Images/tabRightOn.gif) no-repeat top right;
|
||||
}
|
||||
|
||||
#menucontainer ul li.tabon a {
|
||||
#menucontainer ul li.current a {
|
||||
background:url(../Content/Images/tabLeftOn.gif) no-repeat top left;
|
||||
font-weight:600;
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
|
||||
<div id="menucontainer" role="navigation" class="yui-g">
|
||||
<ul id="menu">
|
||||
<li class="tabon"><%= Html.ActionLink("Home", "Index", "Home", new {Area = ""}, new {})%></li>
|
||||
<li><%= Html.ActionLink("Blogs", "List", "Blog", new {Area = "Orchard.Blogs"}, new {})%></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1,9 +0,0 @@
|
||||
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
|
||||
<div id="menucontainer">
|
||||
<ul id="menu">
|
||||
<li><%= Html.ActionLink("Home", "Index", "Home", new {Area = ""}, new {})%></li>
|
||||
<li><%= Html.ActionLink("About", "About", "Home", new {Area = ""}, new {})%></li>
|
||||
<li><%= Html.ActionLink("Blogs", "List", "Blog", new {Area = "Orchard.Blogs"}, new {})%></li>
|
||||
<li><%= Html.ActionLink("Admin", "List", new {Area = "Orchard.Blogs", Controller = "BlogAdmin"})%></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
After Width: | Height: | Size: 91 B |
@@ -60,7 +60,7 @@ body#preview {
|
||||
min-width:0;
|
||||
}
|
||||
#content {
|
||||
background:#fff;
|
||||
background:#fcfcfc;
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,6 @@ number of columns: 24; actual width: 946; column width: 26; gutter width:14
|
||||
width:23.629%;
|
||||
}
|
||||
|
||||
|
||||
/* Headings and defaults
|
||||
----------------------------------------------------------*/
|
||||
h1, h2, h3, h4, h5, legend {
|
||||
@@ -149,9 +148,9 @@ h3 { font-size:1.8em; } /* 18px */
|
||||
h4 { font-size:1.6em; } /* 16px */
|
||||
h5 { font-size:1.4em; } /* 14px */
|
||||
|
||||
h6, p, legend, label, input, select, .button,
|
||||
h6, p, label, input, select, .button,
|
||||
.message, .validation-summary-errors,
|
||||
table.items th, table.items td, table.items caption { font-size:1.4em; line-height:1.4em; } /* 15px */
|
||||
table.items th, table.items td, table.items caption { font-size:1.4em; line-height:1.4em; } /* 14px */
|
||||
p .button { font-size:inherit; }
|
||||
.meta, .hint { font-size:1.2em; } /* 12px */
|
||||
|
||||
@@ -232,7 +231,6 @@ a:hover, a:active, a:focus {
|
||||
}
|
||||
|
||||
#navigation li {
|
||||
background:#fff;
|
||||
margin:7px 0 20px 0;
|
||||
}
|
||||
#navigation ul li {
|
||||
@@ -329,8 +327,14 @@ span.message {
|
||||
color:#fff;
|
||||
}
|
||||
.info.message {
|
||||
background:#fff; /* orange :P */
|
||||
border:1px dashed #D2D6C6;
|
||||
background:#e4ebef; /* blue */
|
||||
border:1px solid #4687AD;
|
||||
color:#062232;
|
||||
}
|
||||
.info.message {
|
||||
background:#e6e7ef; /* blue */
|
||||
border:1px solid #b5b9c4;
|
||||
color:#062232;
|
||||
}
|
||||
.debug.message {
|
||||
background:#eee;
|
||||
@@ -357,13 +361,18 @@ fieldset.bulk.actions {
|
||||
margin:0 1.4em 0 0;
|
||||
padding-top:0;
|
||||
}
|
||||
|
||||
legend {
|
||||
font-size:1.6em;
|
||||
font-weight:600;
|
||||
font-weight:bold;
|
||||
}
|
||||
label {
|
||||
display: block;
|
||||
font-weight:600;
|
||||
color:#1d1b1b;
|
||||
}
|
||||
label.forcheckbox {
|
||||
display:inline;
|
||||
line-height:1.8em;
|
||||
}
|
||||
fieldset.bulk.actions label, label.sub {
|
||||
display:inline;
|
||||
@@ -383,8 +392,7 @@ label input {
|
||||
/* todo: (heskew) try to get .text on stuff like .text-box */
|
||||
select, textarea, input.text, input.text-box {
|
||||
padding:2px;
|
||||
border:1px solid #ddd;
|
||||
color:#000;
|
||||
border:1px solid #bdbcbc;
|
||||
}
|
||||
input.text, input.text-box {
|
||||
line-height:1.2em;
|
||||
@@ -412,7 +420,22 @@ input.large.text, textarea, fieldset {
|
||||
clear:both;
|
||||
}
|
||||
fieldset {
|
||||
margin:.7em 0 .4em;
|
||||
margin:1.8em 0 .4em 0;
|
||||
}
|
||||
/* Settings page styles */
|
||||
.settings fieldset {
|
||||
margin:.5em 0;
|
||||
border-bottom:1px solid #eaeaea;
|
||||
padding:1em;
|
||||
}
|
||||
.settings fieldset div, .settings .button {
|
||||
margin:1em 0 .5em 1em;
|
||||
}
|
||||
.settings legend {
|
||||
margin:0 0 -.4em 0;
|
||||
}
|
||||
.settings input.text, .settings input.text-box {
|
||||
width:26em;
|
||||
}
|
||||
textarea {
|
||||
min-height:8em;
|
||||
@@ -422,7 +445,6 @@ textarea {
|
||||
padding:4px;
|
||||
width:98%;
|
||||
}
|
||||
|
||||
/* todo: (heskew) move editor specific style elsewhere */
|
||||
.primary .mceEditor {
|
||||
display:block;
|
||||
@@ -442,16 +464,17 @@ button, .button, .button:link, .button:visited {
|
||||
text-align:center;
|
||||
padding:0 .8em .1em .8em;
|
||||
}
|
||||
.primaryAction{
|
||||
background:#4687ad;
|
||||
border:1px solid #8f8f8f;
|
||||
color:#fff;
|
||||
}
|
||||
button.remove, .remove.button, .remove.button:link, .remove.button:visited {
|
||||
background-color:#DECCCA;
|
||||
background-image:url(images/tableHeaderBackgroundRed.gif);
|
||||
border-color:#d6c9c7;
|
||||
color:#5c3732;
|
||||
}
|
||||
a.button, a.button:link, a.button:visited {
|
||||
line-height:1em;
|
||||
padding:.2em .6em;
|
||||
}
|
||||
button:hover, .button:hover,
|
||||
button:active, .button:active,
|
||||
button:focus, .button:focus {
|
||||
@@ -505,7 +528,6 @@ button.remove:focus::-moz-focus-inner, .remove.button:focus::-moz-focus-inner {
|
||||
float:right;
|
||||
height:inherit;
|
||||
margin-left:.3em;
|
||||
padding-bottom:.3em;
|
||||
}
|
||||
|
||||
|
||||
@@ -567,19 +589,18 @@ button.ibutton {
|
||||
----------------------------------------------------------*/
|
||||
.contentItems {
|
||||
background:#FFF;
|
||||
border:1px solid #B0B083;
|
||||
margin:1.4em 0;
|
||||
padding:2px;
|
||||
}
|
||||
.contentItems li {
|
||||
background:#FFF;
|
||||
border-bottom:1px solid #EAE9D9;
|
||||
border-bottom:1px solid #eaeaea;
|
||||
margin:0;
|
||||
overflow:hidden;
|
||||
padding:.7em 1.4em;
|
||||
padding:.4em 1.4em;
|
||||
}
|
||||
.contentItems li.last {
|
||||
border-bottom:0;
|
||||
.contentItems li.first {
|
||||
background:#fff url(images/backgroundGradient.gif) repeat-x top left;
|
||||
}
|
||||
#main .contentItems li h3 {
|
||||
border-bottom:0;
|
||||
@@ -598,7 +619,7 @@ button.ibutton {
|
||||
margin-left:8px;
|
||||
margin-right:0;
|
||||
}
|
||||
#main .contentItems li:hover { background:#fafbed; }
|
||||
#main .contentItems li:hover { background:#f8f8f8; }
|
||||
#main .contentItems li:hover .ibutton { background-position:0 0; }
|
||||
#main .contentItems li:hover .ibutton.remove { background-position:-20px 0; }
|
||||
#main .contentItems li:hover .ibutton.view { background-position:-40px 0; }
|
||||
@@ -661,10 +682,17 @@ todo: (heskew) pull out into relevant modules where appropriate
|
||||
|
||||
/* Pages
|
||||
----------------------------------------------------------*/
|
||||
#main .templates p {
|
||||
margin:0 0 .3em 0;
|
||||
}
|
||||
.templates li {
|
||||
border-bottom:1px dashed #e4e7dc;
|
||||
margin-bottom:2em;
|
||||
padding-bottom:2em;
|
||||
margin:.8em;
|
||||
width:30%;
|
||||
display: -moz-inline-stack;
|
||||
display:inline-block;
|
||||
vertical-align:top;
|
||||
zoom:1;
|
||||
*display: inline;
|
||||
}
|
||||
.templates fieldset {
|
||||
margin:0 0 .933%;
|
||||
@@ -672,10 +700,11 @@ todo: (heskew) pull out into relevant modules where appropriate
|
||||
.templates p {
|
||||
overflow:hidden;
|
||||
}
|
||||
.templates p img {
|
||||
float:left;
|
||||
.templates img {
|
||||
border:1px solid #e8e8e8;
|
||||
height:200px;
|
||||
margin:.27em .93em .93em .54em;
|
||||
margin:.27em 0 .93em 0;
|
||||
display:block;
|
||||
}
|
||||
.previewImage {
|
||||
border:1px solid #525e50;
|
||||
@@ -696,4 +725,61 @@ table.items, textarea, input.text, input.text-box,
|
||||
-moz-border-radius:3px 3px 0 0;
|
||||
-webkit-border-radius:3px 3px 0 0;
|
||||
border-radius:3px 3px 0 0;
|
||||
}*/
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/* Added classes for new blog list layout
|
||||
---------------------------------------------------------- */
|
||||
.actions {
|
||||
height:auto;
|
||||
overflow:visible;
|
||||
padding:0;
|
||||
text-align:right;
|
||||
}
|
||||
.contentItems {
|
||||
padding:0;
|
||||
}
|
||||
.contentItems li ul li {
|
||||
border:0;
|
||||
background:inherit;
|
||||
}
|
||||
li.properties {
|
||||
float:left;
|
||||
}
|
||||
#main .contentItems li.properties h3 {
|
||||
border-bottom:none;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
li.related{
|
||||
font-size:1.4em;
|
||||
float:right;
|
||||
padding:.4em 0;
|
||||
text-align:right;
|
||||
}
|
||||
li.related .commentcount{
|
||||
line-height:2em;
|
||||
}
|
||||
li.properties ul li{
|
||||
border:0;
|
||||
float:left;
|
||||
padding:.8em 0;
|
||||
font-size:1.4em;
|
||||
background:inherit;
|
||||
}
|
||||
.icon {
|
||||
margin:0 0 -2px 4px;
|
||||
margin:0 .2em -.2em .2em;
|
||||
}
|
||||
.linkButton {
|
||||
border:none;
|
||||
padding:0;
|
||||
background:none;
|
||||
color:#1E5D7D;
|
||||
}
|
||||
.linkButton:hover {
|
||||
background-color:Transparent;
|
||||
text-decoration:underline;
|
||||
color:#1E5D7D;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 43 B |
BIN
src/Orchard.Web/Themes/TheAdmin/Theme.png
Normal file
|
After Width: | Height: | Size: 120 B |
|
Before Width: | Height: | Size: 43 B |
BIN
src/Orchard.Web/Themes/TheAdminClassic/Theme.png
Normal file
|
After Width: | Height: | Size: 120 B |
69
src/Orchard/Data/Builders/AbstractBuilder.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentNHibernate.Automapping;
|
||||
using FluentNHibernate.Automapping.Alterations;
|
||||
using FluentNHibernate.Cfg;
|
||||
using FluentNHibernate.Cfg.Db;
|
||||
using FluentNHibernate.Conventions.Helpers;
|
||||
using NHibernate;
|
||||
using NHibernate.Cfg;
|
||||
using NHibernate.Tool.hbm2ddl;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Data.Conventions;
|
||||
using Orchard.Environment;
|
||||
|
||||
namespace Orchard.Data.Builders {
|
||||
public abstract class AbstractBuilder {
|
||||
protected abstract IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase);
|
||||
|
||||
public ISessionFactory BuildSessionFactory(SessionFactoryParameters parameters) {
|
||||
var database = GetPersistenceConfigurer(parameters.CreateDatabase);
|
||||
var persistenceModel = CreatePersistenceModel(parameters.RecordDescriptors);
|
||||
|
||||
var sessionFactory = Fluently.Configure()
|
||||
.Database(database)
|
||||
.Mappings(m => m.AutoMappings.Add(persistenceModel))
|
||||
.ExposeConfiguration(config => Initialization(parameters, config))
|
||||
.BuildSessionFactory();
|
||||
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
private static void Initialization(SessionFactoryParameters parameters, Configuration configuration) {
|
||||
if (parameters.CreateDatabase) {
|
||||
var export = new SchemaExport(configuration);
|
||||
export.Execute(false/*script*/, true/*export*/, false/*justDrop*/);
|
||||
}
|
||||
else if (parameters.UpdateSchema) {
|
||||
var update = new SchemaUpdate(configuration);
|
||||
update.Execute(false/*script*/, true /*doUpdate*/);
|
||||
}
|
||||
}
|
||||
|
||||
public static AutoPersistenceModel CreatePersistenceModel(IEnumerable<RecordDescriptor> recordDescriptors) {
|
||||
return AutoMap.Source(new TypeSource(recordDescriptors))
|
||||
// Ensure that namespaces of types are never auto-imported, so that
|
||||
// identical type names from different namespaces can be mapped without ambiguity
|
||||
.Conventions.Setup(x => x.Add(AutoImport.Never()))
|
||||
.Conventions.Add(new RecordTableNameConvention(recordDescriptors))
|
||||
.Alterations(alt => {
|
||||
foreach (var recordAssembly in recordDescriptors.Select(x => x.Type.Assembly).Distinct()) {
|
||||
alt.Add(new AutoMappingOverrideAlteration(recordAssembly));
|
||||
}
|
||||
alt.AddFromAssemblyOf<DataModule>();
|
||||
alt.Add(new ContentItemAlteration(recordDescriptors));
|
||||
})
|
||||
.Conventions.AddFromAssemblyOf<DataModule>();
|
||||
}
|
||||
|
||||
class TypeSource : ITypeSource {
|
||||
private readonly IEnumerable<RecordDescriptor> _recordDescriptors;
|
||||
|
||||
public TypeSource(IEnumerable<RecordDescriptor> recordDescriptors) { _recordDescriptors = recordDescriptors; }
|
||||
|
||||
public IEnumerable<Type> GetTypes() { return _recordDescriptors.Select(descriptor => descriptor.Type); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
21
src/Orchard/Data/Builders/ISessionFactoryBuilder.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using NHibernate;
|
||||
using Orchard.Environment;
|
||||
|
||||
namespace Orchard.Data.Builders {
|
||||
|
||||
public interface ISessionFactoryBuilder : IDependency {
|
||||
ISessionFactory BuildSessionFactory(SessionFactoryParameters sessionFactoryParameters);
|
||||
}
|
||||
|
||||
public class SessionFactoryParameters {
|
||||
public string Provider { get; set; }
|
||||
public string DataFolder { get; set; }
|
||||
public string ConnectionString { get; set; }
|
||||
|
||||
public bool CreateDatabase { get; set; }
|
||||
public bool UpdateSchema { get; set; }
|
||||
|
||||
public IEnumerable<RecordDescriptor> RecordDescriptors { get; set; }
|
||||
}
|
||||
}
|
||||
35
src/Orchard/Data/Builders/SQLiteBuilder.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.IO;
|
||||
using FluentNHibernate.Cfg.Db;
|
||||
|
||||
namespace Orchard.Data.Builders {
|
||||
public class SQLiteBuilder : AbstractBuilder {
|
||||
private readonly string _dataFolder;
|
||||
private readonly string _connectionString;
|
||||
|
||||
public SQLiteBuilder(string dataFolder, string connectionString) {
|
||||
_dataFolder = dataFolder;
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) {
|
||||
var persistence = SQLiteConfiguration.Standard;
|
||||
if (string.IsNullOrEmpty(_connectionString)) {
|
||||
var dataFile = Path.Combine(_dataFolder, "Orchard.db");
|
||||
|
||||
if (!Directory.Exists(_dataFolder)) {
|
||||
Directory.CreateDirectory(_dataFolder);
|
||||
}
|
||||
|
||||
if (createDatabase && File.Exists(dataFile)) {
|
||||
File.Delete(dataFile);
|
||||
}
|
||||
|
||||
persistence = persistence.UsingFile(dataFile);
|
||||
}
|
||||
else {
|
||||
persistence = persistence.ConnectionString(_connectionString);
|
||||
}
|
||||
return persistence;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/Orchard/Data/Builders/SessionFactoryBuilder.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using NHibernate;
|
||||
|
||||
namespace Orchard.Data.Builders {
|
||||
public class SessionFactoryBuilder : ISessionFactoryBuilder {
|
||||
public ISessionFactory BuildSessionFactory(SessionFactoryParameters parameters) {
|
||||
AbstractBuilder builder;
|
||||
if (string.Equals(parameters.Provider, "SQLite", StringComparison.InvariantCultureIgnoreCase)) {
|
||||
builder = new SQLiteBuilder(parameters.DataFolder, parameters.ConnectionString);
|
||||
}
|
||||
else {
|
||||
builder = new SqlServerBuilder(parameters.DataFolder, parameters.ConnectionString);
|
||||
}
|
||||
return builder.BuildSessionFactory(parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
using System;
|
||||
using FluentNHibernate.Cfg.Db;
|
||||
|
||||
namespace Orchard.Data.Migrations {
|
||||
public class SqlServerDatabaseCoordinator : DatabaseCoordinatorBase {
|
||||
namespace Orchard.Data.Builders {
|
||||
public class SqlServerBuilder : AbstractBuilder {
|
||||
private readonly string _dataFolder;
|
||||
private readonly string _connectionString;
|
||||
|
||||
public SqlServerDatabaseCoordinator(string dataFolder, string connectionString) {
|
||||
public SqlServerBuilder(string dataFolder, string connectionString) {
|
||||
_dataFolder = dataFolder;
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
|
||||
protected override IPersistenceConfigurer GetPersistenceConfigurer() {
|
||||
protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) {
|
||||
var persistence = MsSqlConfiguration.MsSql2008;
|
||||
if (string.IsNullOrEmpty(_connectionString)) {
|
||||
throw new NotImplementedException();
|
||||
@@ -4,7 +4,6 @@ namespace Orchard.Data {
|
||||
public class DataModule : Module {
|
||||
protected override void Load(ContainerBuilder builder) {
|
||||
builder.RegisterGeneric(typeof (Repository<>)).As(typeof (IRepository<>)).FactoryScoped();
|
||||
builder.Register<HackSessionLocator>().As<ISessionLocator>().ContainerScoped();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web.Hosting;
|
||||
using FluentNHibernate.Automapping;
|
||||
using FluentNHibernate.Automapping.Alterations;
|
||||
using FluentNHibernate.Cfg;
|
||||
using FluentNHibernate.Cfg.Db;
|
||||
using FluentNHibernate.Conventions.Helpers;
|
||||
using NHibernate;
|
||||
using NHibernate.Tool.hbm2ddl;
|
||||
using Orchard.Data.Conventions;
|
||||
using Orchard.Environment;
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.Data {
|
||||
public class HackSessionLocator : ISessionLocator, IDisposable {
|
||||
private readonly ICompositionStrategy _compositionStrategy;
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
private static ISessionFactory _sessionFactory;
|
||||
private ISession _session;
|
||||
|
||||
public HackSessionLocator(ICompositionStrategy compositionStrategy, ITransactionManager transactionManager) {
|
||||
_compositionStrategy = compositionStrategy;
|
||||
_transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
private ISessionFactory BindSessionFactory() {
|
||||
// TEMP: a real scenario would call for a session factory locator
|
||||
// that would eventually imply the need for configuration against one or more actual sources
|
||||
// and a means to enlist record types from active modules into correct session factory
|
||||
|
||||
var hackPath = HostingEnvironment.MapPath("~/App_Data/hack.db");
|
||||
|
||||
var database = SQLiteConfiguration.Standard.UsingFile(hackPath);
|
||||
|
||||
var recordDescriptors = _compositionStrategy.GetRecordDescriptors();
|
||||
|
||||
return _sessionFactory ??
|
||||
Interlocked.CompareExchange(
|
||||
ref _sessionFactory,
|
||||
BuildSessionFactory(database, recordDescriptors), null) ?? _sessionFactory;
|
||||
|
||||
}
|
||||
|
||||
private static ISessionFactory BuildSessionFactory(IPersistenceConfigurer database, IEnumerable<RecordDescriptor> recordDescriptors) {
|
||||
return Fluently.Configure()
|
||||
.Database(database)
|
||||
.Mappings(m => m.AutoMappings.Add(CreatePersistenceModel(recordDescriptors)))
|
||||
.ExposeConfiguration(c => new SchemaUpdate(c).Execute(false /*script*/, true /*doUpdate*/))
|
||||
.BuildSessionFactory();
|
||||
}
|
||||
|
||||
public static AutoPersistenceModel CreatePersistenceModel(IEnumerable<RecordDescriptor> recordDescriptors) {
|
||||
var types = recordDescriptors.Select(d => d.Type);
|
||||
return AutoMap.Source(new TypeSource(types))
|
||||
// Ensure that namespaces of types are never auto-imported, so that
|
||||
// identical type names from different namespaces can be mapped without ambiguity
|
||||
.Conventions.Setup(x => x.Add(AutoImport.Never()))
|
||||
.Conventions.Add(new RecordTableNameConvention(recordDescriptors))
|
||||
.Alterations(alt => {
|
||||
foreach (var recordAssembly in recordDescriptors.Select(x => x.Type.Assembly).Distinct()) {
|
||||
alt.Add(new AutoMappingOverrideAlteration(recordAssembly));
|
||||
}
|
||||
alt.AddFromAssemblyOf<DataModule>();
|
||||
alt.Add(new ContentItemAlteration(recordDescriptors));
|
||||
})
|
||||
.Conventions.AddFromAssemblyOf<DataModule>();
|
||||
}
|
||||
|
||||
private class TypeSource : ITypeSource {
|
||||
private readonly IEnumerable<Type> _recordTypes;
|
||||
|
||||
public TypeSource(IEnumerable<Type> recordTypes) {
|
||||
_recordTypes = recordTypes;
|
||||
}
|
||||
|
||||
public IEnumerable<Type> GetTypes() {
|
||||
return _recordTypes;
|
||||
}
|
||||
}
|
||||
|
||||
public ISession For(Type entityType) {
|
||||
var sessionFactory = BindSessionFactory();
|
||||
_transactionManager.Demand();
|
||||
return _session ?? Interlocked.CompareExchange(ref _session, sessionFactory.OpenSession(), null) ?? _session;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
//if (_session != null) {
|
||||
// //_session.Flush();
|
||||
// _session.Close();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using NHibernate;
|
||||
|
||||
namespace Orchard.Data {
|
||||
public interface ISessionLocator {
|
||||
public interface ISessionLocator : IDependency {
|
||||
ISession For(Type entityType);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentNHibernate.Automapping;
|
||||
using FluentNHibernate.Automapping.Alterations;
|
||||
using FluentNHibernate.Cfg;
|
||||
using FluentNHibernate.Cfg.Db;
|
||||
using FluentNHibernate.Conventions.Helpers;
|
||||
using NHibernate;
|
||||
using NHibernate.Tool.hbm2ddl;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Data.Conventions;
|
||||
using Orchard.Environment;
|
||||
|
||||
namespace Orchard.Data.Migrations {
|
||||
public abstract class DatabaseCoordinatorBase : IDatabaseCoordinator {
|
||||
protected abstract IPersistenceConfigurer GetPersistenceConfigurer();
|
||||
|
||||
public virtual bool CanConnect() {
|
||||
try {
|
||||
var sessionFactory = Fluently.Configure()
|
||||
.Database(GetPersistenceConfigurer())
|
||||
.BuildSessionFactory();
|
||||
try {
|
||||
// attempting to open a session validates a connection can be made
|
||||
var session = sessionFactory.OpenSession();
|
||||
session.Close();
|
||||
}
|
||||
finally {
|
||||
sessionFactory.Close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void CreateDatabase() {
|
||||
// creating a session factory appears to be sufficient for causing a database file to be created for inplace providers
|
||||
var sessionFactory = Fluently.Configure()
|
||||
.Database(GetPersistenceConfigurer())
|
||||
.BuildSessionFactory();
|
||||
sessionFactory.Close();
|
||||
}
|
||||
|
||||
public void UpdateSchema(IEnumerable<RecordDescriptor> recordDescriptors) {
|
||||
var configuration = Fluently.Configure()
|
||||
.Database(GetPersistenceConfigurer())
|
||||
.Mappings(m => m.AutoMappings.Add(CreatePersistenceModel(recordDescriptors)))
|
||||
.BuildConfiguration();
|
||||
|
||||
var updater = new SchemaUpdate(configuration);
|
||||
updater.Execute(true /*script*/, true /*doUpdate*/);
|
||||
}
|
||||
|
||||
public ISessionFactory BuildSessionFactory(IEnumerable<RecordDescriptor> recordDescriptors) {
|
||||
return Fluently.Configure()
|
||||
.Database(GetPersistenceConfigurer())
|
||||
.Mappings(m => m.AutoMappings.Add(CreatePersistenceModel(recordDescriptors)))
|
||||
.BuildSessionFactory();
|
||||
}
|
||||
|
||||
static AutoPersistenceModel CreatePersistenceModel(IEnumerable<RecordDescriptor> recordDescriptors) {
|
||||
return AutoMap.Source(new TypeSource(recordDescriptors))
|
||||
// Ensure that namespaces of types are never auto-imported, so that
|
||||
// identical type names from different namespaces can be mapped without ambiguity
|
||||
.Conventions.Setup(x => x.Add(AutoImport.Never()))
|
||||
.Conventions.Add(new RecordTableNameConvention(recordDescriptors))
|
||||
.Alterations(alt => {
|
||||
foreach (var recordAssembly in recordDescriptors.Select(x => x.Type.Assembly).Distinct()) {
|
||||
alt.Add(new AutoMappingOverrideAlteration(recordAssembly));
|
||||
}
|
||||
alt.AddFromAssemblyOf<DataModule>();
|
||||
alt.Add(new ContentItemAlteration(recordDescriptors));
|
||||
})
|
||||
.Conventions.AddFromAssemblyOf<DataModule>();
|
||||
}
|
||||
|
||||
class TypeSource : ITypeSource {
|
||||
private readonly IEnumerable<RecordDescriptor> _recordDescriptors;
|
||||
|
||||
public TypeSource(IEnumerable<RecordDescriptor> recordDescriptors) { _recordDescriptors = recordDescriptors; }
|
||||
|
||||
public IEnumerable<Type> GetTypes() { return _recordDescriptors.Select(descriptor => descriptor.Type); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Orchard.Data.Migrations {
|
||||
public class DatabaseMigrationManager : IDatabaseMigrationManager {
|
||||
public IDatabaseCoordinator CreateCoordinator(string provider, string dataFolder, string connectionString) {
|
||||
if (string.Equals(provider, "SQLite", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new SQLiteDatabaseCoordinator(dataFolder, connectionString);
|
||||
return new SqlServerDatabaseCoordinator(dataFolder, connectionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using NHibernate;
|
||||
using Orchard.Environment;
|
||||
|
||||
namespace Orchard.Data.Migrations {
|
||||
public interface IDatabaseCoordinator {
|
||||
bool CanConnect();
|
||||
void CreateDatabase();
|
||||
|
||||
/// <summary>
|
||||
/// Should only be called in a development or evaluation environment. Automatic schema migration
|
||||
/// not a really safe practice on production data sources.
|
||||
/// </summary>
|
||||
/// <param name="recordDescriptors">Set of known records to be applied</param>
|
||||
void UpdateSchema(IEnumerable<RecordDescriptor> recordDescriptors);
|
||||
|
||||
ISessionFactory BuildSessionFactory(IEnumerable<RecordDescriptor> recordDescriptors);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
namespace Orchard.Data.Migrations {
|
||||
public interface IDatabaseMigrationManager {
|
||||
IDatabaseCoordinator CreateCoordinator(string provider, string dataFolder, string connectionString);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.IO;
|
||||
using FluentNHibernate.Cfg.Db;
|
||||
|
||||
namespace Orchard.Data.Migrations {
|
||||
public class SQLiteDatabaseCoordinator : DatabaseCoordinatorBase {
|
||||
private readonly string _dataFolder;
|
||||
private readonly string _connectionString;
|
||||
|
||||
public SQLiteDatabaseCoordinator(string dataFolder, string connectionString) {
|
||||
_dataFolder = dataFolder;
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
protected override IPersistenceConfigurer GetPersistenceConfigurer() {
|
||||
var persistence = SQLiteConfiguration.Standard;
|
||||
if (string.IsNullOrEmpty(_connectionString)) {
|
||||
persistence = persistence.UsingFile(Path.Combine(_dataFolder, "Orchard.db"));
|
||||
}
|
||||
else {
|
||||
persistence = persistence.ConnectionString(_connectionString);
|
||||
}
|
||||
return persistence;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
89
src/Orchard/Data/SessionFactoryHolder.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using NHibernate;
|
||||
using Orchard.Data.Builders;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Data {
|
||||
public interface ISessionFactoryHolder : ISingletonDependency {
|
||||
ISessionFactory GetSessionFactory();
|
||||
void CreateDatabase();
|
||||
void UpdateSchema();
|
||||
}
|
||||
|
||||
public class SessionFactoryHolder : ISessionFactoryHolder {
|
||||
private readonly IShellSettings _shellSettings;
|
||||
private readonly ICompositionStrategy _compositionStrategy;
|
||||
private readonly ISessionFactoryBuilder _sessionFactoryBuilder;
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
|
||||
private ISessionFactory _sessionFactory;
|
||||
|
||||
public SessionFactoryHolder(
|
||||
IShellSettings shellSettings,
|
||||
ICompositionStrategy compositionStrategy,
|
||||
ISessionFactoryBuilder sessionFactoryBuilder,
|
||||
IAppDataFolder appDataFolder) {
|
||||
_shellSettings = shellSettings;
|
||||
_compositionStrategy = compositionStrategy;
|
||||
_sessionFactoryBuilder = sessionFactoryBuilder;
|
||||
_appDataFolder = appDataFolder;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public void CreateDatabase() {
|
||||
lock (this) {
|
||||
if (_sessionFactory != null) {
|
||||
Logger.Error("CreateSchema can not be called after a session factory was created");
|
||||
throw new OrchardException("CreateSchema can not be called after a session factory was created");
|
||||
}
|
||||
|
||||
_sessionFactory = BuildSessionFactory(true /*createDatabase*/, false /*updateSchema*/);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSchema() {
|
||||
lock (this) {
|
||||
if (_sessionFactory != null) {
|
||||
Logger.Error("UpdateSchema can not be called after a session factory was created");
|
||||
throw new OrchardException("UpdateSchema can not be called after a session factory was created");
|
||||
}
|
||||
|
||||
_sessionFactory = BuildSessionFactory(false /*createDatabase*/, true /*updateSchema*/);
|
||||
}
|
||||
}
|
||||
|
||||
public ISessionFactory GetSessionFactory() {
|
||||
lock (this) {
|
||||
if (_sessionFactory == null) {
|
||||
_sessionFactory = BuildSessionFactory(false /*createDatabase*/, false /*updateSchema*/);
|
||||
}
|
||||
}
|
||||
return _sessionFactory;
|
||||
}
|
||||
|
||||
private ISessionFactory BuildSessionFactory(bool createDatabase, bool updateSchema) {
|
||||
Logger.Debug("Building session factory");
|
||||
|
||||
var shellPath = _appDataFolder.CreateDirectory(Path.Combine("Sites", _shellSettings.Name));
|
||||
|
||||
var sessionFactory = _sessionFactoryBuilder.BuildSessionFactory(new SessionFactoryParameters {
|
||||
Provider = _shellSettings.DataProvider,
|
||||
DataFolder = shellPath,
|
||||
ConnectionString = _shellSettings.DataConnectionString,
|
||||
CreateDatabase = createDatabase,
|
||||
UpdateSchema = updateSchema,
|
||||
RecordDescriptors = _compositionStrategy.GetRecordDescriptors(),
|
||||
});
|
||||
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
38
src/Orchard/Data/SessionLocator.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using NHibernate;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Data {
|
||||
public class SessionLocator : ISessionLocator {
|
||||
private readonly ISessionFactoryHolder _sessionFactoryHolder;
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
private ISession _session;
|
||||
|
||||
public SessionLocator(
|
||||
ISessionFactoryHolder sessionFactoryHolder,
|
||||
ITransactionManager transactionManager) {
|
||||
_sessionFactoryHolder = sessionFactoryHolder;
|
||||
_transactionManager = transactionManager;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
|
||||
public ISession For(Type entityType) {
|
||||
Logger.Debug("Acquiring session for {0}", entityType);
|
||||
|
||||
if (_session == null) {
|
||||
|
||||
var sessionFactory = _sessionFactoryHolder.GetSessionFactory();
|
||||
|
||||
_transactionManager.Demand();
|
||||
|
||||
Logger.Information("Openning database session");
|
||||
_session = sessionFactory.OpenSession();
|
||||
}
|
||||
return _session;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
92
src/Orchard/Environment/Configuration/AppDataFolder.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Hosting;
|
||||
|
||||
namespace Orchard.Environment.Configuration {
|
||||
/// <summary>
|
||||
/// Abstraction of App_Data folder
|
||||
/// Expected to work on physical filesystem, but decouples core
|
||||
/// system from web hosting apis
|
||||
/// </summary>
|
||||
public interface IAppDataFolder {
|
||||
IEnumerable<string> ListFiles(string path);
|
||||
IEnumerable<string> ListDirectories(string path);
|
||||
|
||||
void CreateFile(string path, string content);
|
||||
void DeleteFile(string path);
|
||||
|
||||
string CreateDirectory(string path);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// May be called to initialize component when not in a hosting environment
|
||||
/// app domain
|
||||
/// </summary>
|
||||
void SetBasePath(string basePath);
|
||||
string MapPath(string path);
|
||||
|
||||
}
|
||||
|
||||
public class AppDataFolder : IAppDataFolder {
|
||||
protected string _basePath;
|
||||
|
||||
public AppDataFolder() {
|
||||
_basePath = HostingEnvironment.MapPath("~/App_Data");
|
||||
}
|
||||
|
||||
public void CreateFile(string path, string content) {
|
||||
var filePath = Path.Combine(_basePath, path);
|
||||
var folderPath = Path.GetDirectoryName(filePath);
|
||||
if (!Directory.Exists(folderPath))
|
||||
Directory.CreateDirectory(folderPath);
|
||||
File.WriteAllText(filePath, content);
|
||||
}
|
||||
|
||||
public void DeleteFile(string path) {
|
||||
File.Delete(Path.Combine(_basePath, path));
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListFiles(string path) {
|
||||
var directoryPath = Path.Combine(_basePath, path);
|
||||
if (!Directory.Exists(directoryPath))
|
||||
return Enumerable.Empty<string>();
|
||||
|
||||
var files = Directory.GetFiles(directoryPath);
|
||||
|
||||
return files.Select(file => {
|
||||
var fileName = Path.GetFileName(file);
|
||||
return Path.Combine(path, fileName);
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListDirectories(string path) {
|
||||
var directoryPath = Path.Combine(_basePath, path);
|
||||
if (!Directory.Exists(directoryPath))
|
||||
return Enumerable.Empty<string>();
|
||||
|
||||
var files = Directory.GetDirectories(directoryPath);
|
||||
|
||||
return files.Select(file => {
|
||||
var fileName = Path.GetFileName(file);
|
||||
return Path.Combine(path, fileName);
|
||||
});
|
||||
}
|
||||
|
||||
public string CreateDirectory(string path) {
|
||||
var directory = Path.Combine(_basePath, path);
|
||||
if (!Directory.Exists(directory))
|
||||
Directory.CreateDirectory(directory);
|
||||
return directory;
|
||||
}
|
||||
|
||||
public void SetBasePath(string basePath) {
|
||||
_basePath = basePath;
|
||||
}
|
||||
|
||||
public string MapPath(string path) {
|
||||
return Path.Combine(_basePath, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,11 @@ namespace Orchard.Environment.Configuration {
|
||||
}
|
||||
|
||||
public class ShellSettingsLoader : IShellSettingsLoader {
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
Localizer T { get; set; }
|
||||
|
||||
public ShellSettingsLoader() {
|
||||
public ShellSettingsLoader(IAppDataFolder appDataFolder) {
|
||||
_appDataFolder = appDataFolder;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
@@ -30,31 +32,25 @@ namespace Orchard.Environment.Configuration {
|
||||
if (string.IsNullOrEmpty(settings.Name))
|
||||
throw new ArgumentException(T("Settings \"Name\" is not set.").ToString());
|
||||
|
||||
var sitesPath = HostingEnvironment.MapPath("~/App_Data/Sites");
|
||||
|
||||
if (string.IsNullOrEmpty(sitesPath))
|
||||
throw new ArgumentException(T("Can't determine the path on the server to save settings. Looking for something like \"~/App_Data/Sites\".").ToString());
|
||||
|
||||
if (!Directory.Exists(sitesPath))
|
||||
Directory.CreateDirectory(sitesPath);
|
||||
|
||||
var filePath = Path.Combine(sitesPath, string.Format("{0}.txt", settings.Name));
|
||||
File.WriteAllText(filePath, ComposeSettings(settings));
|
||||
var settingsFile = Path.Combine(Path.Combine("Sites", settings.Name), "Settings.txt");
|
||||
_appDataFolder.CreateFile(settingsFile, ComposeSettings(settings));
|
||||
}
|
||||
|
||||
static IEnumerable<IShellSettings> LoadSettings() {
|
||||
IEnumerable<IShellSettings> LoadSettings() {
|
||||
foreach (var yamlDocument in LoadFiles()) {
|
||||
yield return ParseSettings(yamlDocument);
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<YamlDocument> LoadFiles() {
|
||||
var sitesPath = HostingEnvironment.MapPath("~/App_Data/Sites");
|
||||
if (sitesPath != null && Directory.Exists(sitesPath)) {
|
||||
foreach (var settingsFilePath in Directory.GetFiles(sitesPath, "*.txt")) {
|
||||
var yamlStream = YamlParser.Load(settingsFilePath);
|
||||
yield return yamlStream.Documents.Single();
|
||||
}
|
||||
IEnumerable<YamlDocument> LoadFiles() {
|
||||
var sitePaths = _appDataFolder
|
||||
.ListDirectories("Sites")
|
||||
.SelectMany(path => _appDataFolder.ListFiles(path))
|
||||
.Where(path => string.Equals(Path.GetFileName(path), "Settings.txt", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
foreach (var sitePath in sitePaths) {
|
||||
var yamlStream = YamlParser.Load(_appDataFolder.MapPath(sitePath));
|
||||
yield return yamlStream.Documents.Single();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,10 +61,10 @@ namespace Orchard.Environment.Configuration {
|
||||
.ToDictionary(x => ((Scalar)x.Key).Text, x => x.Value);
|
||||
|
||||
return new ShellSettings {
|
||||
Name = GetValue(fields, "Name"),
|
||||
DataProvider = GetValue(fields, "DataProvider"),
|
||||
DataConnectionString = GetValue(fields, "DataConnectionString")
|
||||
};
|
||||
Name = GetValue(fields, "Name"),
|
||||
DataProvider = GetValue(fields, "DataProvider"),
|
||||
DataConnectionString = GetValue(fields, "DataConnectionString")
|
||||
};
|
||||
}
|
||||
|
||||
static string GetValue(
|
||||
|
||||
@@ -36,16 +36,23 @@ namespace Orchard.Environment {
|
||||
get { return _current; }
|
||||
}
|
||||
|
||||
|
||||
void IOrchardHost.Initialize() {
|
||||
ViewEngines.Engines.Insert(0, LayoutViewEngine.CreateShim());
|
||||
_controllerBuilder.SetControllerFactory(new OrchardControllerFactory());
|
||||
ServiceLocator.SetLocator(t => _containerProvider.RequestContainer.Resolve(t));
|
||||
|
||||
Initialize();
|
||||
CreateAndActivateShell();
|
||||
}
|
||||
|
||||
void IOrchardHost.Reinitialize() {
|
||||
Initialize();
|
||||
_current = null;
|
||||
//CreateAndActivateShell();
|
||||
}
|
||||
|
||||
|
||||
void IOrchardHost.BeginRequest() {
|
||||
BeginRequest();
|
||||
}
|
||||
|
||||
void IOrchardHost.EndRequest() {
|
||||
@@ -57,19 +64,30 @@ namespace Orchard.Environment {
|
||||
return new StandaloneEnvironment(shellContainer);
|
||||
}
|
||||
|
||||
protected virtual void Initialize() {
|
||||
var shellContainer = CreateShellContainer();
|
||||
var shell = shellContainer.Resolve<IOrchardShell>();
|
||||
shell.Activate();
|
||||
_current = shell;
|
||||
protected virtual void CreateAndActivateShell() {
|
||||
lock (this) {
|
||||
if (_current != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire off one-time install events on an alternate container
|
||||
HackInstallSimulation();
|
||||
var shellContainer = CreateShellContainer();
|
||||
var shell = shellContainer.Resolve<IOrchardShell>();
|
||||
shell.Activate();
|
||||
_current = shell;
|
||||
|
||||
// Activate extensions inside shell container
|
||||
HackSimulateExtensionActivation(shellContainer);
|
||||
// Fire off one-time install events on an alternate container
|
||||
HackInstallSimulation();
|
||||
|
||||
// Activate extensions inside shell container
|
||||
HackSimulateExtensionActivation(shellContainer);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void BeginRequest() {
|
||||
if (_current == null) {
|
||||
CreateAndActivateShell();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void EndRequest() {
|
||||
_containerProvider.DisposeRequestContainer();
|
||||
@@ -94,8 +112,9 @@ namespace Orchard.Environment {
|
||||
private IContainer CreateShellContainer(IShellSettings shellSettings) {
|
||||
foreach (var factory in _shellContainerFactories) {
|
||||
var container = factory.CreateContainer(shellSettings);
|
||||
if (container != null)
|
||||
if (container != null) {
|
||||
return container;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,16 +7,21 @@ namespace Orchard.Environment {
|
||||
/// </summary>
|
||||
void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Called each time a request ends to deterministically commit and dispose outstanding activity
|
||||
/// </summary>
|
||||
void EndRequest();
|
||||
|
||||
/// <summary>
|
||||
/// Called when configuration changes requires the shell topology to be reloaded and applied
|
||||
/// </summary>
|
||||
void Reinitialize();
|
||||
|
||||
/// <summary>
|
||||
/// Called each time a request begins to offer a just-in-time reinitialization point
|
||||
/// </summary>
|
||||
void BeginRequest();
|
||||
|
||||
/// <summary>
|
||||
/// Called each time a request ends to deterministically commit and dispose outstanding activity
|
||||
/// </summary>
|
||||
void EndRequest();
|
||||
|
||||
/// <summary>
|
||||
/// Can be used to build an temporary self-contained instance of a shell's configured code.
|
||||
/// Services may be resolved from within this instance to configure and initialize it's storage.
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Orchard.Environment {
|
||||
builder.Register<DefaultOrchardHost>().As<IOrchardHost>().SingletonScoped();
|
||||
builder.Register<DefaultCompositionStrategy>().As<ICompositionStrategy>().SingletonScoped();
|
||||
builder.Register<DefaultShellContainerFactory>().As<IShellContainerFactory>().SingletonScoped();
|
||||
builder.Register<AppDataFolder>().As<IAppDataFolder>().SingletonScoped();
|
||||
builder.Register<ShellSettingsLoader>().As<IShellSettingsLoader>().SingletonScoped();
|
||||
builder.Register<SafeModeShellContainerFactory>().As<IShellContainerFactory>().SingletonScoped();
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
|
||||
// add module types to container being built
|
||||
var addingModulesAndServices = new ContainerBuilder();
|
||||
addingModulesAndServices.Register(settings).As<IShellSettings>();
|
||||
addingModulesAndServices.Register<DefaultOrchardShell>().As<IOrchardShell>().SingletonScoped();
|
||||
|
||||
foreach (var moduleType in _compositionStrategy.GetModuleTypes()) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
@@ -7,7 +8,7 @@ using System.Web.Routing;
|
||||
using Autofac;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Data.Migrations;
|
||||
using Orchard.Data.Builders;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Extensions;
|
||||
using Orchard.Localization;
|
||||
@@ -52,7 +53,7 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
builder.Register<PageClassBuilder>().As<IPageClassBuilder>().ContainerScoped();
|
||||
builder.Register<Notifier>().As<INotifier>().ContainerScoped();
|
||||
builder.Register<NotifyFilter>().As<IFilterProvider>().ContainerScoped();
|
||||
builder.Register<DatabaseMigrationManager>().As<IDatabaseMigrationManager>().ContainerScoped();
|
||||
builder.Register<SessionFactoryBuilder>().As<ISessionFactoryBuilder>().ContainerScoped();
|
||||
|
||||
// safe mode specific implementations of needed service interfaces
|
||||
builder.Register<NullHackInstallationGenerator>().As<IHackInstallationGenerator>().ContainerScoped();
|
||||
@@ -161,6 +162,11 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
public string SuperUser {
|
||||
get { return ""; }
|
||||
}
|
||||
|
||||
public string HomePage {
|
||||
get { return ""; }
|
||||
set { throw new NotImplementedException(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||