Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f716cc343 | |||
| 31ed4e0574 | |||
| 9e3cf00cc0 | |||
| 2f74720c38 | |||
| 91ebc649d4 | |||
| 32591eec36 | |||
| e05a55c532 | |||
| f3d96ad45e | |||
| 010a2e012e | |||
| 5986899b5e | |||
| 5dd04d9a3e | |||
| 6ff2f1eabb | |||
| ac9c6305e7 | |||
| b2b9b53af1 | |||
| 2dd5010d2c | |||
| bfd12b3a7b | |||
| 396b499e81 | |||
| 61ce1bcdca | |||
| ec1d2a6433 | |||
| 9ea9c5d6b7 | |||
| fee9bce110 | |||
| 222720aea4 | |||
| 9e3213147f | |||
| c29357b845 | |||
| cc680f2cfb | |||
| 58dab23d04 | |||
| 90a47cd042 | |||
| fb6079d4e2 | |||
| f359648215 | |||
| 74ca315197 | |||
| 541e546f7b | |||
| 26a8d680d4 | |||
| ec1a3f0fe8 | |||
| 8ce200bd16 | |||
| 26e2bc6afa | |||
| 546458bcfd | |||
| f2090e9fc7 | |||
| 46b0063921 | |||
| 7fd1617759 | |||
| 5e7c9f2341 | |||
| bec8aabede | |||
| c07780caff | |||
| 0c3d3ca545 | |||
| 35a0d4451f | |||
| 03fdba6a3b | |||
| 550c383598 | |||
| 9d3d718e16 | |||
| b09bf518c6 | |||
| 8666b222ac | |||
| 9e564d70ef | |||
| 276810be6c | |||
| 49df6e7c9d | |||
| 06e55c8c4e | |||
| 92273f263b | |||
| f5b017ed67 | |||
| 4512cf0145 | |||
| 38e9a3d2ee | |||
| 13f42773d7 | |||
| 71d3c1112e | |||
| 5bfac6c5b4 | |||
| ebae69d00c | |||
| 1ece576825 | |||
| a2611ce35f | |||
| 7a89580db2 | |||
| a031551fb2 | |||
| 69728fb5c4 | |||
| afd91f8adb | |||
| d99d5a0b36 |
@@ -129,7 +129,7 @@ We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-fl
|
||||
|
||||
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
|
||||
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 (version 15.3 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
|
||||

|
||||
|
||||
@@ -156,4 +156,4 @@ git rebase upstream/dev-v7
|
||||
|
||||
In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
|
||||
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
name: 🐛 Bug Report
|
||||
about: File a bug report, if you've discovered a problem in Umbraco.
|
||||
---
|
||||
|
||||
A brief description of the issue goes here.
|
||||
|
||||
<!--
|
||||
|
||||
If you haven't yet done so, please read the "contributing guidelines"
|
||||
thoroughly. Then, proceed by filling out the rest of the details in the issue
|
||||
template below. The more details you can give us, the easier it will be for us
|
||||
to determine the cause of a problem.
|
||||
|
||||
See: https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md
|
||||
|
||||
-->
|
||||
|
||||
|
||||
|
||||
Reproduction
|
||||
------------
|
||||
|
||||
If you're filing a bug, please describe how to reproduce it. Include as much
|
||||
relevant information as possible, such as:
|
||||
|
||||
### Bug summary
|
||||
|
||||
<!--
|
||||
* Write a short summary of the bug
|
||||
* Try to pinpoint it as much as possible
|
||||
* Try to state the _actual problem_, and not just what you _think_ the
|
||||
solution might be.
|
||||
-->
|
||||
|
||||
### Specifics
|
||||
|
||||
<!--
|
||||
* Mention the URL where this bug occurs, if applicable
|
||||
* What version of Umbraco are you using (down to the very last digit!)
|
||||
* What browser and version you are using
|
||||
* Please mention if you've checked it in other browsers as well
|
||||
* Please include *full error messages* and *screenshots* if possible
|
||||
-->
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
<!--
|
||||
* Clearly mention the steps to reproduce the bug
|
||||
-->
|
||||
|
||||
### Expected result
|
||||
|
||||
<!--
|
||||
* What did you _expect_ that would happen on your Umbraco site?
|
||||
* Describe the intended/desired outcome after you did the steps mentioned.
|
||||
-->
|
||||
|
||||
### Actual result
|
||||
|
||||
<!--
|
||||
* What is the actual result of the above steps?
|
||||
* Describe the behaviour of the bug
|
||||
* Please, please include **error messages** and screenshots. They might mean
|
||||
nothing to you, but they are _very_ helpful to us.
|
||||
-->
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: 📮 Feature Request
|
||||
about: Open a feature request, if you want to propose a new feature.
|
||||
---
|
||||
|
||||
A brief description of your feature request goes here.
|
||||
|
||||
|
||||
<!--
|
||||
If you want to discuss the feature you're imagining, please make sure to keep
|
||||
those discussions on the forum at https://our.umbraco.com/ (choose the
|
||||
category "Contributing to Umbraco", Umbraco HQ follows all new topics there).
|
||||
|
||||
Once you've come to a conclusion in the discussion, feel free to propose the
|
||||
new feature here.
|
||||
-->
|
||||
|
||||
How can you help?
|
||||
-------------------------------
|
||||
|
||||
<!--
|
||||
The resources (read: available time and effort) of Umbraco's core team are
|
||||
limited.
|
||||
|
||||
If we can not work on your suggestion, please don't take it personally. Most
|
||||
likely, it's either:
|
||||
|
||||
- We think your idea is valid, but we can't find the time to work on it.
|
||||
- Your idea might be better suited as a package, if it's not suitable for
|
||||
the majority of users.
|
||||
-->
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
name: ⁉️ Support Question
|
||||
about: Having trouble with Umbraco? -> https://our.umbraco.com
|
||||
---
|
||||
|
||||
This issue tracker is NOT meant for support questions. If you have a question,
|
||||
please join us on the forum at https://our.umbraco.com.
|
||||
|
||||
Thanks!
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
name: 📖 Documentation Issue
|
||||
about: See https://github.com/umbraco/UmbracoDocs/issues for documentation issues
|
||||
---
|
||||
|
||||
The Umbraco documentation has its own dedicated repository. Please open your
|
||||
documentation-related issue at https://github.com/umbraco/UmbracoDocs/issues
|
||||
|
||||
Thanks!
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: 🔐 Security Issue
|
||||
about: Discovered a Security Issue in Umbraco?
|
||||
---
|
||||
|
||||
⚠️ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
|
||||
|
||||
If you have found a security issue in Umbraco, please send the details to
|
||||
security@umbraco.com and don't disclose it publicly until we can provide a fix for
|
||||
it. If you wish, we'll credit you for finding verified issues, when we release
|
||||
the patched version.
|
||||
|
||||
❗ Please read more about how to report security issues on https://umbraco.com/security
|
||||
|
||||
A note on "Self XSS"
|
||||
--------------------
|
||||
|
||||
Umbraco is a CMS, that allows users to edit content on a website. As such,
|
||||
all _authenticated users_ can:
|
||||
|
||||
- Edit content, and (depending on the field types) insert HTML and CSS in that
|
||||
content, with a variety of allowed attributes.
|
||||
- Depending on the user level: Edit template files, and insert C#, HTML, CSS and
|
||||
javascript in so on.
|
||||
- Upload files to the site, which will become publicly available.
|
||||
|
||||
We see these functionalities as _features_, and not as security issues. Please
|
||||
report the mentioned items only if they can be performed by non-authorized
|
||||
users, or other exploitable vulnerabilities.
|
||||
|
||||
Thanks!
|
||||
@@ -0,0 +1,11 @@
|
||||
### Prerequisites
|
||||
|
||||
- [ ] I have [created an issue](https://github.com/umbraco/Umbraco-CMS/issues) for the proposed changes in this PR, the link is:
|
||||
- [ ] I have added steps to test this contribution in the description below
|
||||
|
||||
### Description
|
||||
<!-- A description of the changes proposed in the pull-request -->
|
||||
<!-- Make sure to link to the related issue number so we can easily find it in the issue tracker -->
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
@@ -44,6 +44,6 @@ Umbraco is contribution focused and community driven. If you want to contribute
|
||||
|
||||
## Found a bug?
|
||||
|
||||
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/docs/CONTRIBUTING.md).
|
||||
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md).
|
||||
|
||||
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -21,6 +21,6 @@ The following items will now be automatically included when creating a deploy pa
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.com:
|
||||
http://our.umbraco.com/contribute/releases
|
||||
https://our.umbraco.com/download/releases
|
||||
|
||||
- Umbraco
|
||||
- Umbraco
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
### Prerequisites
|
||||
|
||||
- [ ] I have written a descriptive pull-request title
|
||||
- [ ] I have linked this PR to an issue on the tracker at http://issues.umbraco.org
|
||||
|
||||
### Description
|
||||
<!-- A description of the changes proposed in the pull-request -->
|
||||
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.12.2")]
|
||||
[assembly: AssemblyInformationalVersion("7.12.2")]
|
||||
[assembly: AssemblyFileVersion("7.13.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.13.0")]
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
bool DisableAlternativeTemplates { get; }
|
||||
|
||||
bool ValidateAlternativeTemplates { get; }
|
||||
|
||||
bool DisableFindContentByIdPath { get; }
|
||||
|
||||
bool DisableRedirectUrlTracking { get; }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Configuration;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
@@ -21,6 +22,13 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
get { return (bool) base["disableAlternativeTemplates"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("validateAlternativeTemplates", DefaultValue = "false")]
|
||||
public bool ValidateAlternativeTemplates
|
||||
{
|
||||
get { return (bool)base["validateAlternativeTemplates"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("disableFindContentByIdPath", DefaultValue = "false")]
|
||||
public bool DisableFindContentByIdPath
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.12.2");
|
||||
private static readonly Version Version = new Version("7.13.0");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("This file is no longer used and should not be accessed!")]
|
||||
public static string MetablogConfig
|
||||
{
|
||||
get
|
||||
|
||||
@@ -102,6 +102,28 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateId">The template id to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
|
||||
public bool IsAllowedTemplate(int templateId)
|
||||
{
|
||||
var allowedTemplates = AllowedTemplates ?? new ITemplate[0];
|
||||
return allowedTemplates.Any(t => t.Id == templateId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateAlias">The template alias to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
|
||||
public bool IsAllowedTemplate(string templateAlias)
|
||||
{
|
||||
var allowedTemplates = AllowedTemplates ?? new ITemplate[0];
|
||||
return allowedTemplates.Any(t => t.Alias.Equals(templateAlias, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default template for the ContentType
|
||||
/// </summary>
|
||||
|
||||
@@ -17,6 +17,20 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
IEnumerable<ITemplate> AllowedTemplates { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateId">The template id to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
|
||||
bool IsAllowedTemplate(int templateId);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateAlias">The template alias to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
|
||||
bool IsAllowedTemplate(string templateAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default template for the ContentType
|
||||
/// </summary>
|
||||
|
||||
@@ -1,189 +1,188 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
|
||||
namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an SqlSyntaxProvider for Sql Server.
|
||||
/// </summary>
|
||||
[SqlSyntaxProvider(Constants.DatabaseProviders.SqlServer)]
|
||||
public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlServerSyntaxProvider>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets/sets the version of the current SQL server instance
|
||||
/// </summary>
|
||||
internal SqlServerVersionName GetVersionName(Database database)
|
||||
{
|
||||
if (_versionName.HasValue)
|
||||
return _versionName.Value;
|
||||
|
||||
try
|
||||
{
|
||||
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
|
||||
var firstPart = version.Split('.')[0];
|
||||
switch (firstPart)
|
||||
{
|
||||
case "13":
|
||||
_versionName = SqlServerVersionName.V2016;
|
||||
break;
|
||||
case "12":
|
||||
_versionName = SqlServerVersionName.V2014;
|
||||
break;
|
||||
case "11":
|
||||
_versionName = SqlServerVersionName.V2012;
|
||||
break;
|
||||
case "10":
|
||||
_versionName = SqlServerVersionName.V2008;
|
||||
break;
|
||||
case "9":
|
||||
_versionName = SqlServerVersionName.V2005;
|
||||
break;
|
||||
case "8":
|
||||
_versionName = SqlServerVersionName.V2000;
|
||||
break;
|
||||
case "7":
|
||||
_versionName = SqlServerVersionName.V7;
|
||||
break;
|
||||
default:
|
||||
_versionName = SqlServerVersionName.Other;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_versionName = SqlServerVersionName.Invalid;
|
||||
}
|
||||
|
||||
return _versionName.Value;
|
||||
}
|
||||
|
||||
private SqlServerVersionName? _versionName;
|
||||
|
||||
/// <summary>
|
||||
/// SQL Server stores default values assigned to columns as constraints, it also stores them with named values, this is the only
|
||||
/// server type that does this, therefore this method doesn't exist on any other syntax provider
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Tuple<string, string, string, string>> GetDefaultConstraintsPerColumn(Database db)
|
||||
{
|
||||
var items = db.Fetch<dynamic>("SELECT TableName = t.Name,ColumnName = c.Name,dc.Name,dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id");
|
||||
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetTablesInSchema(Database db)
|
||||
{
|
||||
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES");
|
||||
return items.Select(x => x.TABLE_NAME).Cast<string>().ToList();
|
||||
}
|
||||
|
||||
public override IEnumerable<ColumnInfo> GetColumnsInSchema(Database db)
|
||||
{
|
||||
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS");
|
||||
return
|
||||
items.Select(
|
||||
item =>
|
||||
new ColumnInfo(item.TABLE_NAME, item.COLUMN_NAME, item.ORDINAL_POSITION, item.COLUMN_DEFAULT,
|
||||
item.IS_NULLABLE, item.DATA_TYPE)).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
|
||||
{
|
||||
var items =
|
||||
db.Fetch<dynamic>(
|
||||
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE");
|
||||
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
|
||||
{
|
||||
var items =
|
||||
db.Fetch<dynamic>(
|
||||
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE");
|
||||
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
|
||||
{
|
||||
var items =
|
||||
db.Fetch<dynamic>(
|
||||
@"select T.name as TABLE_NAME, I.name as INDEX_NAME, AC.Name as COLUMN_NAME,
|
||||
CASE WHEN I.is_unique_constraint = 1 OR I.is_unique = 1 THEN 1 ELSE 0 END AS [UNIQUE]
|
||||
from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id]
|
||||
inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]
|
||||
inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]
|
||||
WHERE I.is_primary_key = 0
|
||||
order by T.name, I.name");
|
||||
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
|
||||
item.UNIQUE == 1)).ToList();
|
||||
|
||||
}
|
||||
|
||||
public override bool DoesTableExist(Database db, string tableName)
|
||||
{
|
||||
var result =
|
||||
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName",
|
||||
new { TableName = tableName });
|
||||
|
||||
return result > 0;
|
||||
}
|
||||
|
||||
public override string FormatColumnRename(string tableName, string oldName, string newName)
|
||||
{
|
||||
return string.Format(RenameColumn, tableName, oldName, newName);
|
||||
}
|
||||
|
||||
public override string FormatTableRename(string oldName, string newName)
|
||||
{
|
||||
return string.Format(RenameTable, oldName, newName);
|
||||
}
|
||||
|
||||
protected override string FormatIdentity(ColumnDefinition column)
|
||||
{
|
||||
return column.IsIdentity ? GetIdentityString(column) : string.Empty;
|
||||
}
|
||||
|
||||
public override Sql SelectTop(Sql sql, int top)
|
||||
{
|
||||
return new Sql(sql.SQL.Insert(sql.SQL.IndexOf(' '), " TOP " + top), sql.Arguments);
|
||||
}
|
||||
|
||||
private static string GetIdentityString(ColumnDefinition column)
|
||||
{
|
||||
return "IDENTITY(1,1)";
|
||||
}
|
||||
|
||||
protected override string FormatSystemMethods(SystemMethods systemMethod)
|
||||
{
|
||||
switch (systemMethod)
|
||||
{
|
||||
case SystemMethods.NewGuid:
|
||||
return "NEWID()";
|
||||
case SystemMethods.CurrentDateTime:
|
||||
return "GETDATE()";
|
||||
//case SystemMethods.NewSequentialId:
|
||||
// return "NEWSEQUENTIALID()";
|
||||
//case SystemMethods.CurrentUTCDateTime:
|
||||
// return "GETUTCDATE()";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string DeleteDefaultConstraint
|
||||
{
|
||||
get { return "ALTER TABLE [{0}] DROP CONSTRAINT [DF_{0}_{1}]"; }
|
||||
}
|
||||
|
||||
|
||||
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
|
||||
|
||||
public override string RenameColumn { get { return "sp_rename '{0}.{1}', '{2}', 'COLUMN'"; } }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
|
||||
namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an SqlSyntaxProvider for Sql Server.
|
||||
/// </summary>
|
||||
[SqlSyntaxProvider(Constants.DatabaseProviders.SqlServer)]
|
||||
public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlServerSyntaxProvider>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets/sets the version of the current SQL server instance
|
||||
/// </summary>
|
||||
internal SqlServerVersionName GetVersionName(Database database)
|
||||
{
|
||||
if (_versionName.HasValue)
|
||||
return _versionName.Value;
|
||||
|
||||
try
|
||||
{
|
||||
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
|
||||
var firstPart = version.Split('.')[0];
|
||||
switch (firstPart)
|
||||
{
|
||||
case "13":
|
||||
_versionName = SqlServerVersionName.V2016;
|
||||
break;
|
||||
case "12":
|
||||
_versionName = SqlServerVersionName.V2014;
|
||||
break;
|
||||
case "11":
|
||||
_versionName = SqlServerVersionName.V2012;
|
||||
break;
|
||||
case "10":
|
||||
_versionName = SqlServerVersionName.V2008;
|
||||
break;
|
||||
case "9":
|
||||
_versionName = SqlServerVersionName.V2005;
|
||||
break;
|
||||
case "8":
|
||||
_versionName = SqlServerVersionName.V2000;
|
||||
break;
|
||||
case "7":
|
||||
_versionName = SqlServerVersionName.V7;
|
||||
break;
|
||||
default:
|
||||
_versionName = SqlServerVersionName.Other;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_versionName = SqlServerVersionName.Invalid;
|
||||
}
|
||||
|
||||
return _versionName.Value;
|
||||
}
|
||||
|
||||
private SqlServerVersionName? _versionName;
|
||||
|
||||
/// <summary>
|
||||
/// SQL Server stores default values assigned to columns as constraints, it also stores them with named values, this is the only
|
||||
/// server type that does this, therefore this method doesn't exist on any other syntax provider
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Tuple<string, string, string, string>> GetDefaultConstraintsPerColumn(Database db)
|
||||
{
|
||||
var items = db.Fetch<dynamic>("SELECT TableName = t.Name, ColumnName = c.Name, dc.Name, dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id INNER JOIN sys.schemas as s on t.[schema_id] = s.[schema_id] WHERE s.name = (SELECT SCHEMA_NAME())");
|
||||
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetTablesInSchema(Database db)
|
||||
{
|
||||
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
|
||||
return items.Select(x => x.TABLE_NAME).Cast<string>().ToList();
|
||||
}
|
||||
|
||||
public override IEnumerable<ColumnInfo> GetColumnsInSchema(Database db)
|
||||
{
|
||||
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
|
||||
return
|
||||
items.Select(
|
||||
item =>
|
||||
new ColumnInfo(item.TABLE_NAME, item.COLUMN_NAME, item.ORDINAL_POSITION, item.COLUMN_DEFAULT,
|
||||
item.IS_NULLABLE, item.DATA_TYPE)).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
|
||||
{
|
||||
var items =
|
||||
db.Fetch<dynamic>(
|
||||
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
|
||||
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
|
||||
{
|
||||
var items =
|
||||
db.Fetch<dynamic>(
|
||||
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
|
||||
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
|
||||
{
|
||||
var items =
|
||||
db.Fetch<dynamic>(
|
||||
@"select T.name as TABLE_NAME, I.name as INDEX_NAME, AC.Name as COLUMN_NAME,
|
||||
CASE WHEN I.is_unique_constraint = 1 OR I.is_unique = 1 THEN 1 ELSE 0 END AS [UNIQUE]
|
||||
from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id]
|
||||
inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]
|
||||
inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]
|
||||
inner join sys.schemas as S on T.[schema_id] = S.[schema_id]
|
||||
WHERE S.name = (SELECT SCHEMA_NAME()) AND I.is_primary_key = 0
|
||||
order by T.name, I.name");
|
||||
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
|
||||
item.UNIQUE == 1)).ToList();
|
||||
|
||||
}
|
||||
|
||||
public override bool DoesTableExist(Database db, string tableName)
|
||||
{
|
||||
var result =
|
||||
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName AND TABLE_SCHEMA = (SELECT SCHEMA_NAME())",
|
||||
new { TableName = tableName });
|
||||
|
||||
return result > 0;
|
||||
}
|
||||
|
||||
public override string FormatColumnRename(string tableName, string oldName, string newName)
|
||||
{
|
||||
return string.Format(RenameColumn, tableName, oldName, newName);
|
||||
}
|
||||
|
||||
public override string FormatTableRename(string oldName, string newName)
|
||||
{
|
||||
return string.Format(RenameTable, oldName, newName);
|
||||
}
|
||||
|
||||
protected override string FormatIdentity(ColumnDefinition column)
|
||||
{
|
||||
return column.IsIdentity ? GetIdentityString(column) : string.Empty;
|
||||
}
|
||||
|
||||
public override Sql SelectTop(Sql sql, int top)
|
||||
{
|
||||
return new Sql(sql.SQL.Insert(sql.SQL.IndexOf(' '), " TOP " + top), sql.Arguments);
|
||||
}
|
||||
|
||||
private static string GetIdentityString(ColumnDefinition column)
|
||||
{
|
||||
return "IDENTITY(1,1)";
|
||||
}
|
||||
|
||||
protected override string FormatSystemMethods(SystemMethods systemMethod)
|
||||
{
|
||||
switch (systemMethod)
|
||||
{
|
||||
case SystemMethods.NewGuid:
|
||||
return "NEWID()";
|
||||
case SystemMethods.CurrentDateTime:
|
||||
return "GETDATE()";
|
||||
//case SystemMethods.NewSequentialId:
|
||||
// return "NEWSEQUENTIALID()";
|
||||
//case SystemMethods.CurrentUTCDateTime:
|
||||
// return "GETUTCDATE()";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string DeleteDefaultConstraint
|
||||
{
|
||||
get { return "ALTER TABLE [{0}] DROP CONSTRAINT [DF_{0}_{1}]"; }
|
||||
}
|
||||
|
||||
|
||||
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
|
||||
|
||||
public override string RenameColumn { get { return "sp_rename '{0}.{1}', '{2}', 'COLUMN'"; } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -720,7 +720,7 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
else
|
||||
{
|
||||
//if the salt bytes is too long for the required key length for the algorithm, extend it
|
||||
//if the salt bytes is too short for the required key length for the algorithm, extend it
|
||||
var numArray2 = new byte[keyedHashAlgorithm.Key.Length];
|
||||
var dstOffset = 0;
|
||||
while (dstOffset < numArray2.Length)
|
||||
@@ -963,4 +963,4 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Umbraco.Core.Services
|
||||
regs = xr.Repository.GetAll().ToArray();
|
||||
|
||||
// default role is single server, but if registrations contain more
|
||||
// than one active server, then role is master or slave
|
||||
// than one active server, then role is master or replica
|
||||
_currentServerRole = regs.Count(x => x.IsActive) > 1
|
||||
? (server.IsMaster ? ServerRole.Master : ServerRole.Slave)
|
||||
: ServerRole.Single;
|
||||
@@ -175,4 +175,4 @@ namespace Umbraco.Core.Services
|
||||
return _currentServerRole;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1574,5 +1574,29 @@ namespace Umbraco.Core
|
||||
guid[left] = guid[right];
|
||||
guid[right] = temp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a file name to a friendly name for a content item
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToFriendlyName(this string fileName)
|
||||
{
|
||||
// strip the file extension
|
||||
fileName = fileName.StripFileExtension();
|
||||
|
||||
// underscores and dashes to spaces
|
||||
fileName = fileName.ReplaceMany(new[] { '_', '-' }, ' ');
|
||||
|
||||
// any other conversions ?
|
||||
|
||||
// Pascalcase (to be done last)
|
||||
fileName = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(fileName);
|
||||
|
||||
// Replace multiple consecutive spaces with a single space
|
||||
fileName = string.Join(" ", fileName.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
|
||||
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Sync
|
||||
Single = 1,
|
||||
|
||||
/// <summary>
|
||||
/// In a multi-servers environment, the server is a slave server.
|
||||
/// In a multi-servers environment, the server is a replica server.
|
||||
/// </summary>
|
||||
Slave = 2,
|
||||
|
||||
@@ -25,4 +25,4 @@ namespace Umbraco.Core.Sync
|
||||
/// </summary>
|
||||
Master = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace Umbraco.Tests
|
||||
public void SetApplicationUrlFromDcSettingsSsl2()
|
||||
{
|
||||
// set from distributed call settings
|
||||
// other servers are slave servers
|
||||
// other servers are replica servers
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == new IServer[]
|
||||
@@ -224,7 +224,7 @@ namespace Umbraco.Tests
|
||||
[Test]
|
||||
public void ServerRoleUnknown2()
|
||||
{
|
||||
// distributed call enabled, cannot find server, assume it's an undeclared slave
|
||||
// distributed call enabled, cannot find server, assume it's an undeclared replica
|
||||
|
||||
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == new IServer[]
|
||||
@@ -301,4 +301,4 @@ namespace Umbraco.Tests
|
||||
Assert.AreEqual("httpx://whatever.com/umbraco", appCtx._umbracoApplicationUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,12 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings
|
||||
Assert.IsTrue(SettingsSection.WebRouting.DisableAlternativeTemplates == false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ValidateAlternativeTemplates()
|
||||
{
|
||||
Assert.IsTrue(SettingsSection.WebRouting.ValidateAlternativeTemplates == false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisableFindContentByIdPath()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<staticContent>
|
||||
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
|
||||
</staticContent>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
@@ -8,7 +8,7 @@
|
||||
scope.search = "";
|
||||
scope.miniListViews = [];
|
||||
scope.breadcrumb = [];
|
||||
|
||||
|
||||
var miniListViewsHistory = [];
|
||||
var goingForward = true;
|
||||
var skipAnimation = true;
|
||||
@@ -60,9 +60,13 @@
|
||||
|
||||
entityResource.getPagedChildren(miniListView.node.id, scope.entityType, miniListView.pagination)
|
||||
.then(function (data) {
|
||||
|
||||
// update children
|
||||
miniListView.children = data.items;
|
||||
_.each(miniListView.children, function(c) {
|
||||
// child allowed by default
|
||||
c.allowed = true;
|
||||
|
||||
// convert legacy icon for node
|
||||
if(c.icon) {
|
||||
c.icon = iconHelper.convertFromLegacyIcon(c.icon);
|
||||
@@ -74,6 +78,17 @@
|
||||
c.published = c.metaData.IsPublished;
|
||||
}
|
||||
}
|
||||
|
||||
// filter items if there is a filter and it's not advanced
|
||||
// ** ignores advanced filter at the moment
|
||||
if (scope.entityTypeFilter && !scope.entityTypeFilter.filterAdvanced) {
|
||||
var a = scope.entityTypeFilter.filter.toLowerCase().replace(/\s/g, '').split(',');
|
||||
var found = a.indexOf(c.metaData.ContentTypeAlias.toLowerCase()) >= 0;
|
||||
|
||||
if (!scope.entityTypeFilter.filterExclude && !found || scope.entityTypeFilter.filterExclude && found) {
|
||||
c.allowed = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
// update pagination
|
||||
miniListView.pagination.totalItems = data.totalItems;
|
||||
@@ -89,7 +104,7 @@
|
||||
};
|
||||
|
||||
scope.selectNode = function(node) {
|
||||
if(scope.onSelect) {
|
||||
if (scope.onSelect && node.allowed) {
|
||||
scope.onSelect({'node': node});
|
||||
}
|
||||
};
|
||||
@@ -202,7 +217,8 @@
|
||||
entityType: "@",
|
||||
startNodeId: "=",
|
||||
onSelect: "&",
|
||||
onClose: "&"
|
||||
onClose: "&",
|
||||
entityTypeFilter: "="
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -50,6 +50,11 @@ Use this directive make an element sticky and follow the page when scrolling.
|
||||
|
||||
function activate() {
|
||||
|
||||
if (bar.parents(".umb-property").length > 1) {
|
||||
bar.addClass("nested");
|
||||
return;
|
||||
}
|
||||
|
||||
if (attr.scrollableContainer) {
|
||||
scrollableContainer = $(attr.scrollableContainer);
|
||||
} else {
|
||||
|
||||
@@ -298,10 +298,10 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
|
||||
},
|
||||
|
||||
createCollection: function (parentId, collectionName, collectionItemName, collectionIcon, collectionItemIcon) {
|
||||
createCollection: function (parentId, collectionName, collectionCreateTemplate, collectionItemName, collectionItemCreateTemplate, collectionIcon, collectionItemIcon) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateCollection", { parentId: parentId, collectionName: collectionName, collectionItemName: collectionItemName, collectionIcon: collectionIcon, collectionItemIcon: collectionItemIcon})),
|
||||
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateCollection", { parentId: parentId, collectionName: collectionName, collectionCreateTemplate: collectionCreateTemplate, collectionItemName: collectionItemName, collectionItemCreateTemplate: collectionItemCreateTemplate, collectionIcon: collectionIcon, collectionItemIcon: collectionItemIcon})),
|
||||
'Failed to create collection under ' + parentId);
|
||||
|
||||
},
|
||||
|
||||
@@ -260,7 +260,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
// if save button is alread the default don't change it just update the label
|
||||
if (buttons.defaultButton && buttons.defaultButton.letter === "A") {
|
||||
buttons.defaultButton.labelKey = "buttons_saveAndSchedule";
|
||||
return;
|
||||
return buttons;
|
||||
}
|
||||
|
||||
if(buttons.defaultButton && buttons.subButtons && buttons.subButtons.length > 0) {
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
@import "components/umb-querybuilder.less";
|
||||
@import "components/umb-pagination.less";
|
||||
@import "components/umb-mini-list-view.less";
|
||||
@import "components/umb-multiple-textbox.less";
|
||||
@import "components/umb-badge.less";
|
||||
@import "components/umb-nested-content.less";
|
||||
@import "components/umb-checkmark.less";
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
.umb-editor-sub-header {
|
||||
padding: 15px 0;
|
||||
margin-bottom: 30px;
|
||||
background: @white;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: -30px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
padding: 15px 0;
|
||||
margin-bottom: 30px;
|
||||
background: @white;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: -30px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
|
||||
&.nested {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
background: @gray-10;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-editor-sub-header.-umb-sticky-bar {
|
||||
|
||||
@@ -60,11 +60,6 @@
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
// Hide Circle when not active
|
||||
i.small{
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Circle behind the checkmark
|
||||
i.small.active{
|
||||
font-size: 14px;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
.umb-multiple-textbox .textbox-wrapper {
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.umb-multiple-textbox .textbox-wrapper .umb-editor {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.umb-multiple-textbox .textbox-wrapper i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.umb-multiple-textbox .textbox-wrapper i.handle {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.umb-multiple-textbox .textbox-wrapper a.remove {
|
||||
margin-left: 5px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-multiple-textbox .add-link {
|
||||
&:extend(.umb-node-preview-add);
|
||||
}
|
||||
|
||||
.umb-editor-wrapper .umb-multiple-textbox .add-link {
|
||||
&:extend(.umb-editor-wrapper .umb-node-preview);
|
||||
}
|
||||
|
||||
.umb-modal .umb-multiple-textbox .textbox-wrapper .umb-editor {
|
||||
flex: 1 1 auto;
|
||||
width: auto;
|
||||
}
|
||||
@@ -157,6 +157,10 @@
|
||||
|
||||
/* TEMP */
|
||||
|
||||
.umb-minilistview {
|
||||
.umb-table-row.not-allowed { opacity: 0.6; cursor: not-allowed; }
|
||||
}
|
||||
|
||||
.umb-listview .table-striped tbody td {
|
||||
position: relative
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 10000;
|
||||
z-index: 65537;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 !important;
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
<form method="POST" name="requestPasswordResetForm" ng-submit="requestPasswordResetSubmit(email)">
|
||||
<div class="control-group" ng-class="{error: requestPasswordResetForm.email.$invalid}">
|
||||
<label><localize key="general_email">Email</localize></label>
|
||||
<input type="email" ng-model="email" name="email" class="-full-width-input" localize="placeholder" placeholder="@placeholders_email" />
|
||||
<input type="email" val-email ng-model="email" name="email" class="-full-width-input" localize="placeholder" placeholder="@placeholders_email" />
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-show="requestPasswordResetForm.$invalid">
|
||||
|
||||
@@ -250,7 +250,8 @@ angular.module("umbraco")
|
||||
// make sure that last opened node is on the same path as start node
|
||||
var nodePath = node.path.split(",");
|
||||
|
||||
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1) {
|
||||
// also make sure the node is not trashed
|
||||
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1 && node.trashed === false) {
|
||||
$scope.gotoFolder({ id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder" });
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<umb-empty-state ng-if="!hasItems && emptyStateMessage" position="center">
|
||||
{{ emptyStateMessage }}
|
||||
</umb-empty-state>
|
||||
</umb-empty-state>
|
||||
|
||||
<div ng-if="treeReady" ng-hide="searchInfo.showSearch" ng-animate="'tree-fade-out'">
|
||||
<umb-tree
|
||||
@@ -48,7 +48,8 @@
|
||||
entity-type="{{entityType}}"
|
||||
start-node-id="model.startNodeId"
|
||||
on-select="selectListViewNode(node)"
|
||||
on-close="closeMiniListView()">
|
||||
on-close="closeMiniListView()"
|
||||
entity-type-filter="filter">
|
||||
</umb-mini-list-view>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div>
|
||||
<div class="umb-minilistview">
|
||||
|
||||
<div ng-repeat="miniListView in miniListViews" ng-animate="getMiniListViewAnimation()">
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<div class="umb-table-row"
|
||||
ng-repeat="child in miniListView.children"
|
||||
ng-click="selectNode(child)"
|
||||
ng-class="{'-selected':child.selected}">
|
||||
ng-class="{'-selected':child.selected, 'not-allowed':!child.allowed}">
|
||||
<div class="umb-table-cell umb-table-cell--auto-width" ng-class="{'umb-table-cell--faded':child.published === false}">
|
||||
<div class="flex items-center">
|
||||
<ins class="icon-navigation-right umb-table__row-expand" ng-click="openNode($event, child)" ng-class="{'umb-table__row-expand--hidden': child.hasChildren !== true}"> </ins>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
val-form-manager>
|
||||
|
||||
<umb-control-group label="Enter a folder name" hide-label="false">
|
||||
<input type="text" name="folderName" ng-model="model.folderName" class="umb-textstring textstring input-block-level" required />
|
||||
<input type="text" name="folderName" ng-model="model.folderName" class="umb-textstring textstring input-block-level" required autofocus />
|
||||
</umb-control-group>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
||||
|
||||
@@ -27,6 +27,8 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
|
||||
|
||||
$scope.showCreateDocTypeCollection = function () {
|
||||
$scope.model.creatingDoctypeCollection = true;
|
||||
$scope.model.collectionCreateTemplate = true;
|
||||
$scope.model.collectionItemCreateTemplate = true;
|
||||
};
|
||||
|
||||
$scope.createContainer = function () {
|
||||
@@ -83,7 +85,7 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
|
||||
}
|
||||
}
|
||||
|
||||
contentTypeResource.createCollection(node.id, $scope.model.collectionName, $scope.model.collectionItemName, collectionIcon, collectionItemIcon).then(function (collectionData) {
|
||||
contentTypeResource.createCollection(node.id, $scope.model.collectionName, $scope.model.collectionCreateTemplate, $scope.model.collectionItemName, $scope.model.collectionItemCreateTemplate, collectionIcon, collectionItemIcon).then(function (collectionData) {
|
||||
|
||||
navigationService.hideMenu();
|
||||
$location.search('create', null);
|
||||
|
||||
@@ -80,10 +80,14 @@
|
||||
|
||||
<umb-control-group label="Name of the Parent Document Type" hide-label="false">
|
||||
<input type="text" name="collectionName" ng-model="model.collectionName" class="umb-textstring textstring input-block-level" umb-auto-focus required />
|
||||
<umb-toggle on-click="model.collectionCreateTemplate = !model.collectionCreateTemplate" checked="model.collectionCreateTemplate"></umb-toggle>
|
||||
<label>Create template for the Parent Document Type</label>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="Name of the Item Document Type" hide-label="false">
|
||||
<input type="text" name="collectionItemName" ng-model="model.collectionItemName" class="umb-textstring textstring input-block-level" required />
|
||||
<umb-toggle on-click="model.collectionItemCreateTemplate = !model.collectionItemCreateTemplate" checked="model.collectionItemCreateTemplate"></umb-toggle>
|
||||
<label>Create template for the Item Document Type</label>
|
||||
</umb-control-group>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
||||
|
||||
@@ -218,7 +218,7 @@ angular.module("umbraco")
|
||||
// Fade in control when sorting stops
|
||||
ui.item.context.style.opacity = "1";
|
||||
|
||||
ui.item.parents(".umb-cell-content").find(".mceNoEditor").each(function () {
|
||||
ui.item.offsetParent().find(".mceNoEditor").each(function () {
|
||||
if ($.inArray($(this).attr("id"), notIncludedRte) < 0) {
|
||||
// add all dragged's neighbouring RTEs in the new cell
|
||||
notIncludedRte.splice(0, 0, $(this).attr("id"));
|
||||
|
||||
@@ -561,9 +561,6 @@
|
||||
<None Include="Config\scripting.Release.config">
|
||||
<DependentUpon>scripting.config</DependentUpon>
|
||||
</None>
|
||||
<None Include="Config\metablogConfig.Release.config">
|
||||
<DependentUpon>metablogConfig.config</DependentUpon>
|
||||
</None>
|
||||
<None Include="Config\ExamineSettings.Release.config">
|
||||
<DependentUpon>ExamineSettings.config</DependentUpon>
|
||||
</None>
|
||||
@@ -993,7 +990,6 @@
|
||||
<Content Include="Config\Dashboard.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Config\metablogConfig.config" />
|
||||
<Content Include="Config\tinyMceConfig.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
@@ -1034,9 +1030,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7122</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7130</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7122</IISUrl>
|
||||
<IISUrl>http://localhost:7130</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
@@ -1089,4 +1085,4 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<Exec WorkingDirectory="$(ProjectDir)\..\..\" Command="powershell -ExecutionPolicy RemoteSigned -Command "&{ $env:PSModulePath = \"$pwd\build\Modules\;$env:PSModulePath\" ; Import-Module Umbraco.Build -Force -DisableNameChecking ; build-umbraco compile-belle }"" />
|
||||
</Target>
|
||||
<Import Project="..\packages\AutoMapper.3.3.1\tools\AutoMapper.targets" Condition="Exists('..\packages\AutoMapper.3.3.1\tools\AutoMapper.targets')" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<metablogapi>
|
||||
</metablogapi>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<metablogapi>
|
||||
<channel>
|
||||
<name>My FAQs</name>
|
||||
<user>0</user>
|
||||
<startNode>1080</startNode>
|
||||
<fullTree>False</fullTree>
|
||||
<documentTypeAlias>Articulate</documentTypeAlias>
|
||||
<fields>
|
||||
<categories>
|
||||
</categories>
|
||||
<description>
|
||||
</description>
|
||||
<excerpt>
|
||||
</excerpt>
|
||||
</fields>
|
||||
<mediaObjectSupport enabled="True" folderId="-1" mediaTypeAlias="Image" mediaTypeFileProperty="umbracoFile" />
|
||||
</channel>
|
||||
</metablogapi>
|
||||
@@ -152,6 +152,12 @@
|
||||
will make Umbraco render the content on the current page with the template you requested, for example:
|
||||
http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the
|
||||
"About Us" page with a template with the alias Home. Setting this setting to true stops that behavior
|
||||
@validateAlternativeTemplates
|
||||
By default you can add a altTemplate querystring or append a template name to the current URL which
|
||||
will make Umbraco render the content on the current page with the template you requested, for example:
|
||||
http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the
|
||||
"About Us" page with a template with the alias Home. Setting this setting to true will ensure that
|
||||
only templates that have been permitted on the document type will be allowed
|
||||
@disableFindContentByIdPath
|
||||
By default you can call any content Id in the url and show the content with that id, for example:
|
||||
http://mysite.com/1092 or http://mysite.com/1092.aspx would render the content with id 1092. Setting
|
||||
@@ -163,7 +169,7 @@
|
||||
-->
|
||||
<web.routing
|
||||
trySkipIisCustomErrors="false"
|
||||
internalRedirectPreservesTemplate="false" disableAlternativeTemplates="false" disableFindContentByIdPath="false"
|
||||
internalRedirectPreservesTemplate="false" disableAlternativeTemplates="false" validateAlternativeTemplates="false" disableFindContentByIdPath="false"
|
||||
umbracoApplicationUrl="">
|
||||
</web.routing>
|
||||
|
||||
|
||||
@@ -304,7 +304,13 @@
|
||||
By default you can add a altTemplate querystring or append a template name to the current URL which
|
||||
will make Umbraco render the content on the current page with the template you requested, for example:
|
||||
http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the
|
||||
"About Us" page with a template with the alias Home. Setting this setting to true stops that behavior
|
||||
"About Us" page with a template with the alias Home. Setting this setting to true stops that behavior
|
||||
@validateAlternativeTemplates
|
||||
By default you can add a altTemplate querystring or append a template name to the current URL which
|
||||
will make Umbraco render the content on the current page with the template you requested, for example:
|
||||
http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the
|
||||
"About Us" page with a template with the alias Home. Setting this setting to true will ensure that
|
||||
only templates that have been permitted on the document type will be allowed
|
||||
@disableFindContentByIdPath
|
||||
By default you can call any content Id in the url and show the content with that id, for example:
|
||||
http://mysite.com/1092 or http://mysite.com/1092.aspx would render the content with id 1092. Setting
|
||||
@@ -316,7 +322,7 @@
|
||||
-->
|
||||
<web.routing
|
||||
trySkipIisCustomErrors="false"
|
||||
internalRedirectPreservesTemplate="false" disableAlternativeTemplates="false" disableFindContentByIdPath="false"
|
||||
internalRedirectPreservesTemplate="false" disableAlternativeTemplates="false" validateAlternativeTemplates="false" disableFindContentByIdPath="false"
|
||||
umbracoApplicationUrl="">
|
||||
</web.routing>
|
||||
|
||||
|
||||
@@ -480,6 +480,7 @@
|
||||
<key alias="currentListViewDesc" version="7.2">The active list view data type</key>
|
||||
<key alias="createListView" version="7.2">Create custom list view</key>
|
||||
<key alias="removeListView" version="7.2">Remove custom list view</key>
|
||||
<key alias="aliasAlreadyExists">A content type, media type or member type with this alias already exists</key>
|
||||
</area>
|
||||
<area alias="renamecontainer">
|
||||
<key alias="renamed">Renamed</key>
|
||||
|
||||
@@ -480,6 +480,7 @@
|
||||
<key alias="currentListViewDesc" version="7.2">The active list view data type</key>
|
||||
<key alias="createListView" version="7.2">Create custom list view</key>
|
||||
<key alias="removeListView" version="7.2">Remove custom list view</key>
|
||||
<key alias="aliasAlreadyExists">A content type, media type or member type with this alias already exists</key>
|
||||
</area>
|
||||
<area alias="renamecontainer">
|
||||
<key alias="renamed">Renamed</key>
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Umbraco.Web
|
||||
//start the background task runner for processing instructions
|
||||
const int delayMilliseconds = 60000;
|
||||
var instructionProcessingRunner = new BackgroundTaskRunner<IBackgroundTask>("InstructionProcessing", ApplicationContext.ProfilingLogger.Logger);
|
||||
var instructionProcessingTask = new InstructionProcessing(instructionProcessingRunner, this, _appContext.ScopeProvider, delayMilliseconds, Options.ThrottleSeconds * 1000);
|
||||
var instructionProcessingTask = new InstructionProcessing(instructionProcessingRunner, this, _appContext.ScopeProvider, ApplicationContext.ProfilingLogger.Logger, delayMilliseconds, Options.ThrottleSeconds * 1000);
|
||||
instructionProcessingRunner.TryAdd(instructionProcessingTask);
|
||||
e.Add(instructionProcessingTask);
|
||||
}
|
||||
@@ -78,18 +78,36 @@ namespace Umbraco.Web
|
||||
{
|
||||
private readonly DatabaseServerMessenger _messenger;
|
||||
private readonly IScopeProvider _scopeProvider;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public InstructionProcessing(IBackgroundTaskRunner<RecurringTaskBase> runner,
|
||||
DatabaseServerMessenger messenger,
|
||||
IScopeProvider scopeProvider,
|
||||
ILogger logger,
|
||||
int delayMilliseconds, int periodMilliseconds)
|
||||
: base(runner, delayMilliseconds, periodMilliseconds)
|
||||
{
|
||||
_messenger = messenger;
|
||||
_scopeProvider = scopeProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override bool PerformRun()
|
||||
{
|
||||
try
|
||||
{
|
||||
TryPerformRun();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error<InstructionProcessing>("Failed (will repeat).", e);
|
||||
}
|
||||
|
||||
//return true to repeat
|
||||
return true;
|
||||
}
|
||||
|
||||
private void TryPerformRun()
|
||||
{
|
||||
// beware!
|
||||
// DatabaseServerMessenger uses _appContext.DatabaseContext.Database without creating
|
||||
@@ -102,8 +120,6 @@ namespace Umbraco.Web
|
||||
_messenger.Sync();
|
||||
scope.Complete();
|
||||
}
|
||||
//return true to repeat
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool IsAsync
|
||||
@@ -167,7 +183,7 @@ namespace Umbraco.Web
|
||||
// can get the http context from it
|
||||
var httpContext = (UmbracoContext.Current == null ? null : UmbracoContext.Current.HttpContext)
|
||||
// if this is null, it could be that an async thread is calling this method that we weren't aware of and the UmbracoContext
|
||||
// wasn't ensured at the beginning of the thread. We can try to see if the HttpContext.Current is available which might be
|
||||
// wasn't ensured at the beginning of the thread. We can try to see if the HttpContext.Current is available which might be
|
||||
// the case if the asp.net synchronization context has kicked in
|
||||
?? (HttpContext.Current == null ? null : new HttpContextWrapper(HttpContext.Current));
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace Umbraco.Web.Editors
|
||||
: Request.CreateNotificationValidationErrorResponse(result.Exception.Message);
|
||||
}
|
||||
|
||||
public DocumentTypeCollectionDisplay PostCreateCollection(int parentId, string collectionName, string collectionItemName, string collectionIcon, string collectionItemIcon)
|
||||
public DocumentTypeCollectionDisplay PostCreateCollection(int parentId, string collectionName, bool collectionCreateTemplate, string collectionItemName, bool collectionItemCreateTemplate, string collectionIcon, string collectionItemIcon)
|
||||
{
|
||||
var storeInContainer = false;
|
||||
var allowUnderDocType = -1;
|
||||
@@ -226,20 +226,38 @@ namespace Umbraco.Web.Editors
|
||||
// create item doctype
|
||||
var itemDocType = new ContentType(parentId);
|
||||
itemDocType.Name = collectionItemName;
|
||||
itemDocType.Alias = collectionItemName.ToSafeAlias();
|
||||
itemDocType.Alias = collectionItemName.ToSafeAlias(true);
|
||||
itemDocType.Icon = collectionItemIcon;
|
||||
|
||||
// create item doctype template
|
||||
if (collectionItemCreateTemplate)
|
||||
{
|
||||
var template = CreateTemplateForContentType(itemDocType.Alias, itemDocType.Name);
|
||||
itemDocType.SetDefaultTemplate(template);
|
||||
}
|
||||
|
||||
// save item doctype
|
||||
Services.ContentTypeService.Save(itemDocType);
|
||||
|
||||
// create collection doctype
|
||||
var collectionDocType = new ContentType(parentId);
|
||||
collectionDocType.Name = collectionName;
|
||||
collectionDocType.Alias = collectionName.ToSafeAlias();
|
||||
collectionDocType.Alias = collectionName.ToSafeAlias(true);
|
||||
collectionDocType.Icon = collectionIcon;
|
||||
collectionDocType.IsContainer = true;
|
||||
collectionDocType.AllowedContentTypes = new List<ContentTypeSort>()
|
||||
{
|
||||
new ContentTypeSort(itemDocType.Id, 0)
|
||||
};
|
||||
|
||||
// create collection doctype template
|
||||
if (collectionCreateTemplate)
|
||||
{
|
||||
var template = CreateTemplateForContentType(collectionDocType.Alias, collectionDocType.Name);
|
||||
collectionDocType.SetDefaultTemplate(template);
|
||||
}
|
||||
|
||||
// save collection doctype
|
||||
Services.ContentTypeService.Save(collectionDocType);
|
||||
|
||||
// test if the parent id exist and then allow the collection underneath
|
||||
@@ -252,8 +270,6 @@ namespace Umbraco.Web.Editors
|
||||
allowedCts.Add(new ContentTypeSort(collectionDocType.Id, allowedCts.Count()));
|
||||
parentCt.AllowedContentTypes = allowedCts;
|
||||
Services.ContentTypeService.Save(parentCt);
|
||||
} else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,19 +292,7 @@ namespace Umbraco.Web.Editors
|
||||
//create a default template if it doesnt exist -but only if default template is == to the content type
|
||||
if (ctSave.DefaultTemplate.IsNullOrWhiteSpace() == false && ctSave.DefaultTemplate == ctSave.Alias)
|
||||
{
|
||||
var template = Services.FileService.GetTemplate(ctSave.Alias);
|
||||
if (template == null)
|
||||
{
|
||||
var tryCreateTemplate = Services.FileService.CreateTemplateForContentType(ctSave.Alias, ctSave.Name);
|
||||
if (tryCreateTemplate == false)
|
||||
{
|
||||
Logger.Warn<ContentTypeController>(
|
||||
"Could not create a template for the Content Type: {0}, status: {1}",
|
||||
() => ctSave.Alias,
|
||||
() => tryCreateTemplate.Result.StatusType);
|
||||
}
|
||||
template = tryCreateTemplate.Result.Entity;
|
||||
}
|
||||
var template = CreateTemplateForContentType(ctSave.Alias, ctSave.Name);
|
||||
|
||||
// If the alias has been manually updated before the first save,
|
||||
// make sure to also update the first allowed template, as the
|
||||
@@ -318,6 +322,26 @@ namespace Umbraco.Web.Editors
|
||||
return display;
|
||||
}
|
||||
|
||||
private ITemplate CreateTemplateForContentType(string contentTypeAlias, string contentTypeName)
|
||||
{
|
||||
var template = Services.FileService.GetTemplate(contentTypeAlias);
|
||||
if (template == null)
|
||||
{
|
||||
var tryCreateTemplate = Services.FileService.CreateTemplateForContentType(contentTypeAlias, contentTypeName);
|
||||
if (tryCreateTemplate == false)
|
||||
{
|
||||
Logger.Warn<ContentTypeController>(
|
||||
"Could not create a template for the Content Type: {0}, status: {1}",
|
||||
() => contentTypeAlias,
|
||||
() => tryCreateTemplate.Result.StatusType);
|
||||
}
|
||||
|
||||
template = tryCreateTemplate.Result.Entity;
|
||||
}
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty content type for use as a scaffold when creating a new type
|
||||
/// </summary>
|
||||
|
||||
@@ -227,9 +227,9 @@ namespace Umbraco.Web.Editors
|
||||
// works since that is based on aliases.
|
||||
var allAliases = Services.ContentTypeService.GetAllContentTypeAliases();
|
||||
var exists = allAliases.InvariantContains(contentTypeSave.Alias);
|
||||
if ((exists) && (ctId == 0 || ct.Alias != contentTypeSave.Alias))
|
||||
if (exists && (ctId == 0 || ct.Alias.InvariantEquals(contentTypeSave.Alias) == false))
|
||||
{
|
||||
ModelState.AddModelError("Alias", "A content type, media type or member type with this alias already exists");
|
||||
ModelState.AddModelError("Alias", Services.TextService.Localize("editcontenttype/aliasAlreadyExists"));
|
||||
}
|
||||
|
||||
//now let the external validators execute
|
||||
|
||||
@@ -717,15 +717,7 @@ namespace Umbraco.Web.Editors
|
||||
mediaType = result.FormData["contentTypeAlias"];
|
||||
}
|
||||
|
||||
//TODO: make the media item name "nice" since file names could be pretty ugly, we have
|
||||
// string extensions to do much of this but we'll need:
|
||||
// * Pascalcase the name (use string extensions)
|
||||
// * strip the file extension
|
||||
// * underscores to spaces
|
||||
// * probably remove 'ugly' characters - let's discuss
|
||||
// All of this logic should exist in a string extensions method and be unit tested
|
||||
// http://issues.umbraco.org/issue/U4-5572
|
||||
var mediaItemName = fileName;
|
||||
var mediaItemName = fileName.ToFriendlyName();
|
||||
|
||||
var f = mediaService.CreateMedia(mediaItemName, parentId, mediaType, Security.CurrentUser.Id);
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ namespace Umbraco.Web.Mvc
|
||||
/// <remarks></remarks>
|
||||
internal class MasterControllerFactory : DefaultControllerFactory
|
||||
{
|
||||
private readonly FilteredControllerFactoriesResolver _slaveFactories;
|
||||
private readonly FilteredControllerFactoriesResolver _replicaFactories;
|
||||
|
||||
public MasterControllerFactory(FilteredControllerFactoriesResolver factoryResolver)
|
||||
{
|
||||
_slaveFactories = factoryResolver;
|
||||
_replicaFactories = factoryResolver;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// <remarks></remarks>
|
||||
public override IController CreateController(RequestContext requestContext, string controllerName)
|
||||
{
|
||||
var factory = _slaveFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
|
||||
var factory = _replicaFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
|
||||
return factory != null
|
||||
? factory.CreateController(requestContext, controllerName)
|
||||
: base.CreateController(requestContext, controllerName);
|
||||
@@ -53,7 +53,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// <param name="controllerName">The name of the controller.</param>
|
||||
internal Type GetControllerTypeInternal(RequestContext requestContext, string controllerName)
|
||||
{
|
||||
var factory = _slaveFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
|
||||
var factory = _replicaFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
|
||||
if (factory != null)
|
||||
{
|
||||
//check to see if the factory is of type UmbracoControllerFactory which exposes the GetControllerType method so we don't have to create
|
||||
@@ -88,7 +88,7 @@ namespace Umbraco.Web.Mvc
|
||||
if (controller is Controller)
|
||||
{
|
||||
var requestContext = ((Controller)controller).ControllerContext.RequestContext;
|
||||
var factory = _slaveFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
|
||||
var factory = _replicaFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
|
||||
if (factory != null)
|
||||
{
|
||||
factory.ReleaseController(controller);
|
||||
@@ -98,4 +98,4 @@ namespace Umbraco.Web.Mvc
|
||||
if (!released) base.ReleaseController(controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,11 +129,11 @@ namespace Umbraco.Web.PublishedCache
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias)
|
||||
{
|
||||
switch (alias)
|
||||
switch (alias.ToLowerInvariant())
|
||||
{
|
||||
case "Email":
|
||||
case "email":
|
||||
return new PropertyResult("Email", Email, PropertyResultType.CustomProperty);
|
||||
case "UserName":
|
||||
case "username":
|
||||
return new PropertyResult("UserName", UserName, PropertyResultType.CustomProperty);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,12 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Examine.LuceneEngine.SearchCriteria;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Web.Routing;
|
||||
using ContentType = umbraco.cms.businesslogic.ContentType;
|
||||
@@ -130,6 +131,32 @@ namespace Umbraco.Web
|
||||
{
|
||||
var template = ApplicationContext.Current.Services.FileService.GetTemplate(content.TemplateId);
|
||||
return template == null ? string.Empty : template.Alias;
|
||||
}
|
||||
|
||||
public static bool IsAllowedTemplate(this IPublishedContent content, int templateId)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == true)
|
||||
return content.TemplateId == templateId;
|
||||
|
||||
if (content.TemplateId != templateId && UmbracoConfig.For.UmbracoSettings().WebRouting.ValidateAlternativeTemplates == true)
|
||||
{
|
||||
var publishedContentContentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(content.ContentType.Id);
|
||||
if (publishedContentContentType == null)
|
||||
throw new NullReferenceException("No content type returned for published content (contentType='" + content.ContentType.Id + "')");
|
||||
|
||||
return publishedContentContentType.IsAllowedTemplate(templateId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public static bool IsAllowedTemplate(this IPublishedContent content, string templateAlias)
|
||||
{
|
||||
var template = ApplicationContext.Current.Services.FileService.GetTemplate(templateAlias);
|
||||
var isAllowedTemplate = (template != null) ?
|
||||
content.IsAllowedTemplate(template.Id) :
|
||||
false;
|
||||
|
||||
return isAllowedTemplate;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace Umbraco.Web.Routing
|
||||
/// <remarks>If successful, also assigns the template.</remarks>
|
||||
public override bool TryFindContent(PublishedContentRequest docRequest)
|
||||
{
|
||||
const string tracePrefix = "ContentFinderByNiceUrlAndTemplate: ";
|
||||
|
||||
IPublishedContent node = null;
|
||||
string path = docRequest.Uri.GetAbsolutePathDecoded();
|
||||
|
||||
@@ -42,8 +44,16 @@ namespace Umbraco.Web.Routing
|
||||
var route = docRequest.HasDomain ? (docRequest.Domain.RootNodeId.ToString() + path) : path;
|
||||
node = FindContent(docRequest, route);
|
||||
|
||||
if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == false && node != null)
|
||||
if (node.IsAllowedTemplate(template.Id))
|
||||
{
|
||||
docRequest.TemplateModel = template;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Warn<ContentFinderByNiceUrlAndTemplate>("Configuration settings prevent template \"{0}\" from showing for node \"{1}\"", () => templateAlias, () => node.Id);
|
||||
docRequest.PublishedContent = null;
|
||||
node = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@ using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
using umbraco;
|
||||
@@ -651,9 +652,8 @@ namespace Umbraco.Web.Routing
|
||||
// only if the published content is the initial once, else the alternate template
|
||||
// does not apply
|
||||
// + optionnally, apply the alternate template on internal redirects
|
||||
var useAltTemplate = _webRoutingSection.DisableAlternativeTemplates == false
|
||||
&& (_pcr.IsInitialPublishedContent
|
||||
|| (_webRoutingSection.InternalRedirectPreservesTemplate && _pcr.IsInternalRedirectPublishedContent));
|
||||
var useAltTemplate = _pcr.IsInitialPublishedContent
|
||||
|| (_webRoutingSection.InternalRedirectPreservesTemplate && _pcr.IsInternalRedirectPublishedContent);
|
||||
string altTemplate = useAltTemplate
|
||||
? _routingContext.UmbracoContext.HttpContext.Request[Constants.Conventions.Url.AltTemplate]
|
||||
: null;
|
||||
@@ -675,20 +675,11 @@ namespace Umbraco.Web.Routing
|
||||
|
||||
var templateId = _pcr.PublishedContent.TemplateId;
|
||||
|
||||
if (templateId > 0)
|
||||
{
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}Look for template id={1}", () => tracePrefix, () => templateId);
|
||||
var template = ApplicationContext.Current.Services.FileService.GetTemplate(templateId);
|
||||
if (template == null)
|
||||
throw new InvalidOperationException("The template with Id " + templateId + " does not exist, the page cannot render");
|
||||
_pcr.TemplateModel = template;
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}Got template id={1} alias=\"{2}\"", () => tracePrefix, () => template.Id, () => template.Alias);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}No specified template.", () => tracePrefix);
|
||||
}
|
||||
}
|
||||
// This code was moved to GetTemplateModel to allow the same functionality on a failed altTemplate (U4-8550)
|
||||
// The only change is a diffent logger prefix and null will be set to _pcr.TemplateModel if the templateId is <= 0
|
||||
// rather than no set taking place
|
||||
_pcr.TemplateModel = GetTemplateModel(_pcr.PublishedContent.TemplateId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have an alternate template specified. lookup the template with that alias
|
||||
@@ -701,16 +692,19 @@ namespace Umbraco.Web.Routing
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}Has a template already, but also an alternate template.", () => tracePrefix);
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}Look for alternate template alias=\"{1}\"", () => tracePrefix, () => altTemplate);
|
||||
|
||||
var template = ApplicationContext.Current.Services.FileService.GetTemplate(altTemplate);
|
||||
if (template != null)
|
||||
{
|
||||
_pcr.TemplateModel = template;
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}Got template id={1} alias=\"{2}\"", () => tracePrefix, () => template.Id, () => template.Alias);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}The template with alias=\"{1}\" does not exist, ignoring.", () => tracePrefix, () => altTemplate);
|
||||
}
|
||||
if (_pcr.PublishedContent.IsAllowedTemplate(altTemplate))
|
||||
{
|
||||
var template = ApplicationContext.Current.Services.FileService.GetTemplate(altTemplate);
|
||||
if (template != null)
|
||||
_pcr.TemplateModel = template;
|
||||
else
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}The template with alias=\"{1}\" does not exist, ignoring.", () => tracePrefix, () => altTemplate);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Warn<PublishedContentRequestEngine>("{0}Configuration settings prevent template \"{1}\" from showing for node \"{2}\"", () => tracePrefix, () => altTemplate, () => _pcr.PublishedContent.Id);
|
||||
_pcr.TemplateModel = GetTemplateModel(_pcr.PublishedContent.TemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
if (_pcr.HasTemplate == false)
|
||||
@@ -732,11 +726,31 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Follows external redirection through <c>umbracoRedirect</c> document property.
|
||||
/// </summary>
|
||||
/// <remarks>As per legacy, if the redirect does not work, we just ignore it.</remarks>
|
||||
private void FollowExternalRedirect()
|
||||
private ITemplate GetTemplateModel(int templateId)
|
||||
{
|
||||
const string tracePrefix = "GetTemplateModel: ";
|
||||
|
||||
if (templateId > 0)
|
||||
{
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}Look for template id={1}", () => tracePrefix, () => templateId);
|
||||
var template = ApplicationContext.Current.Services.FileService.GetTemplate(templateId);
|
||||
if (template == null)
|
||||
throw new InvalidOperationException("The template with Id " + templateId + " does not exist, the page cannot render");
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}Got template id={1} alias=\"{2}\"", () => tracePrefix, () => template.Id, () => template.Alias);
|
||||
return template;
|
||||
}
|
||||
else
|
||||
{
|
||||
ProfilingLogger.Logger.Debug<PublishedContentRequestEngine>("{0}No specified template.", () => tracePrefix);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Follows external redirection through <c>umbracoRedirect</c> document property.
|
||||
/// </summary>
|
||||
/// <remarks>As per legacy, if the redirect does not work, we just ignore it.</remarks>
|
||||
private void FollowExternalRedirect()
|
||||
{
|
||||
if (_pcr.HasPublishedContent == false) return;
|
||||
|
||||
|
||||
@@ -241,8 +241,8 @@ namespace Umbraco.Web.Routing
|
||||
/// <param name="cacheRefresherEventArgs"></param>
|
||||
private void PageCacheRefresher_CacheUpdated(PageCacheRefresher sender, CacheRefresherEventArgs cacheRefresherEventArgs)
|
||||
{
|
||||
// only on master / single, not on slaves!
|
||||
if (IsSlaveServer) return;
|
||||
// only on master / single, not on replicas!
|
||||
if (IsReplicaServer) return;
|
||||
|
||||
// simply getting OldRoutes will register it in the request cache,
|
||||
// so whatever we do with it, try/finally it to ensure it's cleared
|
||||
@@ -299,8 +299,8 @@ namespace Umbraco.Web.Routing
|
||||
return route == null;
|
||||
}
|
||||
|
||||
// gets a value indicating whether server is 'slave'
|
||||
private static bool IsSlaveServer
|
||||
// gets a value indicating whether server is 'replica'
|
||||
private static bool IsReplicaServer
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Umbraco.Web.Scheduling
|
||||
switch (_appContext.GetCurrentServerRole())
|
||||
{
|
||||
case ServerRole.Slave:
|
||||
LogHelper.Debug<HealthCheckNotifier>("Does not run on slave servers.");
|
||||
LogHelper.Debug<HealthCheckNotifier>("Does not run on replica servers.");
|
||||
return true; // DO repeat, server role can change
|
||||
case ServerRole.Unknown:
|
||||
LogHelper.Debug<HealthCheckNotifier>("Does not run on servers with unknown role.");
|
||||
@@ -80,4 +80,4 @@ namespace Umbraco.Web.Scheduling
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Umbraco.Web.Scheduling
|
||||
switch (_appContext.GetCurrentServerRole())
|
||||
{
|
||||
case ServerRole.Slave:
|
||||
Logger.Debug<ScheduledPublishing>("Does not run on slave servers.");
|
||||
Logger.Debug<ScheduledPublishing>("Does not run on replica servers.");
|
||||
return true; // DO repeat, server role can change
|
||||
case ServerRole.Unknown:
|
||||
Logger.Debug<ScheduledPublishing>("Does not run on servers with unknown role.");
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Umbraco.Web.Scheduling
|
||||
switch (_appContext.GetCurrentServerRole())
|
||||
{
|
||||
case ServerRole.Slave:
|
||||
LogHelper.Debug<LogScrubber>("Does not run on slave servers.");
|
||||
LogHelper.Debug<LogScrubber>("Does not run on replica servers.");
|
||||
return true; // DO repeat, server role can change
|
||||
case ServerRole.Unknown:
|
||||
LogHelper.Debug<LogScrubber>("Does not run on servers with unknown role.");
|
||||
@@ -94,4 +94,4 @@ namespace Umbraco.Web.Scheduling
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Web.Scheduling
|
||||
switch (_appContext.GetCurrentServerRole())
|
||||
{
|
||||
case ServerRole.Slave:
|
||||
Logger.Debug<ScheduledPublishing>("Does not run on slave servers.");
|
||||
Logger.Debug<ScheduledPublishing>("Does not run on replica servers.");
|
||||
return true; // DO repeat, server role can change
|
||||
case ServerRole.Unknown:
|
||||
Logger.Debug<ScheduledPublishing>("Does not run on servers with unknown role.");
|
||||
@@ -106,4 +106,4 @@ namespace Umbraco.Web.Scheduling
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Umbraco.Web.Scheduling
|
||||
switch (_appContext.GetCurrentServerRole())
|
||||
{
|
||||
case ServerRole.Slave:
|
||||
LogHelper.Debug<ScheduledTasks>("Does not run on slave servers.");
|
||||
LogHelper.Debug<ScheduledTasks>("Does not run on replica servers.");
|
||||
return true; // DO repeat, server role can change
|
||||
case ServerRole.Unknown:
|
||||
LogHelper.Debug<ScheduledTasks>("Does not run on servers with unknown role.");
|
||||
|
||||
@@ -104,13 +104,13 @@ namespace Umbraco.Web.Scheduling
|
||||
_keepAliveRunner.TryAdd(tasks[0]);
|
||||
|
||||
// scheduled publishing/unpublishing
|
||||
// install on all, will only run on non-slaves servers
|
||||
// install on all, will only run on non-replica servers
|
||||
_publishingRunner.TryAdd(tasks[1]);
|
||||
|
||||
_tasksRunner.TryAdd(tasks[2]);
|
||||
|
||||
// log scrubbing
|
||||
// install on all, will only run on non-slaves servers
|
||||
// install on all, will only run on non-replica servers
|
||||
_scrubberRunner.TryAdd(tasks[3]);
|
||||
|
||||
if (healthCheckConfig.NotificationSettings.Enabled)
|
||||
|
||||
@@ -647,10 +647,15 @@ namespace Umbraco.Web.Security
|
||||
var provider = _membershipProvider;
|
||||
|
||||
string username;
|
||||
|
||||
if (provider.IsUmbracoMembershipProvider())
|
||||
{
|
||||
var member = GetCurrentPersistedMember();
|
||||
// If a member could not be resolved from the provider, we are clearly not authorized and can break right here
|
||||
if (member == null)
|
||||
return false;
|
||||
username = member.Username;
|
||||
|
||||
// If types defined, check member is of one of those types
|
||||
var allowTypesList = allowTypes as IList<string> ?? allowTypes.ToList();
|
||||
if (allowTypesList.Any(allowType => allowType != string.Empty))
|
||||
@@ -669,6 +674,9 @@ namespace Umbraco.Web.Security
|
||||
else
|
||||
{
|
||||
var member = provider.GetCurrentUser();
|
||||
// If a member could not be resolved from the provider, we are clearly not authorized and can break right here
|
||||
if (member == null)
|
||||
return false;
|
||||
username = member.UserName;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -32,6 +34,8 @@ namespace Umbraco.Web.Trees
|
||||
[HttpQueryStringFilter("queryStrings")]
|
||||
public async Task<SectionRootNode> GetApplicationTrees(string application, string tree, FormDataCollection queryStrings, bool onlyInitialized = true)
|
||||
{
|
||||
application = application.CleanForXss();
|
||||
|
||||
if (string.IsNullOrEmpty(application)) throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
@@ -39,7 +43,7 @@ namespace Umbraco.Web.Trees
|
||||
//find all tree definitions that have the current application alias
|
||||
var appTrees = Services.ApplicationTreeService.GetApplicationTrees(application, onlyInitialized).ToArray();
|
||||
|
||||
if (string.IsNullOrEmpty(tree) == false || appTrees.Length == 1)
|
||||
if (string.IsNullOrEmpty(tree) == false || appTrees.Length == 1 || appTrees.Any() == false)
|
||||
{
|
||||
var apptree = string.IsNullOrEmpty(tree) == false
|
||||
? appTrees.SingleOrDefault(x => x.Alias == tree)
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
|
||||
menu.Items.Add(new MenuItem("rename", Services.TextService.Localize(String.Format("actions/{0}", "rename")))
|
||||
menu.Items.Add(new MenuItem("rename", Services.TextService.Localize(String.Format("actions/rename")))
|
||||
{
|
||||
Icon = "icon icon-edit"
|
||||
});
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
|
||||
menu.Items.Add(new MenuItem("rename", Services.TextService.Localize(String.Format("actions/{0}", "rename")))
|
||||
menu.Items.Add(new MenuItem("rename", Services.TextService.Localize(String.Format("actions/rename")))
|
||||
{
|
||||
Icon = "icon icon-edit"
|
||||
});
|
||||
@@ -139,4 +139,4 @@ namespace Umbraco.Web.Trees
|
||||
return Mapper.Map<IEnumerable<SearchResultItem>>(results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
|
||||
menu.Items.Add(new MenuItem("rename", Services.TextService.Localize(String.Format("actions/{0}", "rename")))
|
||||
menu.Items.Add(new MenuItem("rename", Services.TextService.Localize(String.Format("actions/rename")))
|
||||
{
|
||||
Icon = "icon icon-edit"
|
||||
});
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace umbraco.IO
|
||||
get { return Umbraco.Core.IO.SystemFiles.TinyMceConfig; }
|
||||
}
|
||||
|
||||
[Obsolete("This file is no longer used and should not be accessed!")]
|
||||
public static string MetablogConfig
|
||||
{
|
||||
get { return Umbraco.Core.IO.SystemFiles.MetablogConfig; }
|
||||
|
||||