Compare commits

...

33 Commits

Author SHA1 Message Date
Morten Christensen 8e1c45e981 Updating Sort methods to skip items that hasn't been sorted 2013-05-29 05:37:55 -02:00
Sebastiaan Janssen 4a7ee52d63 Merge with 4.11.9 2013-05-29 03:47:26 -02:00
Sebastiaan Janssen b4d88b0361 U4-2279 TryGetRouteDefinitionFromAncestorViewContexts has infinite loop when
currentContext doesnt contain umbraco-route-def
2013-05-29 03:44:01 -02:00
Sebastiaan Janssen b41cf37dd5 U4-2290 Notifications do not handle fields that have null values. 2013-05-29 03:42:20 -02:00
Sebastiaan Janssen fc32100142 Merge with 4.11.9 2013-05-28 15:45:59 -02:00
Sebastiaan Janssen 7ecbc3b391 Fixes U4-2248 Spelling error in back office 2013-05-28 15:44:59 -02:00
Sebastiaan Janssen c3c44df52e Merge with 4.11.9 2013-05-28 15:43:40 -02:00
Sebastiaan Janssen 13a86624ff Fixes U4-2248 Spelling error in back office 2013-05-28 15:39:12 -02:00
Sebastiaan Janssen 2f61bc27c8 Bump version number 2013-05-28 15:15:32 -02:00
Sebastiaan Janssen e7d157a209 Merge with 4.11.9 2013-05-28 12:18:49 -02:00
Sebastiaan Janssen d3ed90c23e Some fixes & refactor 2013-05-28 12:10:29 -02:00
Sebastiaan Janssen b916360771 Merge with 4.11.9 2013-05-27 10:22:20 -02:00
Sebastiaan Janssen db4b93dbc3 Update test because of new added restextension (EmbedMediaService) 2013-05-27 10:21:14 -02:00
Sebastiaan Janssen 40868ac361 Merge 2013-05-27 10:02:01 -02:00
Sebastiaan Janssen f399a9f52b Merge with 4.11.9 2013-05-27 10:00:28 -02:00
Sebastiaan Janssen 562851b93e Possible fix for U4-2251 TreeDataService throws JSON JavaScriptSerializer. The
length of the string exceeds the value set on the maxJsonLength property
2013-05-27 09:59:02 -02:00
Morten Christensen e61b567ee1 Fixes #U4-2270 and #U4-2269 2013-05-27 08:45:07 -02:00
Sebastiaan Janssen 4ce22b836e Merge with 4.11.9 2013-05-27 08:16:18 -02:00
Sebastiaan Janssen f5bf05a6f5 Move embed media service from webservices dll into it's own /base class 2013-05-27 07:19:42 -02:00
Sebastiaan Janssen e50569597b Minor update to legacy ajax calls 2013-05-27 06:10:04 -02:00
Sebastiaan Janssen 071f3dcc01 Fix javascript error with the speechbubble 2013-05-27 06:05:13 -02:00
Morten Christensen 6943a454f3 Implementing Sort-method for the Content/MediaService 2013-05-23 10:29:44 -02:00
Shannon Deminick 532f407260 Merge with 4.11.9 2013-05-14 14:20:52 -10:00
Shannon Deminick 834d04f8ed Fixes: #U4-1469, #U4-1156 2013-05-14 14:18:41 -10:00
dmilic f36ab37f6a Fix for the U4-2229 issue - broken PublishWithSubs method 2013-05-13 15:49:59 -12:00
Sebastiaan Janssen aeff33d0a6 Bump version number 2013-05-28 15:17:55 -02:00
Sebastiaan Janssen 5cfe9e57ce Merge with 4.11.9 2013-05-13 13:47:01 -02:00
Sebastiaan Janssen 4863e657df Fixes U4-2226 Javascript error "tinyMCE is undefined" in IE - THANKS Adriano Buscema! 2013-05-13 13:42:57 -02:00
Shannon Deminick c0e1be4df9 Merge 2013-05-12 23:56:47 -10:00
Sebastiaan Janssen a93e562f14 Fixes U4-2209 6.0.5 - Bug - Empty recycle bin DELETES all content 2013-05-13 07:48:35 -02:00
Shannon Deminick 822cac5d87 Adds test for #U4-2207 which will now pass but it will still fail on the website because of the case
sensitive checking for the default proeprty editor lookup. Need feedback from sebastian before continuing
2013-05-12 21:44:02 -10:00
Shannon Deminick d58487fafc Merge 2013-05-12 21:13:50 -10:00
Shannon Deminick ea9653fa83 patches fix for #U4-2214 2013-05-12 21:12:55 -10:00
33 changed files with 831 additions and 300 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
@ECHO OFF
SET release=6.0.5
SET release=6.0.6
SET comment=
SET version=%release%
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("6.0.5");
private static readonly Version Version = new Version("6.0.6");
/// <summary>
/// Gets the current version of Umbraco.
@@ -5,12 +5,11 @@ using System.Text;
using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.IO
{
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
internal class FileSystemProviderAttribute : Attribute
public class FileSystemProviderAttribute : Attribute
{
public string Alias { get; set; }
public string Alias { get; private set; }
public FileSystemProviderAttribute(string alias)
{
@@ -6,8 +6,7 @@ using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.IO
{
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
internal class FileSystemProvider
internal class FileSystemProviderConstants
{
public const string Media = "media";
}
@@ -9,9 +9,8 @@ using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.Configuration;
namespace Umbraco.Core.IO
{
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
internal class FileSystemProviderManager
{
public class FileSystemProviderManager
{
private readonly FileSystemProvidersSection _config;
@@ -28,7 +27,7 @@ namespace Umbraco.Core.IO
#region Constructors
public FileSystemProviderManager()
internal FileSystemProviderManager()
{
_config = (FileSystemProvidersSection)ConfigurationManager.GetSection("FileSystemProviders");
}
@@ -48,7 +47,15 @@ namespace Umbraco.Core.IO
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
private readonly ConcurrentDictionary<Type, string> _wrappedProviderLookup = new ConcurrentDictionary<Type, string>();
public IFileSystem GetFileSystemProvider(string alias)
/// <summary>
/// Returns the underlying (non-typed) file system provider for the alias specified
/// </summary>
/// <param name="alias"></param>
/// <returns></returns>
/// <remarks>
/// It is recommended to use the typed GetFileSystemProvider method instead to get a strongly typed provider instance.
/// </remarks>
public IFileSystem GetUnderlyingFileSystemProvider(string alias)
{
//either get the constructor info from cache or create it and add to cache
var ctorInfo = _providerLookup.GetOrAdd(alias, s =>
@@ -88,6 +95,11 @@ namespace Umbraco.Core.IO
return fs;
}
/// <summary>
/// Returns the strongly typed file system provider
/// </summary>
/// <typeparam name="TProviderTypeFilter"></typeparam>
/// <returns></returns>
public TProviderTypeFilter GetFileSystemProvider<TProviderTypeFilter>()
where TProviderTypeFilter : FileSystemWrapper
{
@@ -111,7 +123,7 @@ namespace Umbraco.Core.IO
return attr.Alias;
});
var innerFs = GetFileSystemProvider(alias);
var innerFs = GetUnderlyingFileSystemProvider(alias);
var outputFs = Activator.CreateInstance(typeof (TProviderTypeFilter), innerFs);
return (TProviderTypeFilter)outputFs;
}
@@ -455,9 +455,12 @@ namespace Umbraco.Core.Persistence.Querying
if (fieldType == typeof(decimal))
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
if(fieldType == typeof(DateTime))
if (fieldType == typeof(DateTime))
return "'" + EscapeParam(((DateTime)value).ToString(CultureInfo.InvariantCulture)) + "'";
if (fieldType == typeof(bool))
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
return ShouldQuoteValue(fieldType)
? "'" + EscapeParam(value) + "'"
: value.ToString();
+246 -53
View File
@@ -56,8 +56,13 @@ namespace Umbraco.Core.Services
/// <summary>
/// Creates an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
/// that this Content is based on.
/// that this Content should based on.
/// </summary>
/// <remarks>
/// Note that using this method will simply return a new IContent without any identity
/// as it has not yet been persisted. It is intended as a shortcut to creating new content objects
/// that does not invoke a save operation against the database.
/// </remarks>
/// <param name="name">Name of the Content object</param>
/// <param name="parentId">Id of Parent for the new Content</param>
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
@@ -66,7 +71,7 @@ namespace Umbraco.Core.Services
public IContent CreateContent(string name, int parentId, string contentTypeAlias, int userId = 0)
{
var contentType = FindContentTypeByAlias(contentTypeAlias);
var content = new Content(name, parentId, contentType); ;
var content = new Content(name, parentId, contentType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parentId), this))
{
@@ -86,8 +91,13 @@ namespace Umbraco.Core.Services
/// <summary>
/// Creates an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
/// that this Content is based on.
/// that this Content should based on.
/// </summary>
/// <remarks>
/// Note that using this method will simply return a new IContent without any identity
/// as it has not yet been persisted. It is intended as a shortcut to creating new content objects
/// that does not invoke a save operation against the database.
/// </remarks>
/// <param name="name">Name of the Content object</param>
/// <param name="parent">Parent <see cref="IContent"/> object for the new Content</param>
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
@@ -114,6 +124,86 @@ namespace Umbraco.Core.Services
return content;
}
/// <summary>
/// Creates and saves an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
/// that this Content should based on.
/// </summary>
/// <remarks>
/// This method returns an <see cref="IContent"/> object that has been persisted to the database
/// and therefor has an identity.
/// </remarks>
/// <param name="name">Name of the Content object</param>
/// <param name="parentId">Id of Parent for the new Content</param>
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
/// <param name="userId">Optional id of the user creating the content</param>
/// <returns><see cref="IContent"/></returns>
public IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0)
{
var contentType = FindContentTypeByAlias(contentTypeAlias);
var content = new Content(name, parentId, contentType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parentId), this))
{
content.WasCancelled = true;
return content;
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentRepository(uow))
{
content.CreatorId = userId;
content.WriterId = userId;
repository.AddOrUpdate(content);
uow.Commit();
}
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parentId), this);
Audit.Add(AuditTypes.New, "", content.CreatorId, content.Id);
return content;
}
/// <summary>
/// Creates and saves an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
/// that this Content should based on.
/// </summary>
/// <remarks>
/// This method returns an <see cref="IContent"/> object that has been persisted to the database
/// and therefor has an identity.
/// </remarks>
/// <param name="name">Name of the Content object</param>
/// <param name="parent">Parent <see cref="IContent"/> object for the new Content</param>
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
/// <param name="userId">Optional id of the user creating the content</param>
/// <returns><see cref="IContent"/></returns>
public IContent CreateContentWithIdentity(string name, IContent parent, string contentTypeAlias, int userId = 0)
{
var contentType = FindContentTypeByAlias(contentTypeAlias);
var content = new Content(name, parent, contentType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parent), this))
{
content.WasCancelled = true;
return content;
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentRepository(uow))
{
content.CreatorId = userId;
content.WriterId = userId;
repository.AddOrUpdate(content);
uow.Commit();
}
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parent), this);
Audit.Add(AuditTypes.New, "", content.CreatorId, content.Id);
return content;
}
/// <summary>
/// Gets an <see cref="IContent"/> object by Id
/// </summary>
@@ -1010,6 +1100,92 @@ namespace Umbraco.Core.Services
return content;
}
/// <summary>
/// Sorts a collection of <see cref="IContent"/> objects by updating the SortOrder according
/// to the ordering of items in the passed in <see cref="SortedSet{T}"/>.
/// </summary>
/// <remarks>
/// Using this method will ensure that the Published-state is maintained upon sorting
/// so the cache is updated accordingly - as needed.
/// </remarks>
/// <param name="items"></param>
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
public bool Sort(SortedSet<IContent> items, int userId = 0, bool raiseEvents = true)
{
if (raiseEvents)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IContent>(items), this))
return false;
}
var shouldBePublished = new List<IContent>();
var shouldBeSaved = new List<IContent>();
using (new WriteLock(Locker))
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentRepository(uow))
{
int i = 0;
foreach (var content in items)
{
//If the current sort order equals that of the content
//we don't need to update it, so just increment the sort order
//and continue.
if (content.SortOrder == i)
{
i++;
continue;
}
content.SortOrder = i;
content.WriterId = userId;
i++;
if (content.Published)
{
var published = _publishingStrategy.Publish(content, userId);
shouldBePublished.Add(content);
}
else
shouldBeSaved.Add(content);
repository.AddOrUpdate(content);
}
uow.Commit();
foreach (var content in shouldBeSaved)
{
//Create and Save PreviewXml DTO
var xml = content.ToXml();
CreateAndSavePreviewXml(xml, content.Id, content.Version, uow.Database);
}
foreach (var content in shouldBePublished)
{
//Create and Save PreviewXml DTO
var xml = content.ToXml();
CreateAndSavePreviewXml(xml, content.Id, content.Version, uow.Database);
//Create and Save ContentXml DTO
CreateAndSaveContentXml(xml, content.Id, uow.Database);
}
}
}
if (raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IContent>(items, false), this);
if(shouldBePublished.Any())
_publishingStrategy.PublishingFinalized(shouldBePublished, false);
Audit.Add(AuditTypes.Sort, "Sorting content performed by user", userId, 0);
return true;
}
#region Internal Methods
/// <summary>
@@ -1270,28 +1446,8 @@ namespace Umbraco.Core.Services
using (new WriteLock(Locker))
{
//Has this content item previously been published? If so, we don't need to refresh the children
var previouslyPublished = HasPublishedVersion(content.Id);
var validForPublishing = true;
//Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published
if (content.ParentId != -1 && content.ParentId != -20 && IsPublishable(content) == false)
{
LogHelper.Info<ContentService>(
string.Format(
"Content '{0}' with Id '{1}' could not be published because its parent is not published.",
content.Name, content.Id));
validForPublishing = false;
}
//Content contains invalid property values and can therefore not be published - fire event?
if (!content.IsValid())
{
LogHelper.Info<ContentService>(
string.Format(
"Content '{0}' with Id '{1}' could not be published because of invalid properties.",
content.Name, content.Id));
validForPublishing = false;
}
var previouslyPublished = content.HasIdentity && HasPublishedVersion(content.Id);
var validForPublishing = CheckAndLogIsPublishable(content) && CheckAndLogIsValid(content);
//Publish and then update the database with new status
bool published = validForPublishing && _publishingStrategy.Publish(content, userId);
@@ -1308,37 +1464,12 @@ namespace Umbraco.Core.Services
var xml = content.ToXml();
//Preview Xml
var previewPoco = new PreviewXmlDto
{
NodeId = content.Id,
Timestamp = DateTime.Now,
VersionId = content.Version,
Xml = xml.ToString(SaveOptions.None)
};
var previewExists =
uow.Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version",
new { Id = content.Id, Version = content.Version }) != 0;
int previewResult = previewExists
? uow.Database.Update<PreviewXmlDto>(
"SET xml = @Xml, timestamp = @Timestamp WHERE nodeId = @Id AND versionId = @Version",
new
{
Xml = previewPoco.Xml,
Timestamp = previewPoco.Timestamp,
Id = previewPoco.NodeId,
Version = previewPoco.VersionId
})
: Convert.ToInt32(uow.Database.Insert(previewPoco));
CreateAndSavePreviewXml(xml, content.Id, content.Version, uow.Database);
if (published)
{
//Content Xml
var contentPoco = new ContentXmlDto { NodeId = content.Id, Xml = xml.ToString(SaveOptions.None) };
var contentExists = uow.Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = content.Id }) != 0;
int contentResult = contentExists
? uow.Database.Update(contentPoco)
: Convert.ToInt32(uow.Database.Insert(contentPoco));
CreateAndSaveContentXml(xml, content.Id, uow.Database);
}
}
@@ -1458,6 +1589,68 @@ namespace Umbraco.Core.Services
return true;
}
private bool CheckAndLogIsPublishable(IContent content)
{
//Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published
if (content.ParentId != -1 && content.ParentId != -20 && IsPublishable(content) == false)
{
LogHelper.Info<ContentService>(
string.Format(
"Content '{0}' with Id '{1}' could not be published because its parent is not published.",
content.Name, content.Id));
return false;
}
return true;
}
private bool CheckAndLogIsValid(IContent content)
{
//Content contains invalid property values and can therefore not be published - fire event?
if (content.IsValid() == false)
{
LogHelper.Info<ContentService>(
string.Format(
"Content '{0}' with Id '{1}' could not be published because of invalid properties.",
content.Name, content.Id));
return false;
}
return true;
}
private void CreateAndSavePreviewXml(XElement xml, int id, Guid version, UmbracoDatabase db)
{
var previewPoco = new PreviewXmlDto
{
NodeId = id,
Timestamp = DateTime.Now,
VersionId = version,
Xml = xml.ToString(SaveOptions.None)
};
var previewExists =
db.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version",
new { Id = id, Version = version }) != 0;
int previewResult = previewExists
? db.Update<PreviewXmlDto>(
"SET xml = @Xml, timestamp = @Timestamp WHERE nodeId = @Id AND versionId = @Version",
new
{
Xml = previewPoco.Xml,
Timestamp = previewPoco.Timestamp,
Id = previewPoco.NodeId,
Version = previewPoco.VersionId
})
: Convert.ToInt32(db.Insert(previewPoco));
}
private void CreateAndSaveContentXml(XElement xml, int id, UmbracoDatabase db)
{
var contentPoco = new ContentXmlDto { NodeId = id, Xml = xml.ToString(SaveOptions.None) };
var contentExists = db.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = id }) != 0;
int contentResult = contentExists ? db.Update(contentPoco) : Convert.ToInt32(db.Insert(contentPoco));
}
private IContentType FindContentTypeByAlias(string contentTypeAlias)
{
using (var repository = _repositoryFactory.CreateContentTypeRepository(_uowProvider.GetUnitOfWork()))
@@ -1465,7 +1658,7 @@ namespace Umbraco.Core.Services
var query = Query<IContentType>.Builder.Where(x => x.Alias == contentTypeAlias);
var types = repository.GetByQuery(query);
if (!types.Any())
if (types.Any() == false)
throw new Exception(
string.Format("No ContentType matching the passed in Alias: '{0}' was found",
contentTypeAlias));
+56 -3
View File
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
@@ -12,8 +11,13 @@ namespace Umbraco.Core.Services
{
/// <summary>
/// Creates an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
/// that this Content is based on.
/// that this Content should based on.
/// </summary>
/// <remarks>
/// Note that using this method will simply return a new IContent without any identity
/// as it has not yet been persisted. It is intended as a shortcut to creating new content objects
/// that does not invoke a save operation against the database.
/// </remarks>
/// <param name="name">Name of the Content object</param>
/// <param name="parentId">Id of Parent for the new Content</param>
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
@@ -23,8 +27,13 @@ namespace Umbraco.Core.Services
/// <summary>
/// Creates an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
/// that this Content is based on.
/// that this Content should based on.
/// </summary>
/// <remarks>
/// Note that using this method will simply return a new IContent without any identity
/// as it has not yet been persisted. It is intended as a shortcut to creating new content objects
/// that does not invoke a save operation against the database.
/// </remarks>
/// <param name="name">Name of the Content object</param>
/// <param name="parent">Parent <see cref="IContent"/> object for the new Content</param>
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
@@ -288,5 +297,49 @@ namespace Umbraco.Core.Services
/// <param name="content"><see cref="IContent"/> to check if anscestors are published</param>
/// <returns>True if the Content can be published, otherwise False</returns>
bool IsPublishable(IContent content);
/// <summary>
/// Sorts a collection of <see cref="IContent"/> objects by updating the SortOrder according
/// to the ordering of items in the passed in <see cref="SortedSet{T}"/>.
/// </summary>
/// <remarks>
/// Using this method will ensure that the Published-state is maintained upon sorting
/// so the cache is updated accordingly - as needed.
/// </remarks>
/// <param name="items"></param>
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
bool Sort(SortedSet<IContent> items, int userId = 0, bool raiseEvents = true);
/// <summary>
/// Creates and saves an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
/// that this Content should based on.
/// </summary>
/// <remarks>
/// This method returns an <see cref="IContent"/> object that has been persisted to the database
/// and therefor has an identity.
/// </remarks>
/// <param name="name">Name of the Content object</param>
/// <param name="parent">Parent <see cref="IContent"/> object for the new Content</param>
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
/// <param name="userId">Optional id of the user creating the content</param>
/// <returns><see cref="IContent"/></returns>
IContent CreateContentWithIdentity(string name, IContent parent, string contentTypeAlias, int userId = 0);
/// <summary>
/// Creates and saves an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
/// that this Content should based on.
/// </summary>
/// <remarks>
/// This method returns an <see cref="IContent"/> object that has been persisted to the database
/// and therefor has an identity.
/// </remarks>
/// <param name="name">Name of the Content object</param>
/// <param name="parentId">Id of Parent for the new Content</param>
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
/// <param name="userId">Optional id of the user creating the content</param>
/// <returns><see cref="IContent"/></returns>
IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0);
}
}
+52 -2
View File
@@ -11,8 +11,13 @@ namespace Umbraco.Core.Services
{
/// <summary>
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
/// that this Media is based on.
/// that this Media should based on.
/// </summary>
/// <remarks>
/// Note that using this method will simply return a new IMedia without any identity
/// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
/// that does not invoke a save operation against the database.
/// </remarks>
/// <param name="name">Name of the Media object</param>
/// <param name="parentId">Id of Parent for the new Media item</param>
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
@@ -22,8 +27,13 @@ namespace Umbraco.Core.Services
/// <summary>
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
/// that this Media is based on.
/// that this Media should based on.
/// </summary>
/// <remarks>
/// Note that using this method will simply return a new IMedia without any identity
/// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
/// that does not invoke a save operation against the database.
/// </remarks>
/// <param name="name">Name of the Media object</param>
/// <param name="parent">Parent <see cref="IMedia"/> for the new Media item</param>
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
@@ -184,5 +194,45 @@ namespace Umbraco.Core.Services
/// <param name="mediaPath">Path of the media item to retreive (for example: /media/1024/koala_403x328.jpg)</param>
/// <returns><see cref="IMedia"/></returns>
IMedia GetMediaByPath(string mediaPath);
/// <summary>
/// Sorts a collection of <see cref="IMedia"/> objects by updating the SortOrder according
/// to the ordering of items in the passed in <see cref="SortedSet{T}"/>.
/// </summary>
/// <param name="items"></param>
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
bool Sort(SortedSet<IMedia> items, int userId = 0, bool raiseEvents = true);
/// <summary>
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
/// that this Media should based on.
/// </summary>
/// <remarks>
/// This method returns an <see cref="IMedia"/> object that has been persisted to the database
/// and therefor has an identity.
/// </remarks>
/// <param name="name">Name of the Media object</param>
/// <param name="parent">Parent <see cref="IMedia"/> for the new Media item</param>
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
/// <param name="userId">Optional id of the user creating the media item</param>
/// <returns><see cref="IMedia"/></returns>
IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTypeAlias, int userId = 0);
/// <summary>
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
/// that this Media should based on.
/// </summary>
/// <remarks>
/// This method returns an <see cref="IMedia"/> object that has been persisted to the database
/// and therefor has an identity.
/// </remarks>
/// <param name="name">Name of the Media object</param>
/// <param name="parentId">Id of Parent for the new Media item</param>
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
/// <param name="userId">Optional id of the user creating the media item</param>
/// <returns><see cref="IMedia"/></returns>
IMedia CreateMediaWithIdentity(string name, int parentId, string mediaTypeAlias, int userId = 0);
}
}
+204 -50
View File
@@ -37,8 +37,13 @@ namespace Umbraco.Core.Services
/// <summary>
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
/// that this Media is based on.
/// that this Media should based on.
/// </summary>
/// <remarks>
/// Note that using this method will simply return a new IMedia without any identity
/// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
/// that does not invoke a save operation against the database.
/// </remarks>
/// <param name="name">Name of the Media object</param>
/// <param name="parentId">Id of Parent for the new Media item</param>
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
@@ -46,25 +51,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMedia"/></returns>
public IMedia CreateMedia(string name, int parentId, string mediaTypeAlias, int userId = 0)
{
IMediaType mediaType;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
var query = Query<IMediaType>.Builder.Where(x => x.Alias == mediaTypeAlias);
var mediaTypes = repository.GetByQuery(query);
if (!mediaTypes.Any())
throw new Exception(string.Format("No MediaType matching the passed in Alias: '{0}' was found",
mediaTypeAlias));
mediaType = mediaTypes.First();
if (mediaType == null)
throw new Exception(string.Format("MediaType matching the passed in Alias: '{0}' was null",
mediaTypeAlias));
}
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
var media = new Models.Media(name, parentId, mediaType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId), this))
@@ -84,8 +71,13 @@ namespace Umbraco.Core.Services
/// <summary>
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
/// that this Media is based on.
/// that this Media should based on.
/// </summary>
/// <remarks>
/// Note that using this method will simply return a new IMedia without any identity
/// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
/// that does not invoke a save operation against the database.
/// </remarks>
/// <param name="name">Name of the Media object</param>
/// <param name="parent">Parent <see cref="IMedia"/> for the new Media item</param>
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
@@ -93,25 +85,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMedia"/></returns>
public IMedia CreateMedia(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
{
IMediaType mediaType;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
var query = Query<IMediaType>.Builder.Where(x => x.Alias == mediaTypeAlias);
var mediaTypes = repository.GetByQuery(query);
if (!mediaTypes.Any())
throw new Exception(string.Format("No MediaType matching the passed in Alias: '{0}' was found",
mediaTypeAlias));
mediaType = mediaTypes.First();
if (mediaType == null)
throw new Exception(string.Format("MediaType matching the passed in Alias: '{0}' was null",
mediaTypeAlias));
}
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
var media = new Models.Media(name, parent, mediaType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parent), this))
{
@@ -128,6 +102,94 @@ namespace Umbraco.Core.Services
return media;
}
/// <summary>
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
/// that this Media should based on.
/// </summary>
/// <remarks>
/// This method returns an <see cref="IMedia"/> object that has been persisted to the database
/// and therefor has an identity.
/// </remarks>
/// <param name="name">Name of the Media object</param>
/// <param name="parentId">Id of Parent for the new Media item</param>
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
/// <param name="userId">Optional id of the user creating the media item</param>
/// <returns><see cref="IMedia"/></returns>
public IMedia CreateMediaWithIdentity(string name, int parentId, string mediaTypeAlias, int userId = 0)
{
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
var media = new Models.Media(name, parentId, mediaType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId), this))
{
media.WasCancelled = true;
return media;
}
using (new WriteLock(Locker))
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
{
media.CreatorId = userId;
repository.AddOrUpdate(media);
uow.Commit();
var xml = media.ToXml();
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
}
}
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId), this);
Audit.Add(AuditTypes.New, "", media.CreatorId, media.Id);
return media;
}
/// <summary>
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
/// that this Media should based on.
/// </summary>
/// <remarks>
/// This method returns an <see cref="IMedia"/> object that has been persisted to the database
/// and therefor has an identity.
/// </remarks>
/// <param name="name">Name of the Media object</param>
/// <param name="parent">Parent <see cref="IMedia"/> for the new Media item</param>
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
/// <param name="userId">Optional id of the user creating the media item</param>
/// <returns><see cref="IMedia"/></returns>
public IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
{
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
var media = new Models.Media(name, parent, mediaType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parent), this))
{
media.WasCancelled = true;
return media;
}
using (new WriteLock(Locker))
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
{
media.CreatorId = userId;
repository.AddOrUpdate(media);
uow.Commit();
var xml = media.ToXml();
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
}
}
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parent), this);
Audit.Add(AuditTypes.New, "", media.CreatorId, media.Id);
return media;
}
/// <summary>
/// Gets an <see cref="IMedia"/> object by Id
/// </summary>
@@ -598,18 +660,14 @@ namespace Umbraco.Core.Services
uow.Commit();
var xml = media.ToXml();
var poco = new ContentXmlDto {NodeId = media.Id, Xml = xml.ToString(SaveOptions.None)};
var exists = uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new {Id = media.Id}) != null;
int result = exists
? uow.Database.Update(poco)
: Convert.ToInt32(uow.Database.Insert(poco));
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
}
if (raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
Audit.Add(AuditTypes.Save, "Save Media performed by user", media.CreatorId, media.Id);
}
if (raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
Audit.Add(AuditTypes.Save, "Save Media performed by user", userId, media.Id);
}
/// <summary>
@@ -626,6 +684,7 @@ namespace Umbraco.Core.Services
return;
}
var mediaXml = new Dictionary<int, Lazy<XElement>>();
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
{
@@ -637,6 +696,11 @@ namespace Umbraco.Core.Services
//commit the whole lot in one go
uow.Commit();
foreach (var media in medias)
{
CreateAndSaveMediaXml(media.ToXml(), media.Id, uow.Database);
}
}
if(raiseEvents)
@@ -645,6 +709,67 @@ namespace Umbraco.Core.Services
Audit.Add(AuditTypes.Save, "Save Media items performed by user", userId, -1);
}
/// <summary>
/// Sorts a collection of <see cref="IMedia"/> objects by updating the SortOrder according
/// to the ordering of items in the passed in <see cref="SortedSet{T}"/>.
/// </summary>
/// <param name="items"></param>
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
public bool Sort(SortedSet<IMedia> items, int userId = 0, bool raiseEvents = true)
{
if (raiseEvents)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMedia>(items), this))
return false;
}
var shouldBeCached = new List<IMedia>();
using (new WriteLock(Locker))
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
{
int i = 0;
foreach (var media in items)
{
//If the current sort order equals that of the media
//we don't need to update it, so just increment the sort order
//and continue.
if (media.SortOrder == i)
{
i++;
continue;
}
media.SortOrder = i;
i++;
repository.AddOrUpdate(media);
shouldBeCached.Add(media);
}
uow.Commit();
foreach (var content in shouldBeCached)
{
//Create and Save ContentXml DTO
var xml = content.ToXml();
CreateAndSaveMediaXml(xml, content.Id, uow.Database);
}
}
}
if (raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IMedia>(items, false), this);
Audit.Add(AuditTypes.Sort, "Sorting Media performed by user", userId, 0);
return true;
}
/// <summary>
/// Updates the Path and Level on a collection of <see cref="IMedia"/> objects
/// based on the Parent's Path and Level.
@@ -671,6 +796,35 @@ namespace Umbraco.Core.Services
return list;
}
private void CreateAndSaveMediaXml(XElement xml, int id, UmbracoDatabase db)
{
var poco = new ContentXmlDto { NodeId = id, Xml = xml.ToString(SaveOptions.None) };
var exists = db.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = id }) != null;
int result = exists ? db.Update(poco) : Convert.ToInt32(db.Insert(poco));
}
private IMediaType FindMediaTypeByAlias(string mediaTypeAlias)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
var query = Query<IMediaType>.Builder.Where(x => x.Alias == mediaTypeAlias);
var mediaTypes = repository.GetByQuery(query);
if (mediaTypes.Any() == false)
throw new Exception(string.Format("No MediaType matching the passed in Alias: '{0}' was found",
mediaTypeAlias));
var mediaType = mediaTypes.First();
if (mediaType == null)
throw new Exception(string.Format("MediaType matching the passed in Alias: '{0}' was null",
mediaTypeAlias));
return mediaType;
}
}
#region Event Handlers
/// <summary>
@@ -324,6 +324,7 @@ namespace Umbraco.Core.Services
var template = _fileService.GetTemplate(alias);
if (template != null)
{
if(allowedTemplates.Any(x => x.Id == template.Id)) continue;
allowedTemplates.Add(template);
}
else
+1 -1
View File
@@ -675,7 +675,7 @@
<Compile Include="IfExtensions.cs" />
<Compile Include="PluginManager.cs" />
<Compile Include="IO\FileSecurityException.cs" />
<Compile Include="IO\FileSystemProvider.cs" />
<Compile Include="IO\FileSystemProviderConstants.cs" />
<Compile Include="IO\FileSystemProviderManager.cs" />
<Compile Include="IO\IFileSystem.cs" />
<Compile Include="IO\IOHelper.cs" />
@@ -14,7 +14,7 @@ namespace Umbraco.Tests.IO
[Test]
public void Can_Get_Base_File_System()
{
var fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media);
var fs = FileSystemProviderManager.Current.GetUnderlyingFileSystemProvider(FileSystemProviderConstants.Media);
Assert.NotNull(fs);
}
+1 -1
View File
@@ -317,7 +317,7 @@ namespace Umbraco.Tests
public void Resolves_RestExtensions()
{
var types = PluginManager.Current.ResolveRestExtensions();
Assert.AreEqual(2, types.Count());
Assert.AreEqual(3, types.Count());
}
[Test]
@@ -30,7 +30,7 @@ namespace Umbraco.Tests.PublishedContent
//need to specify a custom callback for unit tests
PublishedContentHelper.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
{
if (propertyAlias == "content")
if (propertyAlias.InvariantEquals("content"))
{
//return the rte type id
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
@@ -222,6 +222,10 @@ namespace Umbraco.Tests.PublishedContent
var propVal2 = doc.GetPropertyValue<IHtmlString>("content");
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(propVal2.GetType()));
Assert.AreEqual("<div>This is some content</div>", propVal2.ToString());
var propVal3 = doc.GetPropertyValue("Content");
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(propVal3.GetType()));
Assert.AreEqual("<div>This is some content</div>", propVal3.ToString());
}
[Test]
@@ -162,6 +162,30 @@ namespace Umbraco.Tests.Services.Importing
Assert.That(contentMaster.PropertyGroups["SEO"].PropertyTypes.Any(x => x.PropertyGroupId.Value != propertyGroupId), Is.False);
}
[Test]
public void PackagingService_Can_Import_StandardMvc_ContentTypes_And_Templates_Xml()
{
// Arrange
string strXml = ImportResources.StandardMvc_Package;
var xml = XElement.Parse(strXml);
var dataTypeElement = xml.Descendants("DataTypes").First();
var templateElement = xml.Descendants("Templates").First();
var docTypeElement = xml.Descendants("DocumentTypes").First();
// Act
var dataTypeDefinitions = ServiceContext.PackagingService.ImportDataTypeDefinitions(dataTypeElement);
var templates = ServiceContext.PackagingService.ImportTemplates(templateElement);
var contentTypes = ServiceContext.PackagingService.ImportContentTypes(docTypeElement);
var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count();
//Assert - Re-Import contenttypes doesn't throw
Assert.DoesNotThrow(() => ServiceContext.PackagingService.ImportContentTypes(docTypeElement));
Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes));
Assert.That(dataTypeDefinitions, Is.Not.Null);
Assert.That(dataTypeDefinitions.Any(), Is.True);
Assert.That(templates.Any(), Is.True);
}
[Test]
public void PackagingService_Can_Import_Content_Package_Xml()
{
@@ -34,7 +34,7 @@ UmbracoSpeechBubble.prototype.ShowMessage = function (icon, header, message, don
if (!dontAutoHide) {
jQuery("#" + this.id).fadeIn("slow").animate({ opacity: 1.0 }, 5000).fadeOut("fast");
} else {
speechBubble.jQuery(".speechClose").show();
jQuery(".speechClose").show();
jQuery("#" + this.id).fadeIn("slow");
}
} else {
@@ -173,7 +173,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls");
var self = this;
// Inject the upload overlay
var instructions = 'draggable' in document.createElement('span') ? "<h1>Drag files here to upload</h1> \<p>Or, click the button below to chose the items to upload</p>" : "<h1>Click the browse button below to chose the items to upload</h1>";
var instructions = 'draggable' in document.createElement('span') ? "<h1>Drag files here to upload</h1> \<p>Or, click the button below to choose the items to upload</p>" : "<h1>Click the browse button below to choose the items to upload</h1>";
var overlay = $("<div class='upload-overlay'>" +
"<div class='upload-panel'>" +
@@ -7,7 +7,6 @@ var UmbracoEmbedDialog = {
tinyMCEPopup.close();
},
showPreview: function () {
$('#insert').attr('disabled', 'disabled');
var url = $('#url').val();
@@ -16,44 +15,39 @@ var UmbracoEmbedDialog = {
$('#preview').html('<img src="img/ajax-loader.gif" alt="loading"/>');
$('#source').val('');
$.ajax(
{
type: 'POST',
async: true,
url: '../../../../umbraco/webservices/api/mediaservice.asmx/Embed',
data: '{ url: "' + url + '", width: "' + width + '", height: "' + height + '" }',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (msg) {
var resultAsJson = msg.d;
switch (resultAsJson.Status) {
case 0:
//not supported
$('#preview').html('Not Supported');
break;
case 1:
//error
$('#preview').html('Error');
break;
case 2:
$('#preview').html(resultAsJson.Markup);
$('#source').val(resultAsJson.Markup);
if (resultAsJson.SupportsDimensions) {
$('#dimensions').show();
} else {
$('#dimensions').hide();
}
$('#insert').removeAttr('disabled');
break;
$.ajax({
type: 'POST',
async: true,
url: '../../../../base/EmbedMediaService/Embed/',
data: { url: url, width: width, height: height },
dataType: 'json',
success: function (result) {
switch (result.Status) {
case 0:
//not supported
$('#preview').html('Not Supported');
break;
case 1:
//error
$('#preview').html('Error');
break;
case 2:
$('#preview').html(result.Markup);
$('#source').val(result.Markup);
if (result.SupportsDimensions) {
$('#dimensions').show();
} else {
$('#dimensions').hide();
}
},
error: function (xhr, ajaxOptions, thrownError) {
$('#preview').html("Error");
//alert(xhr.status);
//alert(thrownError);
}
});
$('#insert').removeAttr('disabled');
break;
}
},
error: function (xhr, ajaxOptions, thrownError) {
$('#preview').html("Error");
}
});
},
beforeResize: function () {
this.width = parseInt($('#width').val(), 10);
@@ -73,11 +67,9 @@ var UmbracoEmbedDialog = {
$('#width').val(this.width);
}
}
if ($('#url').val() != '') {
UmbracoEmbedDialog.showPreview();
}
},
changeSource: function (type) {
if ($('#source').val() != '') {
@@ -1,3 +1,3 @@
tinyMCE.addI18n('da.umbracoembed', {
desc: 'Inds\u00E6t ekstern mediefil',
desc: 'Inds\u00E6t ekstern mediefil'
});
@@ -1,3 +1,3 @@
tinyMCE.addI18n('en.umbracoembed', {
desc: 'Embed third party media',
desc: 'Embed third party media'
});
@@ -1,3 +1,3 @@
tinyMCE.addI18n('en_us.umbracoembed', {
desc: 'Embed third party media',
desc: 'Embed third party media'
});
+1 -1
View File
@@ -114,7 +114,7 @@ namespace Umbraco.Web.Mvc
else
{
//exit the loop
currentRouteData = null;
currentContext = null;
}
}
return new Attempt<RouteDefinition>(
+1
View File
@@ -1805,6 +1805,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>Reference.map</DependentUpon>
</Compile>
<Compile Include="WebServices\EmbedMediaService.cs" />
<Compile Include="WebServices\FolderBrowserService.cs" />
<Compile Include="WebServices\UmbracoAuthorizedHttpHandler.cs" />
<Compile Include="WebServices\SaveFileController.cs" />
@@ -0,0 +1,84 @@
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Script.Serialization;
using System.Xml;
using Umbraco.Core.Configuration;
using Umbraco.Core.Media;
using umbraco.BusinessLogic;
using Umbraco.Web.BaseRest;
namespace Umbraco.Web.WebServices
{
[RestExtension("EmbedMediaService")]
public class EmbedMediaService
{
[RestExtensionMethod(ReturnXml = false)]
public static string Embed()
{
var currentUser = User.GetCurrent();
if (currentUser == null)
throw new UnauthorizedAccessException("You must be logged in to use this service");
var url = HttpContext.Current.Request.Form["url"];
var width = int.Parse(HttpContext.Current.Request.Form["width"]);
var height = int.Parse(HttpContext.Current.Request.Form["height"]);
var result = new Result();
//todo cache embed doc
var xmlConfig = new XmlDocument();
xmlConfig.Load(GlobalSettings.FullpathToRoot + Path.DirectorySeparatorChar + "config" + Path.DirectorySeparatorChar + "EmbeddedMedia.config");
foreach (XmlNode node in xmlConfig.SelectNodes("//provider"))
{
var regexPattern = new Regex(node.SelectSingleNode("./urlShemeRegex").InnerText, RegexOptions.IgnoreCase);
if (regexPattern.IsMatch(url))
{
var prov = (IEmbedProvider)Activator.CreateInstance(Type.GetType(node.Attributes["type"].Value));
if (node.Attributes["supportsDimensions"] != null)
result.SupportsDimensions = node.Attributes["supportsDimensions"].Value == "True";
else
result.SupportsDimensions = prov.SupportsDimensions;
var settings = node.ChildNodes.Cast<XmlNode>().ToDictionary(settingNode => settingNode.Name);
foreach (var prop in prov.GetType().GetProperties().Where(prop => prop.IsDefined(typeof(ProviderSetting), true)))
{
if (settings.Any(s => s.Key.ToLower() == prop.Name.ToLower()))
{
var setting = settings.FirstOrDefault(s => s.Key.ToLower() == prop.Name.ToLower()).Value;
var settingType = typeof(Media.EmbedProviders.Settings.String);
if (setting.Attributes["type"] != null)
settingType = Type.GetType(setting.Attributes["type"].Value);
var settingProv = (IEmbedSettingProvider)Activator.CreateInstance(settingType);
prop.SetValue(prov, settingProv.GetSetting(settings.FirstOrDefault(s => s.Key.ToLower() == prop.Name.ToLower()).Value), null);
}
}
try
{
result.Markup = prov.GetMarkup(url, width, height);
result.Status = Status.Success;
}
catch
{
result.Status = Status.Error;
}
return new JavaScriptSerializer().Serialize(result);
}
}
result.Status = Status.NotSupported;
return new JavaScriptSerializer().Serialize(result);
}
}
}
@@ -1,16 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using Umbraco.Core;
using Umbraco.Web.Media.ThumbnailProviders;
using umbraco.BasePages;
using umbraco.BusinessLogic;
using umbraco.IO;
using Umbraco.Core.IO;
using umbraco.cms.businesslogic.Tags;
using umbraco.cms.businesslogic.media;
using Umbraco.Web.BaseRest;
namespace Umbraco.Web.WebServices
@@ -23,26 +18,20 @@ namespace Umbraco.Web.WebServices
[RestExtensionMethod(ReturnXml = false)]
public static string GetChildren(int parentId)
{
var currentUser = GetCurrentUser();
var parentMedia = new global::umbraco.cms.businesslogic.media.Media(parentId);
var currentUser = User.GetCurrent();
AuthorizeAccess(parentMedia, currentUser);
var data = new List<object>();
// Check user is logged in
if (currentUser == null)
throw new UnauthorizedAccessException("You must be logged in to use this service");
// Check user is allowed to access selected media item
if(!("," + parentMedia.Path + ",").Contains("," + currentUser.StartMediaId + ","))
throw new UnauthorizedAccessException("You do not have access to this Media node");
// Get children and filter
//TODO: Only fetch files, not containers
//TODO: Cache responses to speed up susequent searches
foreach (var child in parentMedia.Children)
{
var fileProp = child.getProperty("umbracoFile") ??
child.GenericProperties.FirstOrDefault(x =>
x.PropertyType.DataTypeDefinition.DataType.Id == new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"));
child.GenericProperties.FirstOrDefault(x => x.PropertyType.DataTypeDefinition.DataType.Id == new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"));
var fileUrl = fileProp != null ? fileProp.Value.ToString() : "";
var thumbUrl = ThumbnailProvidersResolver.Current.GetThumbnailUrl(fileUrl);
@@ -55,9 +44,9 @@ namespace Umbraco.Web.WebServices
MediaTypeAlias = child.ContentType.Alias,
EditUrl = string.Format("editMedia.aspx?id={0}", child.Id),
FileUrl = fileUrl,
ThumbnailUrl = !string.IsNullOrEmpty(thumbUrl)
? thumbUrl
: IOHelper.ResolveUrl(SystemDirectories.Umbraco + "/images/thumbnails/" + child.ContentType.Thumbnail)
ThumbnailUrl = string.IsNullOrEmpty(thumbUrl)
? IOHelper.ResolveUrl(SystemDirectories.Umbraco + "/images/thumbnails/" + child.ContentType.Thumbnail)
: thumbUrl
};
data.Add(item);
@@ -69,15 +58,19 @@ namespace Umbraco.Web.WebServices
[RestExtensionMethod(ReturnXml = false)]
public static string Delete(string nodeIds)
{
var nodeIdParts = nodeIds.Split(',');
var currentUser = GetCurrentUser();
foreach (var nodeIdPart in nodeIdParts.Where(x => !string.IsNullOrEmpty(x)))
var nodeIdParts = nodeIds.Split(',');
foreach (var nodeIdPart in nodeIdParts.Where(x => string.IsNullOrEmpty(x) == false))
{
var nodeId = 0;
if (!Int32.TryParse(nodeIdPart, out nodeId))
int nodeId;
if (Int32.TryParse(nodeIdPart, out nodeId) == false)
continue;
var node = new global::umbraco.cms.businesslogic.media.Media(nodeId);
AuthorizeAccess(node, currentUser);
node.delete(("," + node.Path + ",").Contains(",-21,"));
}
@@ -86,5 +79,20 @@ namespace Umbraco.Web.WebServices
success = true
});
}
private static User GetCurrentUser()
{
var currentUser = User.GetCurrent();
if (currentUser == null)
throw new UnauthorizedAccessException("You must be logged in to use this service");
return currentUser;
}
private static void AuthorizeAccess(global::umbraco.cms.businesslogic.media.Media mediaItem, User currentUser)
{
if (("," + mediaItem.Path + ",").Contains("," + currentUser.StartMediaId + ",") == false)
throw new UnauthorizedAccessException("You do not have access to this Media node");
}
}
}
@@ -50,7 +50,7 @@ namespace umbraco.cms.presentation.Trees
private void Init()
{
m_JSSerializer = new JSONSerializer();
m_JSSerializer = new JSONSerializer { MaxJsonLength = int.MaxValue };
switch (m_TreeType)
{
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using Umbraco.Web.WebServices;
using umbraco.BasePages;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.web;
using umbraco.cms.businesslogic;
@@ -25,77 +25,44 @@ namespace umbraco.presentation.umbraco.webservices
public override void ProcessRequest(HttpContext context)
{
//user must be allowed to see content or media
if (!AuthorizeRequest(DefaultApps.content.ToString()) && !AuthorizeRequest(DefaultApps.media.ToString()))
return;
if (BasePage.ValidateUserContextID(BasePage.umbracoUserContextID) == false)
throw new Exception("Client authorization failed. User is not logged in");
//user must be allowed to see content or media
if (AuthorizeRequest(DefaultApps.content.ToString()) == false && AuthorizeRequest(DefaultApps.media.ToString()) == false)
return;
context.Response.ContentType = "text/plain";
_prefix = context.Request.QueryString["q"];
int parentNodeId = Convert.ToInt32(context.Request.QueryString["id"]);
bool showGrandChildren = Convert.ToBoolean(context.Request.QueryString["showchildren"]);
var parentNodeId = Convert.ToInt32(context.Request.QueryString["id"]);
var showGrandChildren = Convert.ToBoolean(context.Request.QueryString["showchildren"]);
string documentAliasFilter = context.Request.QueryString["filter"];
string[] documentAliasFilters = documentAliasFilter.Split(",".ToCharArray());
var documentAliasFilter = context.Request.QueryString["filter"];
var documentAliasFilters = documentAliasFilter.Split(",".ToCharArray());
var parent = new CMSNode(parentNodeId);
CMSNode parent = new CMSNode(parentNodeId);
if (!showGrandChildren)
_nodeCount = 0;
//store children array here because iterating over an Array property object is very inneficient.
var children = parent.Children;
foreach (CMSNode child in children)
{
_nodeCount = 0;
//store children array here because iterating over an Array property object is very inneficient.
var children = parent.Children;
foreach (CMSNode child in children)
{
NodeChildrenCount(child, false, documentAliasFilters);
}
_output = new string[_nodeCount];
_counter = 0;
int level = 1;
//why is there a 2nd iteration of the same thing here?
foreach (CMSNode child in children)
{
AddNode(child, level, showGrandChildren, documentAliasFilters);
}
}
else
{
_nodeCount = 0;
//store children array here because iterating over an Array property object is very inneficient.
var children = parent.Children;
foreach (CMSNode child in children)
{
NodeChildrenCount(child, true, documentAliasFilters);
}
_output = new string[_nodeCount];
_counter = 0;
int level = 1;
foreach (CMSNode child in children)
{
AddNode(child, level, showGrandChildren, documentAliasFilters);
}
NodeChildrenCount(child, showGrandChildren, documentAliasFilters);
}
_output = new string[_nodeCount];
_counter = 0;
int level = 1;
foreach (string item in _output)
foreach (CMSNode child in children)
{
AddNode(child, level, showGrandChildren, documentAliasFilters);
}
foreach (var item in _output)
{
context.Response.Write(item + Environment.NewLine);
}
@@ -103,38 +70,21 @@ namespace umbraco.presentation.umbraco.webservices
private bool ValidNode(string nodeText)
{
if (nodeText.Length >= _prefix.Length)
{
if (nodeText.Substring(0, _prefix.Length).ToLower() == _prefix.ToLower())
{
return true;
}
}
return false;
return nodeText.Length >= _prefix.Length && nodeText.Substring(0, _prefix.Length).ToLower() == _prefix.ToLower();
}
private void NodeChildrenCount(CMSNode node, bool countChildren, string[] documentAliasFilters)
{
if (documentAliasFilters.Length > 0)
{
foreach (string filter in documentAliasFilters)
foreach (var filter in documentAliasFilters)
{
string trimmedFilter = filter.TrimStart(" ".ToCharArray());
var trimmedFilter = filter.TrimStart(" ".ToCharArray());
trimmedFilter = trimmedFilter.TrimEnd(" ".ToCharArray());
if (new Document(node.Id).ContentType.Alias == trimmedFilter || trimmedFilter == string.Empty)
if ((new Document(node.Id).ContentType.Alias == trimmedFilter || trimmedFilter == string.Empty) && ValidNode(node.Text))
{
if (ValidNode(node.Text))
{
_nodeCount += 1;
}
_nodeCount += 1;
}
}
}
@@ -160,28 +110,24 @@ namespace umbraco.presentation.umbraco.webservices
private void AddNode(CMSNode node, int level, bool showGrandChildren, string[] documentAliasFilters)
{
var preText = string.Empty;
string preText = string.Empty;
for (int i = 1; i < level; i++)
for (var i = 1; i < level; i++)
{
preText += "- ";
}
if (documentAliasFilters.Length > 0)
{
foreach (string filter in documentAliasFilters)
foreach (var filter in documentAliasFilters)
{
string trimmedFilter = filter.TrimStart(" ".ToCharArray());
var trimmedFilter = filter.TrimStart(" ".ToCharArray());
trimmedFilter = trimmedFilter.TrimEnd(" ".ToCharArray());
if (new Document(node.Id).ContentType.Alias == trimmedFilter || trimmedFilter == string.Empty)
if ((new Document(node.Id).ContentType.Alias == trimmedFilter || trimmedFilter == string.Empty) && ValidNode(node.Text))
{
if (ValidNode(node.Text))
{
_output[_counter] = preText + node.Text + " [" + node.Id + "]";
_counter++;
}
_output[_counter] = preText + node.Text + " [" + node.Id + "]";
_counter++;
}
}
@@ -211,10 +157,7 @@ namespace umbraco.presentation.umbraco.webservices
public override bool IsReusable
{
get
{
return false;
}
get { return false; }
}
}
}
@@ -163,6 +163,8 @@ namespace umbraco.presentation.webservices
[ScriptMethod]
public string ProgressStatus(string Key)
{
AuthorizeRequest(true);
return Application[helper.Request("key")].ToString();
}
@@ -261,9 +261,17 @@ namespace umbraco.BasePages
return encTicket.DecryptWithMachineKey();
}
}
catch (HttpException ex)
catch (Exception ex)
{
// we swallow this type of exception as it happens if a legacy (pre 4.8.1) cookie is set
if (ex is ArgumentException || ex is FormatException || ex is HttpException)
{
StateHelper.Cookies.UserContext.Clear();
}
else
{
throw;
}
}
}
return "";
+2 -1
View File
@@ -146,7 +146,8 @@ namespace umbraco.cms.businesslogic
public static Guid GetDataType(string contentTypeAlias, string propertyTypeAlias)
{
var key = new System.Tuple<string, string>(contentTypeAlias, propertyTypeAlias);
//propertyTypeAlias needs to be invariant, so we will store uppercase
var key = new System.Tuple<string, string>(contentTypeAlias, propertyTypeAlias.ToUpper());
return PropertyTypeCache.GetOrAdd(
@@ -83,8 +83,8 @@ namespace umbraco.cms.businesslogic.workflow
{
// check if something was changed and display the changes otherwise display the fields
Property oldProperty = oldDoc.getProperty(p.PropertyType.Alias);
string oldText = oldProperty.Value.ToString();
string newText = p.Value.ToString();
string oldText = oldProperty.Value != null ? oldProperty.Value.ToString() : "";
string newText = p.Value != null ? p.Value.ToString() : "";
// replace html with char equivalent
ReplaceHTMLSymbols(ref oldText);
@@ -123,7 +123,7 @@ namespace umbraco.cms.businesslogic.workflow
summary.Append("<tr>");
summary.Append("<th style='text-align: left; vertical-align: top; width: 25%;'>" +
p.PropertyType.Name + "</th>");
summary.Append("<td style='text-align: left; vertical-align: top;'>" + p.Value.ToString() + "</td>");
summary.Append("<td style='text-align: left; vertical-align: top;'>" + newText + "</td>");
summary.Append("</tr>");
}
summary.Append(