Merge branch 'dev-v7' into temp-U4-5963

Conflicts:
	src/Umbraco.Web.UI.Client/src/controllers/main.controller.js
This commit is contained in:
Sebastiaan Janssen
2015-10-28 16:56:40 +01:00
50 changed files with 578 additions and 329 deletions

View File

@@ -36,7 +36,7 @@ namespace Umbraco.Core.Configuration
//make this volatile so that we can ensure thread safety with a double check lock
private static volatile string _reservedUrlsCache;
private static string _reservedPathsCache;
private static StartsWithContainer _reservedList = new StartsWithContainer();
private static HashSet<string> _reservedList = new HashSet<string>();
private static string _reservedPaths;
private static string _reservedUrls;
//ensure the built on (non-changeable) reserved paths are there at all times
@@ -768,37 +768,30 @@ namespace Umbraco.Core.Configuration
_reservedPathsCache = GlobalSettings.ReservedPaths;
_reservedUrlsCache = GlobalSettings.ReservedUrls;
string _root = SystemDirectories.Root.Trim().ToLower();
// add URLs and paths to a new list
StartsWithContainer _newReservedList = new StartsWithContainer();
foreach (string reservedUrl in _reservedUrlsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
var newReservedList = new HashSet<string>();
foreach (var reservedUrlTrimmed in _reservedUrlsCache
.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim().ToLowerInvariant())
.Where(x => x.IsNullOrWhiteSpace() == false)
.Select(reservedUrl => IOHelper.ResolveUrl(reservedUrl).Trim().EnsureStartsWith("/"))
.Where(reservedUrlTrimmed => reservedUrlTrimmed.IsNullOrWhiteSpace() == false))
{
if (string.IsNullOrWhiteSpace(reservedUrl))
continue;
//resolves the url to support tilde chars
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl.Trim()).Trim().ToLower();
if (reservedUrlTrimmed.Length > 0)
_newReservedList.Add(reservedUrlTrimmed);
newReservedList.Add(reservedUrlTrimmed);
}
foreach (string reservedPath in _reservedPathsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
foreach (var reservedPathTrimmed in _reservedPathsCache
.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim().ToLowerInvariant())
.Where(x => x.IsNullOrWhiteSpace() == false)
.Select(reservedPath => IOHelper.ResolveUrl(reservedPath).Trim().EnsureStartsWith("/").EnsureEndsWith("/"))
.Where(reservedPathTrimmed => reservedPathTrimmed.IsNullOrWhiteSpace() == false))
{
bool trimEnd = !reservedPath.EndsWith("/");
if (string.IsNullOrWhiteSpace(reservedPath))
continue;
//resolves the url to support tilde chars
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath.Trim()).Trim().ToLower();
if (reservedPathTrimmed.Length > 0)
_newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/"));
newReservedList.Add(reservedPathTrimmed);
}
// use the new list from now on
_reservedList = _newReservedList;
_reservedList = newReservedList;
}
}
}
@@ -806,107 +799,17 @@ namespace Umbraco.Core.Configuration
//The url should be cleaned up before checking:
// * If it doesn't contain an '.' in the path then we assume it is a path based URL, if that is the case we should add an trailing '/' because all of our reservedPaths use a trailing '/'
// * We shouldn't be comparing the query at all
var pathPart = url.Split('?')[0];
if (!pathPart.Contains(".") && !pathPart.EndsWith("/"))
var pathPart = url.Split(new[] {'?'}, StringSplitOptions.RemoveEmptyEntries)[0].ToLowerInvariant();
if (pathPart.Contains(".") == false)
{
pathPart += "/";
pathPart = pathPart.EnsureEndsWith('/');
}
// return true if url starts with an element of the reserved list
return _reservedList.StartsWith(pathPart.ToLowerInvariant());
return _reservedList.Any(x => pathPart.InvariantStartsWith(x));
}
/// <summary>
/// Structure that checks in logarithmic time
/// if a given string starts with one of the added keys.
/// </summary>
private class StartsWithContainer
{
/// <summary>Internal sorted list of keys.</summary>
public SortedList<string, string> _list
= new SortedList<string, string>(StartsWithComparator.Instance);
/// <summary>
/// Adds the specified new key.
/// </summary>
/// <param name="newKey">The new key.</param>
public void Add(string newKey)
{
// if the list already contains an element that begins with newKey, return
if (String.IsNullOrEmpty(newKey) || StartsWith(newKey))
return;
// create a new collection, so the old one can still be accessed
SortedList<string, string> newList
= new SortedList<string, string>(_list.Count + 1, StartsWithComparator.Instance);
// add only keys that don't already start with newKey, others are unnecessary
foreach (string key in _list.Keys)
if (!key.StartsWith(newKey))
newList.Add(key, null);
// add the new key
newList.Add(newKey, null);
// update the list (thread safe, _list was never in incomplete state)
_list = newList;
}
/// <summary>
/// Checks if the given string starts with any of the added keys.
/// </summary>
/// <param name="target">The target.</param>
/// <returns>true if a key is found that matches the start of target</returns>
/// <remarks>
/// Runs in O(s*log(n)), with n the number of keys and s the length of target.
/// </remarks>
public bool StartsWith(string target)
{
return _list.ContainsKey(target);
}
/// <summary>Comparator that tests if a string starts with another.</summary>
/// <remarks>Not a real comparator, since it is not reflexive. (x==y does not imply y==x)</remarks>
private sealed class StartsWithComparator : IComparer<string>
{
/// <summary>Default string comparer.</summary>
private readonly static Comparer<string> _stringComparer = Comparer<string>.Default;
/// <summary>Gets an instance of the StartsWithComparator.</summary>
public static readonly StartsWithComparator Instance = new StartsWithComparator();
/// <summary>
/// Tests if whole begins with all characters of part.
/// </summary>
/// <param name="part">The part.</param>
/// <param name="whole">The whole.</param>
/// <returns>
/// Returns 0 if whole starts with part, otherwise performs standard string comparison.
/// </returns>
public int Compare(string part, string whole)
{
// let the default string comparer deal with null or when part is not smaller then whole
if (part == null || whole == null || part.Length >= whole.Length)
return _stringComparer.Compare(part, whole);
////ensure both have a / on the end
//part = part.EndsWith("/") ? part : part + "/";
//whole = whole.EndsWith("/") ? whole : whole + "/";
//if (part.Length >= whole.Length)
// return _stringComparer.Compare(part, whole);
// loop through all characters that part and whole have in common
int pos = 0;
bool match;
do
{
match = (part[pos] == whole[pos]);
} while (match && ++pos < part.Length);
// return result of last comparison
return match ? 0 : (part[pos] < whole[pos] ? -1 : 1);
}
}
}
}

View File

@@ -0,0 +1,38 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeOne
{
/// <summary>
/// This fixes the storage of user languages from the old format like en_us to en-US
/// </summary>
[Migration("7.3.1", 0, GlobalSettings.UmbracoMigrationName)]
public class UpdateUserLanguagesToIsoCode : MigrationBase
{
public UpdateUserLanguagesToIsoCode(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
{
}
public override void Up()
{
var userData = Context.Database.Fetch<UserDto>(new Sql().Select("*").From<UserDto>(SqlSyntax));
foreach (var user in userData.Where(x => x.UserLanguage.Contains("_")))
{
var languageParts = user.UserLanguage.Split('_');
if (languageParts.Length == 2)
{
Update.Table("umbracoUser")
.Set(new {userLanguage = languageParts[0] + "-" + languageParts[1].ToUpperInvariant()})
.Where(new {id = user.Id});
}
}
}
public override void Down()
{
}
}
}

View File

@@ -2,6 +2,7 @@ using System;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Maps a property source value to a data object.
/// </summary>
// todo: drop IPropertyEditorValueConverter support (when?).

View File

@@ -187,7 +187,13 @@ namespace Umbraco.Core.Sync
using (_profilingLogger.DebugDuration<DatabaseServerMessenger>("Syncing from database..."))
{
ProcessDatabaseInstructions();
switch (_appContext.GetCurrentServerRole())
{
case ServerRole.Single:
case ServerRole.Master:
PruneOldInstructions();
break;
}
}
}
finally

View File

@@ -15,7 +15,12 @@ namespace Umbraco.Core.Sync
// but at the moment it is exposed in CacheRefresher webservice
// so for the time being we keep it as-is for backward compatibility reasons
// need the public one so it can be de-serialized
// need this public, parameter-less constructor so the web service messenger
// can de-serialize the instructions it receives
public RefreshInstruction()
{ }
// need this public one so it can be de-serialized - used by the Json thing
// otherwise, should use GetInstructions(...)
public RefreshInstruction(Guid refresherId, RefreshMethodType refreshType, Guid guidId, int intId, string jsonIds, string jsonPayload)
{

View File

@@ -435,6 +435,7 @@
<Compile Include="Media\Exif\TIFFHeader.cs" />
<Compile Include="Media\Exif\TIFFStrip.cs" />
<Compile Include="Media\Exif\Utility.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeOne\UpdateUserLanguagesToIsoCode.cs" />
<Compile Include="Persistence\RecordPersistenceType.cs" />
<Compile Include="Persistence\Relators\AccessRulesRelator.cs" />
<Compile Include="Persistence\Repositories\AuditRepository.cs" />

View File

@@ -1163,6 +1163,36 @@ namespace Umbraco.Tests.Services
Assert.That(propertyGroup.ParentId.HasValue, Is.False);
}
[Test]
public void Can_Remove_PropertyGroup_Without_Removing_Property_Types()
{
var service = ServiceContext.ContentTypeService;
var basePage = (IContentType)MockedContentTypes.CreateBasicContentType();
service.Save(basePage);
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author")
{
Name = "Author",
Description = "",
Mandatory = false,
SortOrder = 1,
DataTypeDefinitionId = -88
};
var authorAdded = basePage.AddPropertyType(authorPropertyType, "Content");
service.Save(basePage);
basePage = service.GetContentType(basePage.Id);
var totalPt = basePage.PropertyTypes.Count();
basePage.RemovePropertyGroup("Content");
service.Save(basePage);
basePage = service.GetContentType(basePage.Id);
Assert.AreEqual(totalPt, basePage.PropertyTypes.Count());
}
[Test]
public void Can_Add_PropertyGroup_With_Same_Name_On_Parent_and_Child()
{

View File

@@ -8,7 +8,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
{
public static Content CreateSimpleContent(IContentType contentType)
{
var content = new Content("Home", -1, contentType) { Language = "en-US", Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0 };
var content = new Content("Home", -1, contentType) { Language = "en-US", Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0, Path = "-1" };
object obj =
new
{

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -13,7 +13,9 @@ angular.module("umbraco.directives")
restrict: 'E',
replace: true,
templateUrl: 'views/directives/umb-property.html',
link: function(scope) {
scope.propertyAlias = Umbraco.Sys.ServerVariables.isDebuggingEnabled === true ? scope.property.alias : null;
},
//Define a controller for this directive to expose APIs to other directives
controller: function ($scope, $timeout) {

View File

@@ -139,6 +139,12 @@ function entityResource($q, $http, umbRequestHelper) {
_.each(ids, function(item) {
query += "ids=" + item + "&";
});
// if ids array is empty we need a empty variable in the querystring otherwise the service returns a error
if (ids.length === 0) {
query += "ids=&";
}
query += "type=" + type;
return umbRequestHelper.resourcePromise(

View File

@@ -13,7 +13,11 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $
//the null is important because we do an explicit bool check on this in the view
//the avatar is by default the umbraco logo
$scope.authenticated = null;
$scope.avatar = "assets/img/application/logo.png";
$scope.avatar = [
{ value: "assets/img/application/logo.png" },
{ value: "assets/img/application/logo@2x.png" },
{ value: "assets/img/application/logo@3x.png" }
];
$scope.touchDevice = appState.getGlobalState("touchDevice");
@@ -95,7 +99,14 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $
$scope.$apply(function () {
//this can be null if they time out
if ($scope.user && $scope.user.emailHash) {
$scope.avatar = "https://www.gravatar.com/avatar/" + $scope.user.emailHash + ".jpg?s=64&d=mm";
var avatarBaseUrl = "https://www.gravatar.com/avatar/",
hash = $scope.user.emailHash;
$scope.avatar = [
{ value: avatarBaseUrl + hash + ".jpg?s=30&d=mm" },
{ value: avatarBaseUrl + hash + ".jpg?s=60&d=mm" },
{ value: avatarBaseUrl + hash + ".jpg?s=90&d=mm" }
];
}
});
$("#avatar-img").fadeTo(1000, 1);

View File

@@ -81,8 +81,8 @@ ul.sections li.avatar a {
}
ul.sections li.avatar a img {
border-radius: 16px;
width: 30px
border-radius: 50%;
width: 30px;
}
.faded ul.sections li {

View File

@@ -7,6 +7,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
searchText = value + "...";
});
$scope.recursive = true;
$scope.relateToOriginal = false;
$scope.dialogTreeEventHandler = $({});
$scope.busy = false;
@@ -95,7 +96,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
$scope.busy = true;
$scope.error = false;
contentResource.copy({ parentId: $scope.target.id, id: node.id, relateToOriginal: $scope.relateToOriginal })
contentResource.copy({ parentId: $scope.target.id, id: node.id, relateToOriginal: $scope.relateToOriginal, recursive: $scope.recursive })
.then(function (path) {
$scope.error = false;
$scope.success = true;

View File

@@ -56,6 +56,12 @@
</umb-control-group>
</umb-pane>
<umb-pane>
<umb-control-group label="Include descendants">
<input type="checkbox" ng-model="$parent.$parent.recursive" />
</umb-control-group>
</umb-pane>
</div>
</div>
</div>

View File

@@ -5,7 +5,7 @@
<val-property-msg property="property"></val-property-msg>
<div class="umb-el-wrap">
<label class="control-label" ng-hide="property.hideLabel" for="{{property.alias}}">
<label class="control-label" ng-hide="property.hideLabel" for="{{property.alias}}" ng-attr-title="{{propertyAlias}}">
{{property.label}}
<small ng-bind-html="property.description"></small>
</label>

View File

@@ -3,7 +3,7 @@
<ul class="sections">
<li class="avatar">
<a href="#" ng-click="avatarClick()" hotkey="ctrl+shift+u" title="{{user.name}}" prevent-default>
<img id="avatar-img" ng-src="{{avatar}}" />
<img id="avatar-img" ng-src="{{avatar[0].value}}" ng-srcset="{{avatar[1].value}} 2x, {{avatar[2].value}} 3x" />
</a>
</li>
<li ng-repeat="section in sections | limitTo: maxSections" ng-class="{current: section.alias == currentSection}">

View File

@@ -2,13 +2,29 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.UrlListController"
function($rootScope, $scope, $filter) {
function formatDisplayValue() {
if (angular.isArray($scope.model.value)) {
//it's the json value
$scope.renderModel = _.map($scope.model.value, function (item) {
return {
url: item.url,
linkText: item.linkText,
urlTarget: (item.target) ? item.target : "_blank",
icon: (item.icon) ? item.icon : "icon-out"
};
});
}
else {
//it's the default csv value
$scope.renderModel = _.map($scope.model.value.split(","), function (item) {
return {
url: item,
urlTarget: ($scope.config && $scope.config.target) ? $scope.config.target : "_blank"
linkText: "",
urlTarget: ($scope.config && $scope.config.target) ? $scope.config.target : "_blank",
icon: ($scope.config && $scope.config.icon) ? $scope.config.icon : "icon-out"
};
});
}
}
$scope.getUrl = function(valueUrl) {
if (valueUrl.indexOf("/") >= 0) {

View File

@@ -1,7 +1,11 @@
<div ng-controller="Umbraco.PropertyEditors.UrlListController">
<ul class="nav nav-stacked">
<li ng-repeat="value in renderModel">
<a href="{{getUrl(value.url)}}" prevent-default="{{value.url.indexOf('/') == -1}}" target="{{value.urlTarget}}"><i class="icon-out"></i> {{value.url}}</a>
<a href="{{getUrl(value.url)}}" prevent-default="{{value.url.indexOf('/') == -1}}" target="{{value.urlTarget}}">
<i ng-class="value.icon"></i>
<span ng-if="value.linkText">{{value.linkText}}</span>
<span ng-if="!value.linkText">{{value.url}}</span>
</a>
</li>
</ul>
</div>

View File

@@ -7,7 +7,7 @@
</root>
<appender name="rollingFile" type="log4net.Appender.RollingFileAppender">
<file value="App_Data\Logs\UmbracoTraceLog.txt" />
<file type="log4net.Util.PatternString" value="App_Data\Logs\UmbracoTraceLog.%property{log4net:HostName}.txt" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true" />
<rollingStyle value="Date" />

View File

@@ -7,7 +7,7 @@
</root>
<appender name="rollingFile" type="log4net.Appender.RollingFileAppender">
<file value="App_Data\Logs\UmbracoTraceLog.txt" />
<file type="log4net.Util.PatternString" value="App_Data\Logs\UmbracoTraceLog.%property{log4net:HostName}.txt" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true" />
<rollingStyle value="Date" />

View File

@@ -53,7 +53,7 @@
<key alias="domainUpdated">Domain '%0%' has been updated</key>
<key alias="orEdit">Edit Current Domains</key>
<key alias="domainHelp"><![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
"https://www.example.com/".<br /><br />One-level paths in domains are supported, eg. "example.com/en". However, they
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
should be avoided. Better use the culture setting above.]]></key>
<key alias="inherit">Inherit</key>
<key alias="setLanguage">Culture</key>

View File

@@ -53,7 +53,7 @@
<key alias="domainUpdated">Domain '%0%' has been updated</key>
<key alias="orEdit">Edit Current Domains</key>
<key alias="domainHelp"><![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
"https://www.example.com/".<br /><br />One-level paths in domains are supported, eg. "example.com/en". However, they
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
should be avoided. Better use the culture setting above.]]></key>
<key alias="inherit">Inherit</key>
<key alias="setLanguage">Culture</key>

View File

@@ -40,6 +40,7 @@
<cc1:Pane runat="server" ID="pane_domains">
<small class="help-inline"><%=umbraco.ui.Text("assignDomain", "domainHelp") %></small>
<cc1:PropertyPanel runat="server">
<table class="table domains" data-bind="visible: domains().length > 0">
<thead>
@@ -51,7 +52,7 @@
</thead>
<tbody data-bind="foreach: domains">
<tr>
<td valign="top"><input class="domain" data-bind="value: Name, uniqueName: true" /><input type="hidden" value="0" data-bind="uniqueName: true"/></td>
<td valign="top"><input class="domain duplicate" data-bind="value: Name, uniqueName: true" /><input type="hidden" value="" data-bind="uniqueName: true"/></td>
<td valign="top"><select class="language" data-bind="options: $parent.languages, optionsText: 'Code', optionsValue: 'Id', value: Lang, uniqueName: true"></select></td>
<td valign="top"><a href="#" class="btn btn-danger" data-bind="click: $parent.removeDomain"><i class="icon icon-trash"></i></a></td>
</tr>
@@ -60,7 +61,6 @@
</cc1:PropertyPanel>
<cc1:PropertyPanel runat="server">
<small data-bind="visible: domains().length == 0" class="help-inline"><%=umbraco.ui.Text("assignDomain", "domainHelp") %></small>
<button class="btn" data-bind="click: addDomain"><%=umbraco.ui.Text("assignDomain", "addNew") %></button>
</cc1:PropertyPanel>

View File

@@ -63,9 +63,17 @@
return ret;
}, self._opts.invalidDomain);
function getDuplicateMessage(val, el) {
var other = $(el).nextAll('input').val();
var msg = self._opts.duplicateDomain
if (other != "" && other != "!!!")
msg = msg + ' (' + other + ')';
return msg;
}
$.validator.addMethod("duplicate", function (value, element, param) {
return $(element).nextAll('input').val() == 0 && !self._isRepeated($(element));
}, self._opts.duplicateDomain);
return $(element).nextAll('input').val() == "" && !self._isRepeated($(element));
}, getDuplicateMessage);
$.validator.addClassRules({
domain: { domain: true },
@@ -80,7 +88,7 @@
$('form input.domain').live('focus', function(event) {
if (event.type != 'focusin') return;
$(this).nextAll('input').val(0);
$(this).nextAll('input').val("");
});
// force validation *now*
@@ -105,14 +113,14 @@
}
else {
var inputs = $('form input.domain');
inputs.each(function() { $(this).nextAll('input').val(0); });
inputs.each(function() { $(this).nextAll('input').val(""); });
for (var i = 0; i < json.Domains.length; i++) {
var d = json.Domains[i];
if (d.Duplicate == 1)
if (d.Duplicate)
inputs.each(function() {
var input = $(this);
if (input.val() == d.Name)
input.nextAll('input').val(1);
input.nextAll('input').val(d.Other ? d.Other : "!!!");
});
}
$('form').valid();

View File

@@ -189,8 +189,12 @@
top.UmbSpeechBubble.ShowMessage('save', header, msg);
if (args && args.name) {
this._opts.originalFileName = args.name;
}
if (args && args.path) {
this._opts.treeSyncPath = args.path;
}
UmbClientMgr.mainTree().syncTree(path, true, null, newFilePath.split("/")[1]);
}

View File

@@ -5,6 +5,7 @@ using Umbraco.Core.Events;
using Umbraco.Core.Models;
using umbraco;
using umbraco.cms.businesslogic.web;
using Umbraco.Core.Persistence.Repositories;
namespace Umbraco.Web.Cache
{
@@ -400,6 +401,12 @@ namespace Umbraco.Web.Cache
dc.Remove(DistributedCache.DomainCacheRefresherGuid, domain.Id);
}
public static void ClearDomainCacheOnCurrentServer(this DistributedCache dc)
{
var key = RepositoryBase.GetCacheTypeKey<IDomain>();
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(key);
}
#endregion
#region Language Cache

View File

@@ -79,6 +79,7 @@ namespace Umbraco.Web.Cache
{
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<IContent>();
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
base.RefreshAll();
}
@@ -87,6 +88,7 @@ namespace Umbraco.Web.Cache
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey<IContent>(id));
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
content.Instance.UpdateSortOrder(id);
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
base.Refresh(id);
}
@@ -94,6 +96,7 @@ namespace Umbraco.Web.Cache
{
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey<IContent>(id));
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
base.Remove(id);
}
@@ -103,6 +106,7 @@ namespace Umbraco.Web.Cache
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey<IContent>(instance.Id));
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
content.Instance.UpdateSortOrder(instance);
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
base.Refresh(instance);
}
@@ -110,6 +114,7 @@ namespace Umbraco.Web.Cache
{
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey<IContent>(instance.Id));
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
base.Remove(instance);
}
@@ -127,6 +132,8 @@ namespace Umbraco.Web.Cache
content.Instance.UpdateSortOrder(payload.Id);
}
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
OnCacheUpdated(Instance, new CacheRefresherEventArgs(jsonPayload, MessageType.RefreshByJson));
}

View File

@@ -349,7 +349,9 @@ namespace Umbraco.Web.Editors
{"trees", GetTreePluginsMetaData()}
}
},
{"isDebuggingEnabled", HttpContext.IsDebuggingEnabled},
{
"isDebuggingEnabled", HttpContext.IsDebuggingEnabled
},
{
"application", GetApplicationState()
},

View File

@@ -491,7 +491,7 @@ namespace Umbraco.Web.Editors
{
var toCopy = ValidateMoveOrCopy(copy);
var c = Services.ContentService.Copy(toCopy, copy.ParentId, copy.RelateToOriginal);
var c = Services.ContentService.Copy(toCopy, copy.ParentId, copy.RelateToOriginal, copy.Recursive);
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(c.Path, Encoding.UTF8, "application/json");

View File

@@ -471,7 +471,7 @@ namespace Umbraco.Web.Editors
{
tempFiles.Notifications.Add(new Notification(
Services.TextService.Localize("speechBubbles/operationFailedHeader"),
"Cannot upload file " + file + ", it is not an approved file type",
"Cannot upload file " + file.Headers.ContentDisposition.FileName + ", it is not an approved file type",
SpeechBubbleIcon.Warning));
}
}

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
@@ -11,10 +10,12 @@ using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Dynamics;
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.Profiling;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
using umbraco;
using umbraco.cms.businesslogic.member;
using Constants = Umbraco.Core.Constants;
using Member = umbraco.cms.businesslogic.member.Member;
namespace Umbraco.Web
{
@@ -194,6 +195,117 @@ namespace Umbraco.Web
return htmlHelper.Action(actionName, metaData.ControllerName, routeVals);
}
#region GetCropUrl
/// <summary>
/// Gets the ImageProcessor Url of a media item by the crop alias (using default media item property alias of "umbracoFile")
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="mediaItem"></param>
/// <param name="cropAlias"></param>
/// <returns></returns>
public static IHtmlString GetCropUrl(this HtmlHelper htmlHelper, IPublishedContent mediaItem, string cropAlias)
{
return new HtmlString(mediaItem.GetCropUrl(cropAlias: cropAlias, useCropDimensions: true));
}
/// <summary>
/// Gets the ImageProcessor Url of a media item by the property alias and crop alias.
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="mediaItem"></param>
/// <param name="propertyAlias"></param>
/// <param name="cropAlias"></param>
/// <returns></returns>
public static IHtmlString GetCropUrl(this HtmlHelper htmlHelper, IPublishedContent mediaItem, string propertyAlias, string cropAlias)
{
return new HtmlString(mediaItem.GetCropUrl(propertyAlias: propertyAlias, cropAlias: cropAlias, useCropDimensions: true));
}
/// <summary>
/// Gets the ImageProcessor Url of a media item
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="mediaItem"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="propertyAlias"></param>
/// <param name="cropAlias"></param>
/// <param name="quality"></param>
/// <param name="imageCropMode"></param>
/// <param name="imageCropAnchor"></param>
/// <param name="preferFocalPoint"></param>
/// <param name="useCropDimensions"></param>
/// <param name="cacheBuster"></param>
/// <param name="furtherOptions"></param>
/// <param name="ratioMode"></param>
/// <param name="upScale"></param>
/// <returns></returns>
public static IHtmlString GetCropUrl(this HtmlHelper htmlHelper,
IPublishedContent mediaItem,
int? width = null,
int? height = null,
string propertyAlias = Constants.Conventions.Media.File,
string cropAlias = null,
int? quality = null,
ImageCropMode? imageCropMode = null,
ImageCropAnchor? imageCropAnchor = null,
bool preferFocalPoint = false,
bool useCropDimensions = false,
bool cacheBuster = true,
string furtherOptions = null,
ImageCropRatioMode? ratioMode = null,
bool upScale = true)
{
return
new HtmlString(mediaItem.GetCropUrl(width, height, propertyAlias, cropAlias, quality, imageCropMode,
imageCropAnchor, preferFocalPoint, useCropDimensions, cacheBuster, furtherOptions, ratioMode,
upScale));
}
/// <summary>
/// Gets the ImageProcessor Url from the media path
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="imageUrl"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="imageCropperValue"></param>
/// <param name="cropAlias"></param>
/// <param name="quality"></param>
/// <param name="imageCropMode"></param>
/// <param name="imageCropAnchor"></param>
/// <param name="preferFocalPoint"></param>
/// <param name="useCropDimensions"></param>
/// <param name="cacheBusterValue"></param>
/// <param name="furtherOptions"></param>
/// <param name="ratioMode"></param>
/// <param name="upScale"></param>
/// <returns></returns>
public static IHtmlString GetCropUrl(this HtmlHelper htmlHelper,
string imageUrl,
int? width = null,
int? height = null,
string imageCropperValue = null,
string cropAlias = null,
int? quality = null,
ImageCropMode? imageCropMode = null,
ImageCropAnchor? imageCropAnchor = null,
bool preferFocalPoint = false,
bool useCropDimensions = false,
string cacheBusterValue = null,
string furtherOptions = null,
ImageCropRatioMode? ratioMode = null,
bool upScale = true)
{
return
new HtmlString(imageUrl.GetCropUrl(width, height, imageCropperValue, cropAlias, quality, imageCropMode,
imageCropAnchor, preferFocalPoint, useCropDimensions, cacheBusterValue, furtherOptions, ratioMode,
upScale));
}
#endregion
#region BeginUmbracoForm
/// <summary>

View File

@@ -33,6 +33,13 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "relateToOriginal", IsRequired = true)]
[Required]
public bool RelateToOriginal { get; set; }
/// <summary>
/// Boolean indicating whether copying the object should be recursive
/// </summary>
[DataMember(Name = "recursive", IsRequired = true)]
[Required]
public bool Recursive { get; set; }
}
}

View File

@@ -2,22 +2,16 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.Serialization;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using AutoMapper;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Mapping;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Trees;
using umbraco;
using Umbraco.Web.Routing;
using umbraco.BusinessLogic.Actions;
@@ -51,11 +45,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(
dto => dto.IsContainer,
expression => expression.MapFrom(content => content.ContentType.IsContainer))
.ForMember(
dto => dto.IsChildOfListView,
//TODO: Fix this shorthand .Parent() lookup, at least have an overload to use the current
// application context so it's testable!
expression => expression.MapFrom(content => content.Parent().ContentType.IsContainer))
.ForMember(display => display.IsChildOfListView, expression => expression.Ignore())
.ForMember(
dto => dto.Trashed,
expression => expression.MapFrom(content => content.Trashed))
@@ -78,7 +68,8 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(display => display.Tabs, expression => expression.ResolveUsing<TabsAndPropertiesResolver>())
.ForMember(display => display.AllowedActions, expression => expression.ResolveUsing(
new ActionButtonsResolver(new Lazy<IUserService>(() => applicationContext.Services.UserService))))
.AfterMap((media, display) => AfterMap(media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService));
.AfterMap((media, display) => AfterMap(media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService,
applicationContext.Services.ContentTypeService));
//FROM IContent TO ContentItemBasic<ContentPropertyBasic, IContent>
config.CreateMap<IContent, ContentItemBasic<ContentPropertyBasic, IContent>>()
@@ -119,8 +110,15 @@ namespace Umbraco.Web.Models.Mapping
/// <param name="display"></param>
/// <param name="dataTypeService"></param>
/// <param name="localizedText"></param>
private static void AfterMap(IContent content, ContentItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText)
/// <param name="contentTypeService"></param>
private static void AfterMap(IContent content, ContentItemDisplay display, IDataTypeService dataTypeService,
ILocalizedTextService localizedText, IContentTypeService contentTypeService)
{
//map the IsChildOfListView (this is actually if it is a descendant of a list view!)
//TODO: Fix this shorthand .Ancestors() lookup, at least have an overload to use the current
var ancesctorListView = content.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
display.IsChildOfListView = ancesctorListView != null;
//map the tree node url
if (HttpContext.Current != null)
{
@@ -142,8 +140,8 @@ namespace Umbraco.Web.Models.Mapping
TabsAndPropertiesResolver.AddListView(display, "content", dataTypeService);
}
TabsAndPropertiesResolver.MapGenericProperties(
content, display,
var properties = new List<ContentPropertyDisplay>
{
new ContentPropertyDisplay
{
Alias = string.Format("{0}releasedate", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
@@ -175,10 +173,43 @@ namespace Umbraco.Web.Models.Mapping
Label = localizedText.Localize("content/urls"),
Value = string.Join(",", display.Urls),
View = "urllist" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
});
}
};
TabsAndPropertiesResolver.MapGenericProperties(content, display, properties.ToArray(),
genericProperties =>
{
//TODO: This would be much nicer with the IUmbracoContextAccessor so we don't use singletons
//If this is a web request and debugging is enabled and there's a user signed in and the
// user has access tot he settings section, we will
if (HttpContext.Current != null && HttpContext.Current.IsDebuggingEnabled
&& UmbracoContext.Current != null && UmbracoContext.Current.Security.CurrentUser != null
&& UmbracoContext.Current.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)))
{
var currentDocumentType = contentTypeService.GetContentType(display.ContentTypeAlias);
var currentDocumentTypeName = currentDocumentType == null ? string.Empty : currentDocumentType.Name;
var currentDocumentTypeId = currentDocumentType == null ? string.Empty : currentDocumentType.Id.ToString(CultureInfo.InvariantCulture);
//TODO: Hard coding this is not good
var docTypeLink = string.Format("#/settings/framed/%252Fumbraco%252Fsettings%252FeditNodeTypeNew.aspx%253Fid%253D{0}", currentDocumentTypeId);
//Replace the doc type property
var docTypeProp = genericProperties.First(x => x.Alias == string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
docTypeProp.Value = new List<object>
{
new
{
linkText = currentDocumentTypeName,
url = docTypeLink,
target = "_self", icon = "icon-item-arrangement"
}
};
//TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
docTypeProp.View = "urllist";
}
});
}
/// <summary>
/// Gets the published date value for the IContent object

View File

@@ -35,11 +35,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(
dto => dto.ContentTypeAlias,
expression => expression.MapFrom(content => content.ContentType.Alias))
.ForMember(
dto => dto.IsChildOfListView,
//TODO: Fix this shorthand .Parent() lookup, at least have an overload to use the current
// application context so it's testable!
expression => expression.MapFrom(content => content.Parent().ContentType.IsContainer))
.ForMember(display => display.IsChildOfListView, expression => expression.Ignore())
.ForMember(
dto => dto.Trashed,
expression => expression.MapFrom(content => content.Trashed))

View File

@@ -178,8 +178,8 @@ namespace Umbraco.Web.Models.Mapping
display.TreeNodeUrl = url;
}
TabsAndPropertiesResolver.MapGenericProperties(
member, display,
var genericProperties = new List<ContentPropertyDisplay>
{
GetLoginProperty(memberService, member, display),
new ContentPropertyDisplay
{
@@ -187,7 +187,7 @@ namespace Umbraco.Web.Models.Mapping
Label = ui.Text("general", "email"),
Value = display.Email,
View = "email",
Validation = { Mandatory = true }
Validation = {Mandatory = true}
},
new ContentPropertyDisplay
{
@@ -197,8 +197,8 @@ namespace Umbraco.Web.Models.Mapping
// only when creating a new member and we want to have a generated password pre-filled.
Value = new Dictionary<string, object>
{
{"generatedPassword", member.GetAdditionalDataValueIgnoreCase("GeneratedPassword", null) },
{"newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null) },
{"generatedPassword", member.GetAdditionalDataValueIgnoreCase("GeneratedPassword", null)},
{"newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null)},
},
//TODO: Hard coding this because the changepassword doesn't necessarily need to be a resolvable (real) property editor
View = "changepassword",
@@ -215,8 +215,11 @@ namespace Umbraco.Web.Models.Mapping
Label = ui.Text("content", "membergroup"),
Value = GetMemberGroupValue(display.Username),
View = "membergroups",
Config = new Dictionary<string, object> { { "IsRequired", true } }
});
Config = new Dictionary<string, object> {{"IsRequired", true}}
}
};
TabsAndPropertiesResolver.MapGenericProperties(member, display, genericProperties);
//check if there's an approval field
var provider = membersProvider as global::umbraco.providers.members.UmbracoMembershipProvider;

View File

@@ -1,10 +1,11 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
@@ -40,6 +41,7 @@ namespace Umbraco.Web.Models.Mapping
/// <param name="customProperties">
/// Any additional custom properties to assign to the generic properties tab.
/// </param>
/// <param name="onGenericPropertiesMapped"></param>
/// <remarks>
/// The generic properties tab is mapped during AfterMap and is responsible for
/// setting up the properties such as Created date, updated date, template selected, etc...
@@ -47,11 +49,10 @@ namespace Umbraco.Web.Models.Mapping
public static void MapGenericProperties<TPersisted>(
TPersisted content,
ContentItemDisplayBase<ContentPropertyDisplay, TPersisted> display,
params ContentPropertyDisplay[] customProperties)
IEnumerable<ContentPropertyDisplay> customProperties = null,
Action<List<ContentPropertyDisplay>> onGenericPropertiesMapped = null)
where TPersisted : IContentBase
{
var genericProps = display.Tabs.Single(x => x.Id == 0);
//store the current props to append to the newly inserted ones
@@ -101,15 +102,26 @@ namespace Umbraco.Web.Models.Mapping
}
};
if (customProperties != null)
{
//add the custom ones
contentProps.AddRange(customProperties);
}
//now add the user props
contentProps.AddRange(currProps);
//callback
if (onGenericPropertiesMapped != null)
{
onGenericPropertiesMapped(contentProps);
}
//re-assign
genericProps.Properties = contentProps;
}
/// <summary>

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Mvc.Async;
@@ -11,9 +12,6 @@ namespace Umbraco.Web.Mvc
/// </summary>
public class RenderActionInvoker : AsyncControllerActionInvoker
{
private static readonly ConcurrentDictionary<Type, ReflectedActionDescriptor> IndexDescriptors = new ConcurrentDictionary<Type, ReflectedActionDescriptor>();
/// <summary>
/// Ensures that if an action for the Template name is not explicitly defined by a user, that the 'Index' action will execute
/// </summary>
@@ -31,16 +29,7 @@ namespace Umbraco.Web.Mvc
//check if the controller is an instance of IRenderMvcController
if (controllerContext.Controller is IRenderMvcController)
{
return IndexDescriptors.GetOrAdd(controllerContext.Controller.GetType(),
type => new ReflectedActionDescriptor(
controllerContext.Controller.GetType().GetMethods()
.First(x => x.Name == "Index" &&
x.GetCustomAttributes(typeof (NonActionAttribute), false).Any() == false),
"Index",
controllerDescriptor));
return controllerDescriptor.FindAction(controllerContext, "Index");
}
}
return ad;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using System.Web.Services.Description;
using Umbraco.Core;
@@ -113,7 +114,25 @@ namespace Umbraco.Web.WebServices
if (domain != null)
domain.LanguageId = language.Id;
else if (Services.DomainService.Exists(domainModel.Name))
{
domainModel.Duplicate = true;
var xdomain = Services.DomainService.GetByName(domainModel.Name);
var xrcid = xdomain.RootContentId;
if (xrcid.HasValue)
{
var xcontent = Services.ContentService.GetById(xrcid.Value);
var xnames = new List<string>();
while (xcontent != null)
{
xnames.Add(xcontent.Name);
if (xcontent.ParentId < -1)
xnames.Add("Recycle Bin");
xcontent = xcontent.Parent();
}
xnames.Reverse();
domainModel.Other = "/" + string.Join("/", xnames);
}
}
else
{
// yet there is a race condition here...
@@ -159,6 +178,7 @@ namespace Umbraco.Web.WebServices
public string Name { get; private set; }
public int Lang { get; private set; }
public bool Duplicate { get; set; }
public string Other { get; set; }
}
#endregion

View File

@@ -258,9 +258,16 @@ namespace Umbraco.Web.WebServices
//ignore these properties
.Where(x => new[] {"IndexerData", "Description", "WorkingFolder"}.InvariantContains(x.Name) == false)
.OrderBy(x => x.Name);
foreach (var p in props)
{
indexerModel.ProviderProperties.Add(p.Name, p.GetValue(indexer, null).ToString());
var val = p.GetValue(indexer, null);
if (val == null)
{
LogHelper.Warn<ExamineManagementApiController>("Property value was null when setting up property on indexer: " + indexer.Name + " property: " + p.Name);
val = string.Empty;
}
indexerModel.ProviderProperties.Add(p.Name, val.ToString());
}
var luceneIndexer = indexer as LuceneIndexer;

View File

@@ -97,22 +97,25 @@ namespace Umbraco.Web.WebServices
oldname = oldname.TrimStart(pathPrefix);
}
var view = get(svce, oldname);
if (view == null)
view = new PartialView(filename);
var currentView = oldname.IsNullOrWhiteSpace()
? get(svce, filename)
: get(svce, oldname);
if (currentView == null)
currentView = new PartialView(filename);
else
view.Path = filename;
view.Content = contents;
currentView.Path = filename;
currentView.Content = contents;
Attempt<IPartialView> attempt;
try
{
var partialView = view as PartialView;
var partialView = currentView as PartialView;
if (partialView != null && validate != null && validate(svce, partialView) == false)
return Failed(ui.Text("speechBubbles", "partialViewErrorText"), ui.Text("speechBubbles", "partialViewErrorHeader"),
new FileSecurityException("File '" + view.Path + "' is not a valid partial view file."));
new FileSecurityException("File '" + currentView.Path + "' is not a valid partial view file."));
attempt = save(svce, view);
attempt = save(svce, currentView);
}
catch (Exception e)
{

View File

@@ -602,7 +602,7 @@ namespace umbraco
XmlDocument mXml = new XmlDocument();
mXml.LoadXml(m.ToXml(mXml, false).OuterXml);
XPathNavigator xp = mXml.CreateNavigator();
return xp.Select("/node");
return xp.Select("/node()");
}
XmlDocument xd = new XmlDocument();

View File

@@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.IO;
using System.Text;
using System.Web;
@@ -71,7 +72,7 @@ namespace umbraco
else
tmp = new Dictionary.DictionaryItem(this.id).Children;
foreach (Dictionary.DictionaryItem di in tmp)
foreach (Dictionary.DictionaryItem di in tmp.OrderBy(a => a.key))
{
XmlTreeNode xNode = XmlTreeNode.Create(this);
xNode.NodeID = di.id.ToString(); //dictionary_ + id..

View File

@@ -79,7 +79,7 @@ namespace umbraco.presentation.umbraco.dialogs
if (IsPostBack == false)
{
if (Access.IsProtected(documentId, documentObject.Path) && Access.GetProtectionType(documentId) != ProtectionType.NotProtected)
if (Access.IsProtected(documentId) && Access.GetProtectionType(documentId) != ProtectionType.NotProtected)
{
bt_buttonRemoveProtection.Visible = true;
bt_buttonRemoveProtection.Attributes.Add("onClick", "return confirm('" + ui.Text("areyousure") + "')");
@@ -263,10 +263,11 @@ namespace umbraco.presentation.umbraco.dialogs
p_buttons.Visible = false;
pane_advanced.Visible = false;
pane_simple.Visible = false;
var content = ApplicationContext.Current.Services.ContentService.GetById(pageId);
//reloads the current node in the tree
ClientTools.SyncTree(content.Path, true);
//reloads the current node's children in the tree
ClientTools.ReloadActionNode(false, true);
feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.success;
}
}
@@ -284,8 +285,10 @@ namespace umbraco.presentation.umbraco.dialogs
feedback.Text = ui.Text("publicAccess", "paIsRemoved", new cms.businesslogic.CMSNode(pageId).Text) + "</p><p><a href='#' onclick='" + ClientTools.Scripts.CloseModalWindow() + "'>" + ui.Text("closeThisWindow") + "</a>";
var content = ApplicationContext.Current.Services.ContentService.GetById(pageId);
//reloads the current node in the tree
ClientTools.SyncTree(content.Path, true);
//reloads the current node's children in the tree
ClientTools.ReloadActionNode(false, true);
feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.success;
}

View File

@@ -19,7 +19,6 @@ using umbraco.BasePages;
using umbraco.BusinessLogic;
using umbraco.businesslogic.Exceptions;
using umbraco.cms.businesslogic.media;
using umbraco.cms.businesslogic.propertytype;
using umbraco.cms.businesslogic.web;
using umbraco.controls;
using umbraco.presentation.channels.businesslogic;
@@ -28,7 +27,9 @@ using umbraco.providers;
using umbraco.cms.presentation.Trees;
using Umbraco.Core.IO;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using PropertyType = umbraco.cms.businesslogic.propertytype.PropertyType;
namespace umbraco.cms.presentation.user
{
@@ -107,7 +108,7 @@ namespace umbraco.cms.presentation.user
}
}
var userCulture = Services.TextService.ConvertToSupportedCultureWithRegionCode(new CultureInfo(u.Language));
var userCulture = UserExtensions.GetUserCulture(u.Language, Services.TextService);
// Populate ui language lsit
foreach (var lang in Services.TextService.GetSupportedCultures())

View File

@@ -161,7 +161,7 @@ namespace umbraco.presentation.umbraco.webservices
var ext = uploadFile.FileName.Substring(uploadFile.FileName.LastIndexOf('.') + 1).ToLower();
if (UmbracoConfig.For.UmbracoSettings().Content.DisallowedUploadFiles.Contains(ext))
{
LogHelper.Warn<MediaUploader>("Cannot upload file " + uploadFile + ", it is not an approved file type");
LogHelper.Warn<MediaUploader>("Cannot upload file " + uploadFile.FileName + ", it is not approved in `disallowedUploadFiles` in ~/config/UmbracoSettings.config");
continue;
}

View File

@@ -213,7 +213,7 @@ namespace umbraco.cms.businesslogic.web
var noAccessContent = ApplicationContext.Current.Services.ContentService.GetById(ErrorDocumentId);
if (noAccessContent == null) throw new NullReferenceException("No content item found with id " + ErrorDocumentId);
var entry = ApplicationContext.Current.Services.PublicAccessService.GetEntryForContent(doc.ContentEntity);
var entry = ApplicationContext.Current.Services.PublicAccessService.GetEntryForContent(doc.ContentEntity.Id.ToString());
if (entry != null)
{
if (Simple)
@@ -420,6 +420,12 @@ namespace umbraco.cms.businesslogic.web
return ApplicationContext.Current.Services.PublicAccessService.IsProtected(Path.EnsureEndsWith("," + DocumentId));
}
//return the protection status of this exact document - not based on inheritance
public static bool IsProtected(int DocumentId)
{
return ApplicationContext.Current.Services.PublicAccessService.IsProtected(DocumentId.ToString());
}
public static int GetErrorPage(string Path)
{
var entry = ApplicationContext.Current.Services.PublicAccessService.GetEntryForContent(Path);