Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c1853e8c51 | |||
| 31c965ae42 | |||
| d91fc6ce60 | |||
| d5124e9739 | |||
| d9b507c947 | |||
| d3fcdfb176 | |||
| 2479c5a272 | |||
| fee071db22 | |||
| 004e00599d | |||
| 2e2e8b43b0 | |||
| e77c5f8667 | |||
| 3509a2c40f | |||
| 378d0f7939 | |||
| d64fa7f92d | |||
| ea14170272 | |||
| 73209d7e2c | |||
| cf8ead62ac | |||
| 8461aea7d8 | |||
| 034de1651b | |||
| dcb8aa7e56 | |||
| e8a52a95da | |||
| 42c99e0f07 | |||
| a31b368b60 | |||
| 77f6d28a74 | |||
| 0b8d3ef214 | |||
| a4f83f9c00 | |||
| 85467976ad | |||
| d7e93fe466 | |||
| 660f048b4f | |||
| 9fa76a0133 | |||
| 444c444f0e | |||
| 383bbbe7e0 | |||
| 72eddca3c6 | |||
| 7c2ddde311 | |||
| c6229e4fcb | |||
| fbac0aba8b | |||
| f01511c592 | |||
| 187354f0bd | |||
| 2f540b1bfa | |||
| b1f104d1de | |||
| ba5fcad09a | |||
| d553eb2978 | |||
| d1e6c0e835 | |||
| 244977dc95 | |||
| 3242b31a8a | |||
| efc3261163 | |||
| 8c6aa9875d | |||
| f89ce1ff26 | |||
| 1274fbaefd | |||
| 8140dfdc04 | |||
| a69eba61c8 | |||
| 46078a841c | |||
| 0eb5e5f6e4 | |||
| ec9020f63e | |||
| 0b61685fc8 | |||
| 3779b3c782 | |||
| 5b0e824301 | |||
| d24b0aa9eb | |||
| 9cd7e09986 | |||
| 9f505a7976 | |||
| f737004544 | |||
| 850e354b11 | |||
| 1b27114014 | |||
| d8b235ad62 | |||
| 56581478c8 | |||
| 2be330d237 | |||
| 4381a700ba | |||
| 99821954f1 | |||
| 10a15be8ad | |||
| 0a2830aece | |||
| d1094eea7a | |||
| c629a50f39 | |||
| 430f906ae6 | |||
| 736798c769 | |||
| e913034d93 | |||
| bed5f8a03b | |||
| 0291ab615d | |||
| ceeea7827e | |||
| 756b4d24c0 | |||
| ffe3fc9257 | |||
| 26bd3c7c0b | |||
| 944b3dcaac | |||
| ba489afe9a | |||
| 968d52e490 | |||
| ebbe9f6ed0 | |||
| ba32636fe7 | |||
| a6f9d14a1b | |||
| 7cd385dd6b | |||
| 5d4a97591a | |||
| bfb81f6362 | |||
| 23816665f3 | |||
| ca3dc030bc | |||
| 67e3ec2ae0 | |||
| d295174e53 | |||
| da8c46e426 | |||
| 5880df3859 | |||
| 13ccd86192 | |||
| 336266c0eb | |||
| de9739118e |
@@ -37,8 +37,8 @@
|
||||
<dependency id="Examine" version="[0.1.82, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[2.5.3, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.3, 5.0.0)" />
|
||||
<dependency id="semver" version="[2.0.4, 3.0.0)" />
|
||||
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
|
||||
<dependency id="semver" version="[1.1.2, 3.0.0)" />
|
||||
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
|
||||
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.7.0, 5.0.0)" />
|
||||
</dependencies>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.7, 4.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.6.0
|
||||
RC2
|
||||
7.6.0
|
||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.6.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-RC2")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0")]
|
||||
@@ -8,6 +8,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
Guid Id { get; }
|
||||
string RepositoryUrl { get; }
|
||||
string WebServiceUrl { get; }
|
||||
bool HasCustomWebServiceUrl { get; }
|
||||
bool HasCustomWebServiceUrl { get; }
|
||||
string RestApiUrl { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public static class RepositoryConfigExtensions
|
||||
{
|
||||
//Our package repo
|
||||
private static readonly Guid RepoGuid = new Guid("65194810-1f85-11dd-bd0b-0800200c9a66");
|
||||
|
||||
public static IRepository GetDefault(this IRepositoriesSection repos)
|
||||
{
|
||||
var found = repos.Repositories.FirstOrDefault(x => x.Id == RepoGuid);
|
||||
if (found == null)
|
||||
throw new InvalidOperationException("No default package repository found with id " + RepoGuid);
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,9 +38,16 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get
|
||||
{
|
||||
var prop = Properties["webserviceurl"];
|
||||
var repoUrl = this[prop] as ConfigurationElement;
|
||||
return (repoUrl != null && repoUrl.ElementInformation.IsPresent);
|
||||
return (string) prop.DefaultValue != (string) this[prop];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty("restapiurl", DefaultValue = "https://our.umbraco.org/webapi/packages/v1")]
|
||||
public string RestApiUrl
|
||||
{
|
||||
get { return (string)base["restapiurl"]; }
|
||||
set { base["restapiurl"] = value; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets the version comment (like beta or RC).
|
||||
/// </summary>
|
||||
/// <value>The version comment.</value>
|
||||
public static string CurrentComment { get { return "RC2"; } }
|
||||
public static string CurrentComment { get { return ""; } }
|
||||
|
||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||
|
||||
@@ -1,85 +1,177 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Permissions;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event args for a strongly typed object that can support cancellation
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
|
||||
public class CancellableObjectEventArgs<T> : CancellableEventArgs, IEquatable<CancellableObjectEventArgs<T>>
|
||||
{
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
|
||||
/// <summary>
|
||||
/// Used as a base class for the generic type CancellableObjectEventArgs{T} so that we can get direct 'object' access to the underlying EventObject
|
||||
/// </summary>
|
||||
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
|
||||
public abstract class CancellableObjectEventArgs : CancellableEventArgs
|
||||
{
|
||||
protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
|
||||
: base(canCancel, messages, additionalData)
|
||||
{
|
||||
{
|
||||
EventObject = eventObject;
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages)
|
||||
protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(canCancel, eventMessages)
|
||||
{
|
||||
EventObject = eventObject;
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages)
|
||||
protected CancellableObjectEventArgs(object eventObject, EventMessages eventMessages)
|
||||
: this(eventObject, true, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
protected CancellableObjectEventArgs(object eventObject, bool canCancel)
|
||||
: base(canCancel)
|
||||
{
|
||||
EventObject = eventObject;
|
||||
}
|
||||
|
||||
protected CancellableObjectEventArgs(object eventObject)
|
||||
: this(eventObject, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the object relating to the event
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is protected so that inheritors can expose it with their own name
|
||||
/// </remarks>
|
||||
internal object EventObject { get; set; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for a strongly typed object that can support cancellation
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
|
||||
public class CancellableObjectEventArgs<T> : CancellableObjectEventArgs, IEquatable<CancellableObjectEventArgs<T>>
|
||||
{
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
|
||||
: base(eventObject, canCancel, messages, additionalData)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(eventObject, canCancel, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages)
|
||||
: base(eventObject, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel)
|
||||
: base(canCancel)
|
||||
{
|
||||
EventObject = eventObject;
|
||||
}
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject)
|
||||
: this(eventObject, true)
|
||||
{
|
||||
}
|
||||
public CancellableObjectEventArgs(T eventObject)
|
||||
: base(eventObject)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the object relating to the event
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is protected so that inheritors can expose it with their own name
|
||||
/// </remarks>
|
||||
protected T EventObject { get; set; }
|
||||
/// <summary>
|
||||
/// Returns the object relating to the event
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is protected so that inheritors can expose it with their own name
|
||||
/// </remarks>
|
||||
protected new T EventObject
|
||||
{
|
||||
get { return (T) base.EventObject; }
|
||||
set { base.EventObject = value; }
|
||||
}
|
||||
|
||||
public bool Equals(CancellableObjectEventArgs<T> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && EqualityComparer<T>.Default.Equals(EventObject, other.EventObject);
|
||||
}
|
||||
public bool Equals(CancellableObjectEventArgs<T> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && EqualityComparer<T>.Default.Equals(EventObject, other.EventObject);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((CancellableObjectEventArgs<T>) obj);
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((CancellableObjectEventArgs<T>)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (base.GetHashCode() * 397) ^ EqualityComparer<T>.Default.GetHashCode(EventObject);
|
||||
}
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (base.GetHashCode() * 397) ^ EqualityComparer<T>.Default.GetHashCode(EventObject);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator ==(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
|
||||
{
|
||||
return Equals(left, right);
|
||||
}
|
||||
public static bool operator ==(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
|
||||
{
|
||||
return Equals(left, right);
|
||||
}
|
||||
|
||||
public static bool operator !=(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
|
||||
{
|
||||
return !Equals(left, right);
|
||||
}
|
||||
}
|
||||
public static bool operator !=(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
|
||||
{
|
||||
return !Equals(left, right);
|
||||
}
|
||||
}
|
||||
|
||||
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
|
||||
public class CancellableEnumerableObjectEventArgs<T> : CancellableObjectEventArgs<IEnumerable<T>>, IEquatable<CancellableEnumerableObjectEventArgs<T>>
|
||||
{
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
|
||||
: base(eventObject, canCancel, messages, additionalData)
|
||||
{ }
|
||||
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(eventObject, canCancel, eventMessages)
|
||||
{ }
|
||||
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, EventMessages eventMessages)
|
||||
: base(eventObject, eventMessages)
|
||||
{ }
|
||||
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{ }
|
||||
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject)
|
||||
: base(eventObject)
|
||||
{ }
|
||||
|
||||
public bool Equals(CancellableEnumerableObjectEventArgs<T> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return EventObject.SequenceEqual(other.EventObject);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((CancellableEnumerableObjectEventArgs<T>)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCodeHelper.GetHashCode(EventObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class DeleteEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<DeleteEventArgs<TEntity>>, IDeletingMediaFilesEventArgs
|
||||
[SupersedeEvent(typeof(SaveEventArgs<>))]
|
||||
[SupersedeEvent(typeof(PublishEventArgs<>))]
|
||||
[SupersedeEvent(typeof(MoveEventArgs<>))]
|
||||
[SupersedeEvent(typeof(CopyEventArgs<>))]
|
||||
public class DeleteEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<DeleteEventArgs<TEntity>>, IDeletingMediaFilesEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the delete operation
|
||||
@@ -106,7 +111,7 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && MediaFilesToDelete.Equals(other.MediaFilesToDelete);
|
||||
return base.Equals(other) && MediaFilesToDelete.SequenceEqual(other.MediaFilesToDelete);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class ImportEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<ImportEventArgs<TEntity>>
|
||||
public class ImportEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportEventArgs<TEntity>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting an XElement with the xml being imported
|
||||
|
||||
@@ -4,7 +4,7 @@ using Umbraco.Core.Packaging.Models;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
internal class ImportPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<ImportPackageEventArgs<TEntity>>
|
||||
internal class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
|
||||
{
|
||||
private readonly MetaData _packageMetaData;
|
||||
|
||||
@@ -32,7 +32,8 @@ namespace Umbraco.Core.Events
|
||||
public bool Equals(ImportPackageEventArgs<TEntity> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
//TODO: MetaData for package metadata has no equality operators :/
|
||||
return base.Equals(other) && _packageMetaData.Equals(other._packageMetaData);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ using System.Linq;
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// This event manager supports event cancellation and will raise the events as soon as they are tracked, it does not store tracked events
|
||||
/// An IEventDispatcher that immediately raise all events.
|
||||
/// </summary>
|
||||
/// <remarks>This means that events will be raised during the scope transaction,
|
||||
/// whatever happens, and the transaction could roll back in the end.</remarks>
|
||||
internal class PassThroughEventDispatcher : IEventDispatcher
|
||||
{
|
||||
public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string eventName = null)
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class PublishEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<PublishEventArgs<TEntity>>
|
||||
public class PublishEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<PublishEventArgs<TEntity>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the publish operation
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class SaveEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
|
||||
public class SaveEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the saving operation
|
||||
@@ -116,7 +117,5 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
get { return EventObject; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,9 @@ using Umbraco.Core.IO;
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// This event manager is created for each scope and is aware of if it is nested in an outer scope
|
||||
/// An IEventDispatcher that queues events, and raise them when the scope
|
||||
/// exits and has been completed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The outer scope is the only scope that can raise events, the inner scope's will defer to the outer scope
|
||||
/// </remarks>
|
||||
internal class ScopeEventDispatcher : ScopeEventDispatcherBase
|
||||
{
|
||||
public ScopeEventDispatcher()
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// An IEventDispatcher that queues events.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Can raise, or ignore, cancelable events, depending on option.</para>
|
||||
/// <para>Implementations must override ScopeExitCompleted to define what
|
||||
/// to do with the events when the scope exits and has been completed.</para>
|
||||
/// <para>If the scope exits without being completed, events are ignored.</para>
|
||||
/// </remarks>
|
||||
public abstract class ScopeEventDispatcherBase : IEventDispatcher
|
||||
{
|
||||
//events will be enlisted in the order they are raised
|
||||
private List<IEventDefinition> _events;
|
||||
private readonly bool _raiseCancelable;
|
||||
|
||||
@@ -64,29 +76,263 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
if (_events == null)
|
||||
return Enumerable.Empty<IEventDefinition>();
|
||||
|
||||
|
||||
switch (filter)
|
||||
{
|
||||
case EventDefinitionFilter.All:
|
||||
return _events;
|
||||
return FilterSupersededAndUpdateToLatestEntity(_events);
|
||||
case EventDefinitionFilter.FirstIn:
|
||||
var l1 = new OrderedHashSet<IEventDefinition>();
|
||||
foreach (var e in _events)
|
||||
{
|
||||
l1.Add(e);
|
||||
}
|
||||
return l1;
|
||||
return FilterSupersededAndUpdateToLatestEntity(l1);
|
||||
case EventDefinitionFilter.LastIn:
|
||||
var l2 = new OrderedHashSet<IEventDefinition>(keepOldest: false);
|
||||
foreach (var e in _events)
|
||||
{
|
||||
l2.Add(e);
|
||||
}
|
||||
return l2;
|
||||
return FilterSupersededAndUpdateToLatestEntity(l2);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("filter", filter, null);
|
||||
}
|
||||
}
|
||||
|
||||
private class EventDefinitionTypeData
|
||||
{
|
||||
public IEventDefinition EventDefinition { get; set; }
|
||||
public Type EventArgType { get; set; }
|
||||
public SupersedeEventAttribute[] SupersedeAttributes { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will iterate over the events (latest first) and filter out any events or entities in event args that are included
|
||||
/// in more recent events that Supersede previous ones. For example, If an Entity has been Saved and then Deleted, we don't want
|
||||
/// to raise the Saved event (well actually we just don't want to include it in the args for that saved event)
|
||||
/// </summary>
|
||||
/// <param name="events"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<IEventDefinition> FilterSupersededAndUpdateToLatestEntity(IReadOnlyList<IEventDefinition> events)
|
||||
{
|
||||
//used to keep the 'latest' entity and associated event definition data
|
||||
var allEntities = new List<Tuple<IEntity, EventDefinitionTypeData>>();
|
||||
|
||||
//tracks all CancellableObjectEventArgs instances in the events which is the only type of args we can work with
|
||||
var cancelableArgs = new List<CancellableObjectEventArgs>();
|
||||
|
||||
var result = new List<IEventDefinition>();
|
||||
|
||||
//This will eagerly load all of the event arg types and their attributes so we don't have to continuously look this data up
|
||||
var allArgTypesWithAttributes = events.Select(x => x.Args.GetType())
|
||||
.Distinct()
|
||||
.ToDictionary(x => x, x => x.GetCustomAttributes<SupersedeEventAttribute>(false).ToArray());
|
||||
|
||||
//Iterate all events and collect the actual entities in them and relates them to their corresponding EventDefinitionTypeData
|
||||
//we'll process the list in reverse because events are added in the order they are raised and we want to filter out
|
||||
//any entities from event args that are not longer relevant
|
||||
//(i.e. if an item is Deleted after it's Saved, we won't include the item in the Saved args)
|
||||
for (var index = events.Count - 1; index >= 0; index--)
|
||||
{
|
||||
var eventDefinition = events[index];
|
||||
|
||||
var argType = eventDefinition.Args.GetType();
|
||||
var attributes = allArgTypesWithAttributes[eventDefinition.Args.GetType()];
|
||||
|
||||
var meta = new EventDefinitionTypeData
|
||||
{
|
||||
EventDefinition = eventDefinition,
|
||||
EventArgType = argType,
|
||||
SupersedeAttributes = attributes
|
||||
};
|
||||
|
||||
var args = eventDefinition.Args as CancellableObjectEventArgs;
|
||||
if (args != null)
|
||||
{
|
||||
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
|
||||
|
||||
if (list == null)
|
||||
{
|
||||
//extract the event object
|
||||
var obj = args.EventObject as IEntity;
|
||||
if (obj != null)
|
||||
{
|
||||
//Now check if this entity already exists in other event args that supersede this current event arg type
|
||||
if (IsFiltered(obj, meta, allEntities) == false)
|
||||
{
|
||||
//if it's not filtered we can adde these args to the response
|
||||
cancelableArgs.Add(args);
|
||||
result.Add(eventDefinition);
|
||||
//track the entity
|
||||
allEntities.Add(Tuple.Create(obj, meta));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Can't retrieve the entity so cant' filter or inspect, just add to the output
|
||||
result.Add(eventDefinition);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var toRemove = new List<IEntity>();
|
||||
foreach (var entity in list)
|
||||
{
|
||||
//extract the event object
|
||||
var obj = entity as IEntity;
|
||||
if (obj != null)
|
||||
{
|
||||
//Now check if this entity already exists in other event args that supersede this current event arg type
|
||||
if (IsFiltered(obj, meta, allEntities))
|
||||
{
|
||||
//track it to be removed
|
||||
toRemove.Add(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
//track the entity, it's not filtered
|
||||
allEntities.Add(Tuple.Create(obj, meta));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//we don't need to do anything here, we can't cast to IEntity so we cannot filter, so it will just remain in the list
|
||||
}
|
||||
}
|
||||
|
||||
//remove anything that has been filtered
|
||||
foreach (var entity in toRemove)
|
||||
{
|
||||
list.Remove(entity);
|
||||
}
|
||||
|
||||
//track the event and include in the response if there's still entities remaining in the list
|
||||
if (list.Count > 0)
|
||||
{
|
||||
if (toRemove.Count > 0)
|
||||
{
|
||||
//re-assign if the items have changed
|
||||
args.EventObject = list;
|
||||
}
|
||||
cancelableArgs.Add(args);
|
||||
result.Add(eventDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's not a cancelable event arg so we just include it in the result
|
||||
result.Add(eventDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
|
||||
UpdateToLatestEntities(allEntities, cancelableArgs);
|
||||
|
||||
//we need to reverse the result since we've been adding by latest added events first!
|
||||
result.Reverse();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void UpdateToLatestEntities(IEnumerable<Tuple<IEntity, EventDefinitionTypeData>> allEntities, IEnumerable<CancellableObjectEventArgs> cancelableArgs)
|
||||
{
|
||||
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
|
||||
|
||||
var latestEntities = new OrderedHashSet<IEntity>(keepOldest: true);
|
||||
foreach (var entity in allEntities.OrderByDescending(entity => entity.Item1.UpdateDate))
|
||||
{
|
||||
latestEntities.Add(entity.Item1);
|
||||
}
|
||||
|
||||
foreach (var args in cancelableArgs)
|
||||
{
|
||||
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
|
||||
if (list == null)
|
||||
{
|
||||
//try to find the args entity in the latest entity - based on the equality operators, this will
|
||||
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
|
||||
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
|
||||
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, args.EventObject));
|
||||
if (foundEntity != null)
|
||||
{
|
||||
args.EventObject = foundEntity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var updated = false;
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
//try to find the args entity in the latest entity - based on the equality operators, this will
|
||||
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
|
||||
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
|
||||
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, list[i]));
|
||||
if (foundEntity != null)
|
||||
{
|
||||
list[i] = foundEntity;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
args.EventObject = list;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will check against all of the processed entity/events (allEntities) to see if this entity already exists in
|
||||
/// event args that supersede the event args being passed in and if so returns true.
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="eventDef"></param>
|
||||
/// <param name="allEntities"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsFiltered(
|
||||
IEntity entity,
|
||||
EventDefinitionTypeData eventDef,
|
||||
List<Tuple<IEntity, EventDefinitionTypeData>> allEntities)
|
||||
{
|
||||
var argType = eventDef.EventDefinition.Args.GetType();
|
||||
|
||||
//check if the entity is found in any processed event data that could possible supersede this one
|
||||
var foundByEntity = allEntities
|
||||
.Where(x => x.Item2.SupersedeAttributes.Length > 0
|
||||
//if it's the same arg type than it cannot supersede
|
||||
&& x.Item2.EventArgType != argType
|
||||
&& Equals(x.Item1, entity))
|
||||
.ToArray();
|
||||
|
||||
//no args have been processed with this entity so it should not be filtered
|
||||
if (foundByEntity.Length == 0)
|
||||
return false;
|
||||
|
||||
if (argType.IsGenericType)
|
||||
{
|
||||
var supercededBy = foundByEntity
|
||||
.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeAttributes.Any(y =>
|
||||
//if the attribute type is a generic type def then compare with the generic type def of the event arg
|
||||
(y.SupersededEventArgsType.IsGenericTypeDefinition && y.SupersededEventArgsType == argType.GetGenericTypeDefinition())
|
||||
//if the attribute type is not a generic type def then compare with the normal type of the event arg
|
||||
|| (y.SupersededEventArgsType.IsGenericTypeDefinition == false && y.SupersededEventArgsType == argType)));
|
||||
return supercededBy != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var supercededBy = foundByEntity
|
||||
.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeAttributes.Any(y =>
|
||||
//since the event arg type is not a generic type, then we just compare type 1:1
|
||||
y.SupersededEventArgsType == argType));
|
||||
return supercededBy != null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ScopeExit(bool completed)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// This is used to know if the event arg attributed should supersede another event arg type when
|
||||
/// tracking events for the same entity. If one event args supercedes another then the event args that have been superseded
|
||||
/// will mean that the event will not be dispatched or the args will be filtered to exclude the entity.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
internal class SupersedeEventAttribute : Attribute
|
||||
{
|
||||
public Type SupersededEventArgsType { get; private set; }
|
||||
|
||||
public SupersedeEventAttribute(Type supersededEventArgsType)
|
||||
{
|
||||
SupersededEventArgsType = supersededEventArgsType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
internal class ConnectionException : Exception
|
||||
{
|
||||
public ConnectionException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Exceptions
|
||||
public T Operation { get; private set; }
|
||||
|
||||
public DataOperationException(T operation, string message)
|
||||
:base(message)
|
||||
: base(message)
|
||||
{
|
||||
Operation = operation;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -7,32 +6,32 @@ using System.Text;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to create a hash code from multiple objects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
|
||||
/// which we've not included here as we just need a quick easy class for this in order to create a unique
|
||||
/// hash of directories/files to see if they have changed.
|
||||
/// </remarks>
|
||||
internal class HashCodeCombiner
|
||||
{
|
||||
private long _combinedHash = 5381L;
|
||||
/// <summary>
|
||||
/// Used to create a hash code from multiple objects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
|
||||
/// which we've not included here as we just need a quick easy class for this in order to create a unique
|
||||
/// hash of directories/files to see if they have changed.
|
||||
/// </remarks>
|
||||
internal class HashCodeCombiner
|
||||
{
|
||||
private long _combinedHash = 5381L;
|
||||
|
||||
internal void AddInt(int i)
|
||||
{
|
||||
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
|
||||
}
|
||||
internal void AddInt(int i)
|
||||
{
|
||||
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
|
||||
}
|
||||
|
||||
internal void AddObject(object o)
|
||||
{
|
||||
AddInt(o.GetHashCode());
|
||||
}
|
||||
internal void AddObject(object o)
|
||||
{
|
||||
AddInt(o.GetHashCode());
|
||||
}
|
||||
|
||||
internal void AddDateTime(DateTime d)
|
||||
{
|
||||
AddInt(d.GetHashCode());
|
||||
}
|
||||
internal void AddDateTime(DateTime d)
|
||||
{
|
||||
AddInt(d.GetHashCode());
|
||||
}
|
||||
|
||||
internal void AddString(string s)
|
||||
{
|
||||
@@ -40,61 +39,61 @@ namespace Umbraco.Core
|
||||
AddInt((StringComparer.InvariantCulture).GetHashCode(s));
|
||||
}
|
||||
|
||||
internal void AddCaseInsensitiveString(string s)
|
||||
{
|
||||
if (s != null)
|
||||
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
|
||||
}
|
||||
internal void AddCaseInsensitiveString(string s)
|
||||
{
|
||||
if (s != null)
|
||||
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
|
||||
}
|
||||
|
||||
internal void AddFileSystemItem(FileSystemInfo f)
|
||||
{
|
||||
//if it doesn't exist, don't proceed.
|
||||
if (!f.Exists)
|
||||
return;
|
||||
internal void AddFileSystemItem(FileSystemInfo f)
|
||||
{
|
||||
//if it doesn't exist, don't proceed.
|
||||
if (!f.Exists)
|
||||
return;
|
||||
|
||||
AddCaseInsensitiveString(f.FullName);
|
||||
AddDateTime(f.CreationTimeUtc);
|
||||
AddDateTime(f.LastWriteTimeUtc);
|
||||
|
||||
//check if it is a file or folder
|
||||
var fileInfo = f as FileInfo;
|
||||
if (fileInfo != null)
|
||||
{
|
||||
AddInt(fileInfo.Length.GetHashCode());
|
||||
}
|
||||
|
||||
var dirInfo = f as DirectoryInfo;
|
||||
if (dirInfo != null)
|
||||
{
|
||||
foreach (var d in dirInfo.GetFiles())
|
||||
{
|
||||
AddFile(d);
|
||||
}
|
||||
foreach (var s in dirInfo.GetDirectories())
|
||||
{
|
||||
AddFolder(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
AddCaseInsensitiveString(f.FullName);
|
||||
AddDateTime(f.CreationTimeUtc);
|
||||
AddDateTime(f.LastWriteTimeUtc);
|
||||
|
||||
internal void AddFile(FileInfo f)
|
||||
{
|
||||
AddFileSystemItem(f);
|
||||
}
|
||||
//check if it is a file or folder
|
||||
var fileInfo = f as FileInfo;
|
||||
if (fileInfo != null)
|
||||
{
|
||||
AddInt(fileInfo.Length.GetHashCode());
|
||||
}
|
||||
|
||||
internal void AddFolder(DirectoryInfo d)
|
||||
{
|
||||
AddFileSystemItem(d);
|
||||
}
|
||||
var dirInfo = f as DirectoryInfo;
|
||||
if (dirInfo != null)
|
||||
{
|
||||
foreach (var d in dirInfo.GetFiles())
|
||||
{
|
||||
AddFile(d);
|
||||
}
|
||||
foreach (var s in dirInfo.GetDirectories())
|
||||
{
|
||||
AddFolder(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hex code of the combined hash code
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal string GetCombinedHashCode()
|
||||
{
|
||||
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
|
||||
}
|
||||
internal void AddFile(FileInfo f)
|
||||
{
|
||||
AddFileSystemItem(f);
|
||||
}
|
||||
|
||||
}
|
||||
internal void AddFolder(DirectoryInfo d)
|
||||
{
|
||||
AddFileSystemItem(d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hex code of the combined hash code
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal string GetCombinedHashCode()
|
||||
{
|
||||
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Borrowed from http://stackoverflow.com/a/2575444/694494
|
||||
/// </summary>
|
||||
internal static class HashCodeHelper
|
||||
{
|
||||
public static int GetHashCode<T1, T2>(T1 arg1, T2 arg2)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return 31 * arg1.GetHashCode() + arg2.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = arg1.GetHashCode();
|
||||
hash = 31 * hash + arg2.GetHashCode();
|
||||
return 31 * hash + arg3.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3,
|
||||
T4 arg4)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = arg1.GetHashCode();
|
||||
hash = 31 * hash + arg2.GetHashCode();
|
||||
hash = 31 * hash + arg3.GetHashCode();
|
||||
return 31 * hash + arg4.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(T[] list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (item == null) continue;
|
||||
hash = 31 * hash + item.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(IEnumerable<T> list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (item == null) continue;
|
||||
hash = 31 * hash + item.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a hashcode for a collection for that the order of items
|
||||
/// does not matter.
|
||||
/// So {1, 2, 3} and {3, 2, 1} will get same hash code.
|
||||
/// </summary>
|
||||
public static int GetHashCodeForOrderNoMatterCollection<T>(
|
||||
IEnumerable<T> list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
int count = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (item == null) continue;
|
||||
hash += item.GetHashCode();
|
||||
count++;
|
||||
}
|
||||
return 31 * hash + count.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alternative way to get a hashcode is to use a fluent
|
||||
/// interface like this:<br />
|
||||
/// return 0.CombineHashCode(field1).CombineHashCode(field2).
|
||||
/// CombineHashCode(field3);
|
||||
/// </summary>
|
||||
public static int CombineHashCode<T>(this int hashCode, T arg)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return 31 * hashCode + arg.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,9 +52,20 @@ namespace Umbraco.Core.IO
|
||||
try
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
dir = dir.Substring(0, dir.Length - _shadowPath.Length - 1);
|
||||
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
|
||||
Directory.Delete(dir, true);
|
||||
|
||||
// shadowPath make be path/to/dir, remove each
|
||||
dir = dir.Replace("/", "\\");
|
||||
var min = IOHelper.MapPath("~/App_Data/TEMP/ShadowFs").Length;
|
||||
var pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase);
|
||||
while (pos > min)
|
||||
{
|
||||
dir = dir.Substring(0, pos);
|
||||
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
|
||||
Directory.Delete(dir, true);
|
||||
else
|
||||
break;
|
||||
pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Umbraco.Core.Models
|
||||
public Guid Key { get; set; }
|
||||
public DateTime CreateDate { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public DateTime? DeletedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Special case, always return false, this will cause the repositories managing
|
||||
@@ -60,5 +61,7 @@ namespace Umbraco.Core.Models
|
||||
DeepCloneHelper.DeepCloneRefProperties(this, clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -101,6 +101,9 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _updateDate, Ps.Value.UpdateDateSelector); }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public DateTime? DeletedDate { get; set; }
|
||||
|
||||
internal virtual void ResetIdentity()
|
||||
{
|
||||
_hasIdentity = false;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// Marker interface for aggregate roots
|
||||
/// </summary>
|
||||
public interface IAggregateRoot : IEntity
|
||||
public interface IAggregateRoot : IDeletableEntity
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Models.EntityBase
|
||||
{
|
||||
public interface IDeletableEntity : IEntity
|
||||
{
|
||||
[DataMember]
|
||||
DateTime? DeletedDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
/// <summary>
|
||||
/// Guid based Id
|
||||
/// </summary>
|
||||
/// <remarks>The key is currectly used to store the Unique Id from the
|
||||
/// <remarks>The key is currectly used to store the Unique Id from the
|
||||
/// umbracoNode table, which many of the entities are based on.</remarks>
|
||||
[DataMember]
|
||||
Guid Key { get; set; }
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
private readonly bool _keepOldest;
|
||||
|
||||
public OrderedHashSet(bool keepOldest = true)
|
||||
public OrderedHashSet(bool keepOldest = true)
|
||||
{
|
||||
_keepOldest = keepOldest;
|
||||
}
|
||||
|
||||
+4
-2
@@ -30,8 +30,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
var version = database.FirstOrDefault<string>("SELECT version FROM umbracoMigration WHERE name=@name ORDER BY version DESC", new { name = Constants.System.UmbracoMigrationName });
|
||||
if (version != null && version.StartsWith("7.6.0")) return string.Empty;
|
||||
|
||||
var updates = database.Query<dynamic>("SELECT id, text FROM umbracoNode WHERE nodeObjectType = @guid", new { guid = Constants.ObjectTypes.TemplateTypeGuid})
|
||||
.Select(template => Tuple.Create((int) template.id, ("template____" + (string) template.text).ToGuid()))
|
||||
var updates = database.Query<dynamic>(@"SELECT umbracoNode.id, cmsTemplate.alias FROM umbracoNode
|
||||
JOIN cmsTemplate ON umbracoNode.id=cmsTemplate.nodeId
|
||||
WHERE nodeObjectType = @guid", new { guid = Constants.ObjectTypes.TemplateTypeGuid})
|
||||
.Select(template => Tuple.Create((int) template.id, ("template____" + (string) template.alias).ToGuid()))
|
||||
.ToList();
|
||||
|
||||
foreach (var update in updates)
|
||||
|
||||
@@ -70,6 +70,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
//Remove 'published' xml from the cmsContentXml table for the unpublished content
|
||||
Database.Delete<ContentXmlDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
entity.DeletedDate = DateTime.Now;
|
||||
}
|
||||
|
||||
protected override void PersistNewItem(ContentXmlEntity<TContent> entity)
|
||||
|
||||
@@ -270,6 +270,8 @@ AND umbracoNode.id <> @id",
|
||||
|
||||
//Delete (base) node data
|
||||
Database.Delete<NodeDto>("WHERE uniqueID = @Id", new { Id = entity.Key });
|
||||
|
||||
entity.DeletedDate = DateTime.Now;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -539,6 +541,8 @@ AND umbracoNode.id <> @id",
|
||||
Database.Execute(
|
||||
"DELETE FROM cmsDataTypePreValues WHERE id=@Id",
|
||||
new { Id = entity.Id });
|
||||
|
||||
entity.DeletedDate = DateTime.Now;
|
||||
}
|
||||
|
||||
protected override void PersistNewItem(PreValueEntity entity)
|
||||
|
||||
@@ -195,6 +195,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//Clear the cache entries that exist by uniqueid/item key
|
||||
IsolatedCache.ClearCacheItem(GetCacheIdKey<IDictionaryItem>(entity.ItemKey));
|
||||
IsolatedCache.ClearCacheItem(GetCacheIdKey<IDictionaryItem>(entity.Key));
|
||||
|
||||
entity.DeletedDate = DateTime.Now;
|
||||
}
|
||||
|
||||
private void RecursiveDelete(Guid parentId)
|
||||
|
||||
@@ -167,6 +167,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
// delete
|
||||
Database.Delete(nodeDto);
|
||||
|
||||
entity.DeletedDate = DateTime.Now;
|
||||
}
|
||||
|
||||
protected override void PersistNewItem(EntityContainer entity)
|
||||
|
||||
@@ -74,6 +74,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
Database.Execute(delete, new { Id = GetEntityId(entity) });
|
||||
}
|
||||
entity.DeletedDate = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,6 +311,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var masterpageName = string.Concat(entity.Alias, ".master");
|
||||
_masterpagesFileSystem.DeleteFile(masterpageName);
|
||||
}
|
||||
|
||||
entity.DeletedDate = DateTime.Now;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -8,5 +8,6 @@ namespace Umbraco.Core.Persistence.UnitOfWork
|
||||
IScope Scope { get; }
|
||||
EventMessages Messages { get; }
|
||||
IEventDispatcher Events { get; }
|
||||
void Flush();
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,33 @@ namespace Umbraco.Core.Persistence.UnitOfWork
|
||||
_key = Guid.NewGuid();
|
||||
}
|
||||
|
||||
public object Key
|
||||
public void Flush()
|
||||
{
|
||||
if (_readOnly)
|
||||
throw new NotSupportedException("This unit of work is read-only.");
|
||||
|
||||
while (_operations.Count > 0)
|
||||
{
|
||||
var operation = _operations.Dequeue();
|
||||
switch (operation.Type)
|
||||
{
|
||||
case TransactionType.Insert:
|
||||
operation.Repository.PersistNewItem(operation.Entity);
|
||||
break;
|
||||
case TransactionType.Delete:
|
||||
operation.Repository.PersistDeletedItem(operation.Entity);
|
||||
break;
|
||||
case TransactionType.Update:
|
||||
operation.Repository.PersistUpdatedItem(operation.Entity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_operations.Clear();
|
||||
_key = Guid.NewGuid();
|
||||
}
|
||||
|
||||
public object Key
|
||||
{
|
||||
get { return _key; }
|
||||
}
|
||||
|
||||
@@ -465,6 +465,7 @@ namespace Umbraco.Core.Scoping
|
||||
}
|
||||
finally
|
||||
{
|
||||
// removes the ambient context (ambient scope already gone)
|
||||
_scopeProvider.SetAmbient(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Scoping
|
||||
{
|
||||
public class ScopeContext : IInstanceIdentifiable
|
||||
{
|
||||
private Dictionary<string, IEnlistedObject> _enlisted;
|
||||
private bool _exiting;
|
||||
|
||||
public void ScopeExit(bool completed)
|
||||
{
|
||||
if (_enlisted == null)
|
||||
return;
|
||||
|
||||
_exiting = true;
|
||||
|
||||
List<Exception> exceptions = null;
|
||||
foreach (var enlisted in Enlisted.Values)
|
||||
foreach (var enlisted in _enlisted.Values.OrderBy(x => x.Priority))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -23,6 +30,7 @@ namespace Umbraco.Core.Scoping
|
||||
exceptions.Add(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (exceptions != null)
|
||||
throw new AggregateException("Exceptions were thrown by listed actions.", exceptions);
|
||||
}
|
||||
@@ -42,73 +50,71 @@ namespace Umbraco.Core.Scoping
|
||||
private interface IEnlistedObject
|
||||
{
|
||||
void Execute(bool completed);
|
||||
int Priority { get; }
|
||||
}
|
||||
|
||||
private class EnlistedObject<T> : IEnlistedObject
|
||||
{
|
||||
private readonly Action<bool, T> _action;
|
||||
|
||||
public EnlistedObject(T item)
|
||||
{
|
||||
Item = item;
|
||||
}
|
||||
|
||||
public EnlistedObject(T item, Action<bool, T> action)
|
||||
public EnlistedObject(T item, Action<bool, T> action, int priority)
|
||||
{
|
||||
Item = item;
|
||||
Priority = priority;
|
||||
_action = action;
|
||||
}
|
||||
|
||||
public T Item { get; private set; }
|
||||
|
||||
public int Priority { get; private set; }
|
||||
|
||||
public void Execute(bool completed)
|
||||
{
|
||||
_action(completed, Item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
// todo: replace with optional parameters when we can break things
|
||||
public T Enlist<T>(string key, Func<T> creator)
|
||||
{
|
||||
IEnlistedObject enlisted;
|
||||
if (Enlisted.TryGetValue(key, out enlisted))
|
||||
{
|
||||
var enlistedAs = enlisted as EnlistedObject<T>;
|
||||
if (enlistedAs == null) throw new Exception("An item with a different type has already been enlisted with the same key.");
|
||||
return enlistedAs.Item;
|
||||
}
|
||||
var enlistedOfT = new EnlistedObject<T>(creator());
|
||||
Enlisted[key] = enlistedOfT;
|
||||
return enlistedOfT.Item;
|
||||
return Enlist(key, creator, null, 100);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
// todo: replace with optional parameters when we can break things
|
||||
public T Enlist<T>(string key, Func<T> creator, Action<bool, T> action)
|
||||
{
|
||||
IEnlistedObject enlisted;
|
||||
if (Enlisted.TryGetValue(key, out enlisted))
|
||||
{
|
||||
var enlistedAs = enlisted as EnlistedObject<T>;
|
||||
if (enlistedAs == null) throw new Exception("An item with a different type has already been enlisted with the same key.");
|
||||
return enlistedAs.Item;
|
||||
}
|
||||
var enlistedOfT = new EnlistedObject<T>(creator(), action);
|
||||
Enlisted[key] = enlistedOfT;
|
||||
return enlistedOfT.Item;
|
||||
return Enlist(key, creator, action, 100);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
// todo: replace with optional parameters when we can break things
|
||||
public void Enlist(string key, Action<bool> action)
|
||||
{
|
||||
Enlist<object>(key, null, (completed, item) => action(completed), 100);
|
||||
}
|
||||
|
||||
public void Enlist(string key, Action<bool> action, int priority)
|
||||
{
|
||||
Enlist<object>(key, null, (completed, item) => action(completed), priority);
|
||||
}
|
||||
|
||||
public T Enlist<T>(string key, Func<T> creator, Action<bool, T> action, int priority)
|
||||
{
|
||||
if (_exiting)
|
||||
throw new InvalidOperationException("Cannot enlist now, context is exiting.");
|
||||
|
||||
var enlistedObjects = _enlisted ?? (_enlisted = new Dictionary<string, IEnlistedObject>());
|
||||
|
||||
IEnlistedObject enlisted;
|
||||
if (Enlisted.TryGetValue(key, out enlisted))
|
||||
if (enlistedObjects.TryGetValue(key, out enlisted))
|
||||
{
|
||||
var enlistedAs = enlisted as EnlistedObject<object>;
|
||||
if (enlistedAs == null) throw new Exception("An item with a different type has already been enlisted with the same key.");
|
||||
return;
|
||||
var enlistedAs = enlisted as EnlistedObject<T>;
|
||||
if (enlistedAs == null) throw new InvalidOperationException("An item with the key already exists, but with a different type.");
|
||||
if (enlistedAs.Priority != priority) throw new InvalidOperationException("An item with the key already exits, but with a different priority.");
|
||||
return enlistedAs.Item;
|
||||
}
|
||||
var enlistedOfT = new EnlistedObject<object>(null, (completed, item) => action(completed));
|
||||
var enlistedOfT = new EnlistedObject<T>(creator == null ? default(T) : creator(), action, priority);
|
||||
Enlisted[key] = enlistedOfT;
|
||||
return enlistedOfT.Item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,6 +191,7 @@ namespace Umbraco.Core.Security
|
||||
|
||||
//track the last login date
|
||||
user.LastLoginDateUtc = DateTime.UtcNow;
|
||||
user.AccessFailedCount = 0;
|
||||
await UserManager.UpdateAsync(user);
|
||||
|
||||
_logger.WriteCore(TraceEventType.Information, 0,
|
||||
@@ -231,4 +232,4 @@ namespace Umbraco.Core.Security
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,35 +124,11 @@ namespace Umbraco.Core.Services
|
||||
|
||||
private static Guid GetNodeObjectTypeGuid(UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
switch (umbracoObjectType)
|
||||
{
|
||||
case UmbracoObjectTypes.Document:
|
||||
return Constants.ObjectTypes.DocumentGuid;
|
||||
case UmbracoObjectTypes.MemberType:
|
||||
return Constants.ObjectTypes.MemberTypeGuid;
|
||||
case UmbracoObjectTypes.Media:
|
||||
return Constants.ObjectTypes.MediaGuid;
|
||||
case UmbracoObjectTypes.Template:
|
||||
return Constants.ObjectTypes.TemplateTypeGuid;
|
||||
case UmbracoObjectTypes.MediaType:
|
||||
return Constants.ObjectTypes.MediaTypeGuid;
|
||||
case UmbracoObjectTypes.DocumentType:
|
||||
return Constants.ObjectTypes.DocumentTypeGuid;
|
||||
case UmbracoObjectTypes.Member:
|
||||
return Constants.ObjectTypes.MemberGuid;
|
||||
case UmbracoObjectTypes.DataType:
|
||||
return Constants.ObjectTypes.DataTypeGuid;
|
||||
case UmbracoObjectTypes.MemberGroup:
|
||||
return Constants.ObjectTypes.MemberGroupGuid;
|
||||
case UmbracoObjectTypes.RecycleBin:
|
||||
case UmbracoObjectTypes.Stylesheet:
|
||||
case UmbracoObjectTypes.ContentItem:
|
||||
case UmbracoObjectTypes.ContentItemType:
|
||||
case UmbracoObjectTypes.ROOT:
|
||||
case UmbracoObjectTypes.Unknown:
|
||||
default:
|
||||
throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ").");
|
||||
}
|
||||
var guid = umbracoObjectType.GetGuid();
|
||||
if (guid == Guid.Empty)
|
||||
throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ").");
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
||||
public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
@@ -6,6 +7,15 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
public interface IPackagingService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="umbracoVersion"></param>
|
||||
/// <param name="userId">The current user id performing the operation</param>
|
||||
/// <returns></returns>
|
||||
string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Imports and saves package xml as <see cref="IContent"/>
|
||||
/// </summary>
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Auditing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -75,6 +80,61 @@ namespace Umbraco.Core.Services
|
||||
_importedContentTypes = new Dictionary<string, IContentType>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="umbracoVersion"></param>
|
||||
/// /// <param name="userId">The current user id performing the operation</param>
|
||||
/// <returns></returns>
|
||||
public string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId)
|
||||
{
|
||||
var packageRepo = UmbracoConfig.For.UmbracoSettings().PackageRepositories.GetDefault();
|
||||
|
||||
using (var httpClient = new HttpClient())
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
//includeHidden = true because we don't care if it's hidden we want to get the file regardless
|
||||
var url = string.Format("{0}/{1}?version={2}&includeHidden=true&asFile=true", packageRepo.RestApiUrl, packageId, umbracoVersion.ToString(3));
|
||||
byte[] bytes;
|
||||
try
|
||||
{
|
||||
bytes = httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new ConnectionException("An error occuring downloading the package from " + url, ex);
|
||||
}
|
||||
|
||||
//successfull
|
||||
if (bytes.Length > 0)
|
||||
{
|
||||
var packagePath = IOHelper.MapPath(SystemDirectories.Packages);
|
||||
|
||||
// Check for package directory
|
||||
if (Directory.Exists(packagePath) == false)
|
||||
Directory.CreateDirectory(packagePath);
|
||||
|
||||
var packageFilePath = Path.Combine(packagePath, packageId + ".umb");
|
||||
|
||||
using (var fs1 = new FileStream(packageFilePath, FileMode.Create))
|
||||
{
|
||||
fs1.Write(bytes, 0, bytes.Length);
|
||||
return "packages\\" + packageId + ".umb";
|
||||
}
|
||||
}
|
||||
|
||||
Audit(uow, AuditType.PackagerInstall, string.Format("Package {0} fetched from {1}", packageId, packageRepo.Id), userId, -1);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId)
|
||||
{
|
||||
var auditRepo = _repositoryFactory.CreateAuditRepository(uow);
|
||||
auditRepo.AddOrUpdate(new AuditItem(objectId, message, type, userId));
|
||||
}
|
||||
|
||||
#region Content
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -166,8 +166,8 @@ namespace Umbraco.Core
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is of generic type] [the specified type].
|
||||
/// </summary>
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
@@ -15,11 +16,51 @@ namespace Umbraco.Core
|
||||
{
|
||||
private static readonly ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]> GetPropertiesCache
|
||||
= new ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]>();
|
||||
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache
|
||||
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache
|
||||
= new ConcurrentDictionary<Type, FieldInfo[]>();
|
||||
|
||||
private static readonly Assembly[] EmptyAssemblies = new Assembly[0];
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Based on a type we'll check if it is IEnumerable{T} (or similar) and if so we'll return a List{T}, this will also deal with array types and return List{T} for those too.
|
||||
/// If it cannot be done, null is returned.
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
internal static IList CreateGenericEnumerableFromObject(object obj)
|
||||
{
|
||||
var type = obj.GetType();
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var genericTypeDef = type.GetGenericTypeDefinition();
|
||||
|
||||
if (genericTypeDef == typeof(IEnumerable<>)
|
||||
|| genericTypeDef == typeof(ICollection<>)
|
||||
|| genericTypeDef == typeof(Collection<>)
|
||||
|| genericTypeDef == typeof(IList<>)
|
||||
|| genericTypeDef == typeof(List<>)
|
||||
//this will occur when Linq is used and we get the odd WhereIterator or DistinctIterators since those are special iterator types
|
||||
|| obj is IEnumerable)
|
||||
{
|
||||
//if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<>
|
||||
var genericType = typeof(List<>).MakeGenericType(type.GetGenericArguments());
|
||||
//pass in obj to fill the list
|
||||
return (IList)Activator.CreateInstance(genericType, obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (type.IsArray)
|
||||
{
|
||||
//if its an array, we'll use a List<>
|
||||
var genericType = typeof(List<>).MakeGenericType(type.GetElementType());
|
||||
//pass in obj to fill the list
|
||||
return (IList)Activator.CreateInstance(genericType, obj);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the method is actually overriding a base method
|
||||
/// </summary>
|
||||
@@ -45,8 +86,8 @@ namespace Umbraco.Core
|
||||
if (assembly.IsAppCodeAssembly() || assembly.IsGlobalAsaxAssembly())
|
||||
return EmptyAssemblies;
|
||||
|
||||
|
||||
// find all assembly references that are referencing the current type's assembly since we
|
||||
|
||||
// find all assembly references that are referencing the current type's assembly since we
|
||||
// should only be scanning those assemblies because any other assembly will definitely not
|
||||
// contain sub type's of the one we're currently looking for
|
||||
var name = assembly.GetName().Name;
|
||||
|
||||
@@ -100,9 +100,8 @@
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Semver, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Semver.2.0.4\lib\netstandard1.1\Semver.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="Semver, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\semver.1.1.2\lib\net45\Semver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
@@ -292,6 +291,7 @@
|
||||
<Compile Include="Configuration\UmbracoSettings\RazorStaticMappingElement.cs" />
|
||||
<Compile Include="Configuration\UmbracoSettings\RepositoriesCollection.cs" />
|
||||
<Compile Include="Configuration\UmbracoSettings\RepositoriesElement.cs" />
|
||||
<Compile Include="Configuration\UmbracoSettings\RepositoryConfigExtensions.cs" />
|
||||
<Compile Include="Configuration\UmbracoSettings\RepositoryElement.cs" />
|
||||
<Compile Include="Configuration\UmbracoSettings\RequestHandlerElement.cs" />
|
||||
<Compile Include="Configuration\UmbracoSettings\ScheduledTaskElement.cs" />
|
||||
@@ -338,7 +338,11 @@
|
||||
<Compile Include="Events\IDeletingMediaFilesEventArgs.cs" />
|
||||
<Compile Include="Events\ScopeEventDispatcherBase.cs" />
|
||||
<Compile Include="Events\ScopeLifespanMessagesFactory.cs" />
|
||||
<Compile Include="Events\SupersedeEventAttribute.cs" />
|
||||
<Compile Include="Exceptions\ConnectionException.cs" />
|
||||
<Compile Include="HashCodeHelper.cs" />
|
||||
<Compile Include="IHttpContextAccessor.cs" />
|
||||
<Compile Include="Models\EntityBase\IDeletableEntity.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentTypeConverter.cs" />
|
||||
<Compile Include="OrderedHashSet.cs" />
|
||||
<Compile Include="Events\UninstallPackageEventArgs.cs" />
|
||||
|
||||
@@ -15,11 +15,7 @@
|
||||
<package id="MySql.Data" version="6.9.9" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="Semver" version="2.0.4" targetFramework="net45" />
|
||||
<package id="semver" version="1.1.2" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.3.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net45" />
|
||||
<package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -7,6 +7,7 @@ using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web.Cache;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Tests.Cache
|
||||
{
|
||||
@@ -31,70 +32,70 @@ namespace Umbraco.Tests.Cache
|
||||
new EventDefinition<ISectionService, EventArgs>(null, ServiceContext.SectionService, new EventArgs(), "Deleted"),
|
||||
new EventDefinition<ISectionService, EventArgs>(null, ServiceContext.SectionService, new EventArgs(), "New"),
|
||||
|
||||
new EventDefinition<IUserService, SaveEventArgs<IUserType>>(null, ServiceContext.UserService, new SaveEventArgs<IUserType>((IUserType) null)),
|
||||
new EventDefinition<IUserService, DeleteEventArgs<IUserType>>(null, ServiceContext.UserService, new DeleteEventArgs<IUserType>((IUserType) null)),
|
||||
new EventDefinition<IUserService, SaveEventArgs<IUserType>>(null, ServiceContext.UserService, new SaveEventArgs<IUserType>(Enumerable.Empty<IUserType>())),
|
||||
new EventDefinition<IUserService, DeleteEventArgs<IUserType>>(null, ServiceContext.UserService, new DeleteEventArgs<IUserType>(Enumerable.Empty<IUserType>())),
|
||||
|
||||
new EventDefinition<IUserService, SaveEventArgs<IUser>>(null, ServiceContext.UserService, new SaveEventArgs<IUser>((IUser) null)),
|
||||
new EventDefinition<IUserService, DeleteEventArgs<IUser>>(null, ServiceContext.UserService, new DeleteEventArgs<IUser>((IUser) null)),
|
||||
new EventDefinition<IUserService, DeleteEventArgs<IUser>>(null, ServiceContext.UserService, new DeleteEventArgs<IUser>((IUser) null)),
|
||||
new EventDefinition<IUserService, SaveEventArgs<IUser>>(null, ServiceContext.UserService, new SaveEventArgs<IUser>(Enumerable.Empty<IUser>())),
|
||||
new EventDefinition<IUserService, DeleteEventArgs<IUser>>(null, ServiceContext.UserService, new DeleteEventArgs<IUser>(Enumerable.Empty<IUser>())),
|
||||
new EventDefinition<IUserService, DeleteEventArgs<IUser>>(null, ServiceContext.UserService, new DeleteEventArgs<IUser>(Enumerable.Empty<IUser>())),
|
||||
|
||||
new EventDefinition<ILocalizationService, SaveEventArgs<IDictionaryItem>>(null, ServiceContext.LocalizationService, new SaveEventArgs<IDictionaryItem>((IDictionaryItem) null)),
|
||||
new EventDefinition<ILocalizationService, DeleteEventArgs<IDictionaryItem>>(null, ServiceContext.LocalizationService, new DeleteEventArgs<IDictionaryItem>((IDictionaryItem) null)),
|
||||
new EventDefinition<ILocalizationService, SaveEventArgs<IDictionaryItem>>(null, ServiceContext.LocalizationService, new SaveEventArgs<IDictionaryItem>(Enumerable.Empty<IDictionaryItem>())),
|
||||
new EventDefinition<ILocalizationService, DeleteEventArgs<IDictionaryItem>>(null, ServiceContext.LocalizationService, new DeleteEventArgs<IDictionaryItem>(Enumerable.Empty<IDictionaryItem>())),
|
||||
|
||||
new EventDefinition<IDataTypeService, SaveEventArgs<IDataTypeDefinition>>(null, ServiceContext.DataTypeService, new SaveEventArgs<IDataTypeDefinition>((IDataTypeDefinition) null)),
|
||||
new EventDefinition<IDataTypeService, DeleteEventArgs<IDataTypeDefinition>>(null, ServiceContext.DataTypeService, new DeleteEventArgs<IDataTypeDefinition>((IDataTypeDefinition) null)),
|
||||
new EventDefinition<IDataTypeService, SaveEventArgs<IDataTypeDefinition>>(null, ServiceContext.DataTypeService, new SaveEventArgs<IDataTypeDefinition>(Enumerable.Empty<IDataTypeDefinition>())),
|
||||
new EventDefinition<IDataTypeService, DeleteEventArgs<IDataTypeDefinition>>(null, ServiceContext.DataTypeService, new DeleteEventArgs<IDataTypeDefinition>(Enumerable.Empty<IDataTypeDefinition>())),
|
||||
|
||||
new EventDefinition<IFileService, SaveEventArgs<Stylesheet>>(null, ServiceContext.FileService, new SaveEventArgs<Stylesheet>((Stylesheet) null)),
|
||||
new EventDefinition<IFileService, DeleteEventArgs<Stylesheet>>(null, ServiceContext.FileService, new DeleteEventArgs<Stylesheet>((Stylesheet) null)),
|
||||
new EventDefinition<IFileService, SaveEventArgs<Stylesheet>>(null, ServiceContext.FileService, new SaveEventArgs<Stylesheet>(Enumerable.Empty<Stylesheet>())),
|
||||
new EventDefinition<IFileService, DeleteEventArgs<Stylesheet>>(null, ServiceContext.FileService, new DeleteEventArgs<Stylesheet>(Enumerable.Empty<Stylesheet>())),
|
||||
|
||||
new EventDefinition<IDomainService, SaveEventArgs<IDomain>>(null, ServiceContext.DomainService, new SaveEventArgs<IDomain>((IDomain) null)),
|
||||
new EventDefinition<IDomainService, DeleteEventArgs<IDomain>>(null, ServiceContext.DomainService, new DeleteEventArgs<IDomain>((IDomain) null)),
|
||||
new EventDefinition<IDomainService, SaveEventArgs<IDomain>>(null, ServiceContext.DomainService, new SaveEventArgs<IDomain>(Enumerable.Empty<IDomain>())),
|
||||
new EventDefinition<IDomainService, DeleteEventArgs<IDomain>>(null, ServiceContext.DomainService, new DeleteEventArgs<IDomain>(Enumerable.Empty<IDomain>())),
|
||||
|
||||
new EventDefinition<ILocalizationService, SaveEventArgs<ILanguage>>(null, ServiceContext.LocalizationService, new SaveEventArgs<ILanguage>((ILanguage) null)),
|
||||
new EventDefinition<ILocalizationService, DeleteEventArgs<ILanguage>>(null, ServiceContext.LocalizationService, new DeleteEventArgs<ILanguage>((ILanguage) null)),
|
||||
new EventDefinition<ILocalizationService, SaveEventArgs<ILanguage>>(null, ServiceContext.LocalizationService, new SaveEventArgs<ILanguage>(Enumerable.Empty<ILanguage>())),
|
||||
new EventDefinition<ILocalizationService, DeleteEventArgs<ILanguage>>(null, ServiceContext.LocalizationService, new DeleteEventArgs<ILanguage>(Enumerable.Empty<ILanguage>())),
|
||||
|
||||
new EventDefinition<IContentTypeService, SaveEventArgs<IContentType>>(null, ServiceContext.ContentTypeService, new SaveEventArgs<IContentType>((IContentType) null)),
|
||||
new EventDefinition<IContentTypeService, DeleteEventArgs<IContentType>>(null, ServiceContext.ContentTypeService, new DeleteEventArgs<IContentType>((IContentType) null)),
|
||||
new EventDefinition<IContentTypeService, SaveEventArgs<IMediaType>>(null, ServiceContext.ContentTypeService, new SaveEventArgs<IMediaType>((IMediaType) null)),
|
||||
new EventDefinition<IContentTypeService, DeleteEventArgs<IMediaType>>(null, ServiceContext.ContentTypeService, new DeleteEventArgs<IMediaType>((IMediaType) null)),
|
||||
new EventDefinition<IContentTypeService, SaveEventArgs<IContentType>>(null, ServiceContext.ContentTypeService, new SaveEventArgs<IContentType>(Enumerable.Empty<IContentType>())),
|
||||
new EventDefinition<IContentTypeService, DeleteEventArgs<IContentType>>(null, ServiceContext.ContentTypeService, new DeleteEventArgs<IContentType>(Enumerable.Empty<IContentType>())),
|
||||
new EventDefinition<IContentTypeService, SaveEventArgs<IMediaType>>(null, ServiceContext.ContentTypeService, new SaveEventArgs<IMediaType>(Enumerable.Empty<IMediaType>())),
|
||||
new EventDefinition<IContentTypeService, DeleteEventArgs<IMediaType>>(null, ServiceContext.ContentTypeService, new DeleteEventArgs<IMediaType>(Enumerable.Empty<IMediaType>())),
|
||||
|
||||
new EventDefinition<IMemberTypeService, SaveEventArgs<IMemberType>>(null, ServiceContext.MemberTypeService, new SaveEventArgs<IMemberType>((IMemberType) null)),
|
||||
new EventDefinition<IMemberTypeService, DeleteEventArgs<IMemberType>>(null, ServiceContext.MemberTypeService, new DeleteEventArgs<IMemberType>((IMemberType) null)),
|
||||
new EventDefinition<IMemberTypeService, SaveEventArgs<IMemberType>>(null, ServiceContext.MemberTypeService, new SaveEventArgs<IMemberType>(Enumerable.Empty<IMemberType>())),
|
||||
new EventDefinition<IMemberTypeService, DeleteEventArgs<IMemberType>>(null, ServiceContext.MemberTypeService, new DeleteEventArgs<IMemberType>(Enumerable.Empty<IMemberType>())),
|
||||
|
||||
new EventDefinition<IFileService, SaveEventArgs<ITemplate>>(null, ServiceContext.FileService, new SaveEventArgs<ITemplate>((ITemplate) null)),
|
||||
new EventDefinition<IFileService, DeleteEventArgs<ITemplate>>(null, ServiceContext.FileService, new DeleteEventArgs<ITemplate>((ITemplate) null)),
|
||||
new EventDefinition<IFileService, SaveEventArgs<ITemplate>>(null, ServiceContext.FileService, new SaveEventArgs<ITemplate>(Enumerable.Empty<ITemplate>())),
|
||||
new EventDefinition<IFileService, DeleteEventArgs<ITemplate>>(null, ServiceContext.FileService, new DeleteEventArgs<ITemplate>(Enumerable.Empty<ITemplate>())),
|
||||
|
||||
new EventDefinition<IMacroService, SaveEventArgs<IMacro>>(null, ServiceContext.MacroService, new SaveEventArgs<IMacro>((IMacro) null)),
|
||||
new EventDefinition<IMacroService, DeleteEventArgs<IMacro>>(null, ServiceContext.MacroService, new DeleteEventArgs<IMacro>((IMacro) null)),
|
||||
new EventDefinition<IMacroService, SaveEventArgs<IMacro>>(null, ServiceContext.MacroService, new SaveEventArgs<IMacro>(Enumerable.Empty<IMacro>())),
|
||||
new EventDefinition<IMacroService, DeleteEventArgs<IMacro>>(null, ServiceContext.MacroService, new DeleteEventArgs<IMacro>(Enumerable.Empty<IMacro>())),
|
||||
|
||||
new EventDefinition<IMemberService, SaveEventArgs<IMember>>(null, ServiceContext.MemberService, new SaveEventArgs<IMember>((IMember) null)),
|
||||
new EventDefinition<IMemberService, DeleteEventArgs<IMember>>(null, ServiceContext.MemberService, new DeleteEventArgs<IMember>((IMember) null)),
|
||||
new EventDefinition<IMemberService, SaveEventArgs<IMember>>(null, ServiceContext.MemberService, new SaveEventArgs<IMember>(Enumerable.Empty<IMember>())),
|
||||
new EventDefinition<IMemberService, DeleteEventArgs<IMember>>(null, ServiceContext.MemberService, new DeleteEventArgs<IMember>(Enumerable.Empty<IMember>())),
|
||||
|
||||
new EventDefinition<IMemberGroupService, SaveEventArgs<IMemberGroup>>(null, ServiceContext.MemberGroupService, new SaveEventArgs<IMemberGroup>((IMemberGroup) null)),
|
||||
new EventDefinition<IMemberGroupService, DeleteEventArgs<IMemberGroup>>(null, ServiceContext.MemberGroupService, new DeleteEventArgs<IMemberGroup>((IMemberGroup) null)),
|
||||
new EventDefinition<IMemberGroupService, SaveEventArgs<IMemberGroup>>(null, ServiceContext.MemberGroupService, new SaveEventArgs<IMemberGroup>(Enumerable.Empty<IMemberGroup>())),
|
||||
new EventDefinition<IMemberGroupService, DeleteEventArgs<IMemberGroup>>(null, ServiceContext.MemberGroupService, new DeleteEventArgs<IMemberGroup>(Enumerable.Empty<IMemberGroup>())),
|
||||
|
||||
new EventDefinition<IMediaService, SaveEventArgs<IMedia>>(null, ServiceContext.MediaService, new SaveEventArgs<IMedia>((IMedia) null)),
|
||||
new EventDefinition<IMediaService, DeleteEventArgs<IMedia>>(null, ServiceContext.MediaService, new DeleteEventArgs<IMedia>((IMedia) null)),
|
||||
new EventDefinition<IMediaService, SaveEventArgs<IMedia>>(null, ServiceContext.MediaService, new SaveEventArgs<IMedia>(Enumerable.Empty<IMedia>())),
|
||||
new EventDefinition<IMediaService, DeleteEventArgs<IMedia>>(null, ServiceContext.MediaService, new DeleteEventArgs<IMedia>(Enumerable.Empty<IMedia>())),
|
||||
new EventDefinition<IMediaService, MoveEventArgs<IMedia>>(null, ServiceContext.MediaService, new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(null, "", -1)), "Moved"),
|
||||
new EventDefinition<IMediaService, MoveEventArgs<IMedia>>(null, ServiceContext.MediaService, new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(null, "", -1)), "Trashed"),
|
||||
new EventDefinition<IMediaService, RecycleBinEventArgs>(null, ServiceContext.MediaService, new RecycleBinEventArgs(Guid.NewGuid(), new Dictionary<int, IEnumerable<Property>>(), true)),
|
||||
|
||||
new EventDefinition<IContentService, SaveEventArgs<IContent>>(null, ServiceContext.ContentService, new SaveEventArgs<IContent>((IContent) null)),
|
||||
new EventDefinition<IContentService, DeleteEventArgs<IContent>>(null, ServiceContext.ContentService, new DeleteEventArgs<IContent>((IContent) null)),
|
||||
new EventDefinition<IContentService, SaveEventArgs<IContent>>(null, ServiceContext.ContentService, new SaveEventArgs<IContent>(Enumerable.Empty<IContent>())),
|
||||
new EventDefinition<IContentService, DeleteEventArgs<IContent>>(null, ServiceContext.ContentService, new DeleteEventArgs<IContent>(Enumerable.Empty<IContent>())),
|
||||
new EventDefinition<IContentService, CopyEventArgs<IContent>>(null, ServiceContext.ContentService, new CopyEventArgs<IContent>(null, null, -1)),
|
||||
new EventDefinition<IContentService, MoveEventArgs<IContent>>(null, ServiceContext.ContentService, new MoveEventArgs<IContent>(new MoveEventInfo<IContent>(null, "", -1)), "Trashed"),
|
||||
new EventDefinition<IContentService, RecycleBinEventArgs>(null, ServiceContext.ContentService, new RecycleBinEventArgs(Guid.NewGuid(), new Dictionary<int, IEnumerable<Property>>(), true)),
|
||||
new EventDefinition<IContentService, PublishEventArgs<IContent>>(null, ServiceContext.ContentService, new PublishEventArgs<IContent>((IContent) null), "Published"),
|
||||
new EventDefinition<IContentService, PublishEventArgs<IContent>>(null, ServiceContext.ContentService, new PublishEventArgs<IContent>((IContent) null), "UnPublished"),
|
||||
new EventDefinition<IContentService, PublishEventArgs<IContent>>(null, ServiceContext.ContentService, new PublishEventArgs<IContent>(Enumerable.Empty<IContent>()), "Published"),
|
||||
new EventDefinition<IContentService, PublishEventArgs<IContent>>(null, ServiceContext.ContentService, new PublishEventArgs<IContent>(Enumerable.Empty<IContent>()), "UnPublished"),
|
||||
|
||||
new EventDefinition<IPublicAccessService, SaveEventArgs<PublicAccessEntry>>(null, ServiceContext.PublicAccessService, new SaveEventArgs<PublicAccessEntry>((PublicAccessEntry) null)),
|
||||
new EventDefinition<IPublicAccessService, DeleteEventArgs<PublicAccessEntry>>(null, ServiceContext.PublicAccessService, new DeleteEventArgs<PublicAccessEntry>((PublicAccessEntry) null)),
|
||||
new EventDefinition<IPublicAccessService, SaveEventArgs<PublicAccessEntry>>(null, ServiceContext.PublicAccessService, new SaveEventArgs<PublicAccessEntry>(Enumerable.Empty<PublicAccessEntry>())),
|
||||
new EventDefinition<IPublicAccessService, DeleteEventArgs<PublicAccessEntry>>(null, ServiceContext.PublicAccessService, new DeleteEventArgs<PublicAccessEntry>(Enumerable.Empty<PublicAccessEntry>())),
|
||||
|
||||
new EventDefinition<IRelationService, SaveEventArgs<IRelationType>>(null, ServiceContext.RelationService, new SaveEventArgs<IRelationType>((IRelationType) null)),
|
||||
new EventDefinition<IRelationService, DeleteEventArgs<IRelationType>>(null, ServiceContext.RelationService, new DeleteEventArgs<IRelationType>((IRelationType) null)),
|
||||
new EventDefinition<IRelationService, SaveEventArgs<IRelationType>>(null, ServiceContext.RelationService, new SaveEventArgs<IRelationType>(Enumerable.Empty<IRelationType>())),
|
||||
new EventDefinition<IRelationService, DeleteEventArgs<IRelationType>>(null, ServiceContext.RelationService, new DeleteEventArgs<IRelationType>(Enumerable.Empty<IRelationType>())),
|
||||
|
||||
new EventDefinition<IRelationService, SaveEventArgs<IRelationType>>(null, ServiceContext.RelationService, new SaveEventArgs<IRelationType>((IRelationType) null)),
|
||||
new EventDefinition<IRelationService, DeleteEventArgs<IRelationType>>(null, ServiceContext.RelationService, new DeleteEventArgs<IRelationType>((IRelationType) null)),
|
||||
new EventDefinition<IRelationService, SaveEventArgs<IRelationType>>(null, ServiceContext.RelationService, new SaveEventArgs<IRelationType>(Enumerable.Empty<IRelationType>())),
|
||||
new EventDefinition<IRelationService, DeleteEventArgs<IRelationType>>(null, ServiceContext.RelationService, new DeleteEventArgs<IRelationType>(Enumerable.Empty<IRelationType>())),
|
||||
};
|
||||
|
||||
foreach (var definition in definitions)
|
||||
|
||||
@@ -4,13 +4,16 @@ using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
namespace Umbraco.Tests.Scoping
|
||||
{
|
||||
[TestFixture]
|
||||
public class ScopeEventDispatcherTests
|
||||
public class ScopeEventDispatcherTests : BaseUmbracoConfigurationTest
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
@@ -79,7 +82,7 @@ namespace Umbraco.Tests.Scoping
|
||||
var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray();
|
||||
|
||||
var knownNames = new[] { "DoThing1", "DoThing2", "DoThing3" };
|
||||
var knownArgTypes = new[] { typeof (SaveEventArgs<string>), typeof (SaveEventArgs<int>), typeof (SaveEventArgs<decimal>) };
|
||||
var knownArgTypes = new[] { typeof(SaveEventArgs<string>), typeof(SaveEventArgs<int>), typeof(SaveEventArgs<decimal>) };
|
||||
|
||||
for (var i = 0; i < events.Length; i++)
|
||||
{
|
||||
@@ -89,6 +92,166 @@ namespace Umbraco.Tests.Scoping
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SupersededEvents()
|
||||
{
|
||||
DoSaveForContent += OnDoThingFail;
|
||||
DoDeleteForContent += OnDoThingFail;
|
||||
DoForTestArgs += OnDoThingFail;
|
||||
DoForTestArgs2 += OnDoThingFail;
|
||||
|
||||
var contentType = MockedContentTypes.CreateBasicContentType();
|
||||
|
||||
var content1 = MockedContent.CreateBasicContent(contentType);
|
||||
content1.Id = 123;
|
||||
|
||||
var content2 = MockedContent.CreateBasicContent(contentType);
|
||||
content2.Id = 456;
|
||||
|
||||
var content3 = MockedContent.CreateBasicContent(contentType);
|
||||
content3.Id = 789;
|
||||
|
||||
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
|
||||
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
|
||||
{
|
||||
|
||||
//content1 will be filtered from the args
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(new[]{ content1 , content3}));
|
||||
scope.Events.Dispatch(DoDeleteForContent, this, new DeleteEventArgs<IContent>(content1));
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
|
||||
//this entire event will be filtered
|
||||
scope.Events.Dispatch(DoForTestArgs, this, new TestEventArgs(content1));
|
||||
scope.Events.Dispatch(DoForTestArgs2, this, new TestEventArgs2(content1));
|
||||
|
||||
// events have been queued
|
||||
var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray();
|
||||
Assert.AreEqual(4, events.Length);
|
||||
|
||||
Assert.AreEqual(typeof(SaveEventArgs<IContent>), events[0].Args.GetType());
|
||||
Assert.AreEqual(1, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.Count());
|
||||
Assert.AreEqual(content3.Id, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First().Id);
|
||||
|
||||
Assert.AreEqual(typeof(DeleteEventArgs<IContent>), events[1].Args.GetType());
|
||||
Assert.AreEqual(content1.Id, ((DeleteEventArgs<IContent>) events[1].Args).DeletedEntities.First().Id);
|
||||
|
||||
Assert.AreEqual(typeof(SaveEventArgs<IContent>), events[2].Args.GetType());
|
||||
Assert.AreEqual(content2.Id, ((SaveEventArgs<IContent>)events[2].Args).SavedEntities.First().Id);
|
||||
|
||||
Assert.AreEqual(typeof(TestEventArgs2), events[3].Args.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will test that when we track events that before we Get the events we normalize all of the
|
||||
/// event entities to be the latest one (most current) found amongst the event so that there is
|
||||
/// no 'stale' entities in any of the args
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void LatestEntities()
|
||||
{
|
||||
DoSaveForContent += OnDoThingFail;
|
||||
|
||||
var now = DateTime.Now;
|
||||
var contentType = MockedContentTypes.CreateBasicContentType();
|
||||
var content1 = MockedContent.CreateBasicContent(contentType);
|
||||
content1.Id = 123;
|
||||
content1.UpdateDate = now.AddMinutes(1);
|
||||
var content2 = MockedContent.CreateBasicContent(contentType);
|
||||
content2.Id = 123;
|
||||
content2.UpdateDate = now.AddMinutes(2);
|
||||
var content3 = MockedContent.CreateBasicContent(contentType);
|
||||
content3.Id = 123;
|
||||
content3.UpdateDate = now.AddMinutes(3);
|
||||
|
||||
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
|
||||
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
|
||||
{
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content1));
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content3));
|
||||
|
||||
// events have been queued
|
||||
var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray();
|
||||
Assert.AreEqual(3, events.Length);
|
||||
|
||||
foreach (var t in events)
|
||||
{
|
||||
var args = (SaveEventArgs<IContent>)t.Args;
|
||||
foreach (var entity in args.SavedEntities)
|
||||
{
|
||||
Assert.AreEqual(content3, entity);
|
||||
Assert.IsTrue(object.ReferenceEquals(content3, entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FirstIn()
|
||||
{
|
||||
DoSaveForContent += OnDoThingFail;
|
||||
|
||||
var now = DateTime.Now;
|
||||
var contentType = MockedContentTypes.CreateBasicContentType();
|
||||
var content1 = MockedContent.CreateBasicContent(contentType);
|
||||
content1.Id = 123;
|
||||
content1.UpdateDate = now.AddMinutes(1);
|
||||
var content2 = MockedContent.CreateBasicContent(contentType);
|
||||
content2.Id = 123;
|
||||
content1.UpdateDate = now.AddMinutes(2);
|
||||
var content3 = MockedContent.CreateBasicContent(contentType);
|
||||
content3.Id = 123;
|
||||
content1.UpdateDate = now.AddMinutes(3);
|
||||
|
||||
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
|
||||
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
|
||||
{
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content1));
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content3));
|
||||
|
||||
// events have been queued
|
||||
var events = scope.Events.GetEvents(EventDefinitionFilter.FirstIn).ToArray();
|
||||
Assert.AreEqual(1, events.Length);
|
||||
Assert.AreEqual(content1, ((SaveEventArgs<IContent>) events[0].Args).SavedEntities.First());
|
||||
Assert.IsTrue(object.ReferenceEquals(content1, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First()));
|
||||
Assert.AreEqual(content1.UpdateDate, ((SaveEventArgs<IContent>) events[0].Args).SavedEntities.First().UpdateDate);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LastIn()
|
||||
{
|
||||
DoSaveForContent += OnDoThingFail;
|
||||
|
||||
var now = DateTime.Now;
|
||||
var contentType = MockedContentTypes.CreateBasicContentType();
|
||||
var content1 = MockedContent.CreateBasicContent(contentType);
|
||||
content1.Id = 123;
|
||||
content1.UpdateDate = now.AddMinutes(1);
|
||||
var content2 = MockedContent.CreateBasicContent(contentType);
|
||||
content2.Id = 123;
|
||||
content2.UpdateDate = now.AddMinutes(2);
|
||||
var content3 = MockedContent.CreateBasicContent(contentType);
|
||||
content3.Id = 123;
|
||||
content3.UpdateDate = now.AddMinutes(3);
|
||||
|
||||
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
|
||||
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
|
||||
{
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content1));
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
|
||||
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content3));
|
||||
|
||||
// events have been queued
|
||||
var events = scope.Events.GetEvents(EventDefinitionFilter.LastIn).ToArray();
|
||||
Assert.AreEqual(1, events.Length);
|
||||
Assert.AreEqual(content3, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First());
|
||||
Assert.IsTrue(object.ReferenceEquals(content3, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First()));
|
||||
Assert.AreEqual(content3.UpdateDate, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First().UpdateDate);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void EventsDispatching_Passive(bool complete)
|
||||
@@ -177,12 +340,41 @@ namespace Umbraco.Tests.Scoping
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
public static event EventHandler<SaveEventArgs<IContent>> DoSaveForContent;
|
||||
public static event EventHandler<DeleteEventArgs<IContent>> DoDeleteForContent;
|
||||
public static event EventHandler<TestEventArgs> DoForTestArgs;
|
||||
public static event EventHandler<TestEventArgs2> DoForTestArgs2;
|
||||
public static event EventHandler<SaveEventArgs<string>> DoThing1;
|
||||
|
||||
public static event EventHandler<SaveEventArgs<int>> DoThing2;
|
||||
|
||||
public static event TypedEventHandler<ScopeEventDispatcherTests, SaveEventArgs<decimal>> DoThing3;
|
||||
|
||||
public class TestEventArgs : CancellableObjectEventArgs
|
||||
{
|
||||
public TestEventArgs(object eventObject) : base(eventObject)
|
||||
{
|
||||
}
|
||||
|
||||
public object MyEventObject
|
||||
{
|
||||
get { return EventObject; }
|
||||
}
|
||||
}
|
||||
|
||||
[SupersedeEvent(typeof(TestEventArgs))]
|
||||
public class TestEventArgs2 : CancellableObjectEventArgs
|
||||
{
|
||||
public TestEventArgs2(object eventObject) : base(eventObject)
|
||||
{
|
||||
}
|
||||
|
||||
public object MyEventObject
|
||||
{
|
||||
get { return EventObject; }
|
||||
}
|
||||
}
|
||||
|
||||
public class PassiveEventDispatcher : ScopeEventDispatcherBase
|
||||
{
|
||||
public PassiveEventDispatcher()
|
||||
|
||||
@@ -591,7 +591,7 @@ namespace Umbraco.Tests.Scoping
|
||||
Assert.IsNull(scopeProvider.AmbientContext);
|
||||
|
||||
// back to original thread
|
||||
ScopeProvider.HttpContextItemsGetter = () => httpContextItems;
|
||||
ScopeProvider.HttpContextItemsGetter = () => httpContextItems;
|
||||
}
|
||||
Assert.IsNotNull(scopeProvider.AmbientScope);
|
||||
Assert.AreSame(scope, scopeProvider.AmbientScope);
|
||||
@@ -656,6 +656,44 @@ namespace Umbraco.Tests.Scoping
|
||||
Assert.IsNotNull(ambientContext); // the context is still there
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void ScopeContextEnlistAgain(bool complete)
|
||||
{
|
||||
var scopeProvider = DatabaseContext.ScopeProvider;
|
||||
|
||||
bool? completed = null;
|
||||
Exception exception = null;
|
||||
|
||||
Assert.IsNull(scopeProvider.AmbientScope);
|
||||
using (var scope = scopeProvider.CreateScope())
|
||||
{
|
||||
scopeProvider.Context.Enlist("name", c =>
|
||||
{
|
||||
completed = c;
|
||||
|
||||
// at that point the scope is gone, but the context is still there
|
||||
var ambientContext = scopeProvider.AmbientContext;
|
||||
|
||||
try
|
||||
{
|
||||
ambientContext.Enlist("another", c2 => { });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
exception = e;
|
||||
}
|
||||
});
|
||||
if (complete)
|
||||
scope.Complete();
|
||||
}
|
||||
Assert.IsNull(scopeProvider.AmbientScope);
|
||||
Assert.IsNull(scopeProvider.AmbientContext);
|
||||
Assert.IsNotNull(completed);
|
||||
Assert.IsNotNull(exception);
|
||||
Assert.IsInstanceOf<InvalidOperationException>(exception);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ScopeContextException()
|
||||
{
|
||||
|
||||
@@ -179,7 +179,9 @@ namespace Umbraco.Tests.Scoping
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
Assert.AreEqual(complete ? 2 : 0, evented);
|
||||
//The reason why there is only 1 event occuring is because we are publishing twice for the same event for the same
|
||||
//object and the scope deduplicates the events (uses the latest)
|
||||
Assert.AreEqual(complete ? 1 : 0, evented);
|
||||
|
||||
// this should never change
|
||||
Assert.AreEqual(beforeOuterXml, beforeXml.OuterXml);
|
||||
|
||||
@@ -97,9 +97,8 @@
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Semver, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Semver.2.0.4\lib\netstandard1.1\Semver.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Reference Include="Semver, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\semver.1.1.2\lib\net45\Semver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="Selenium.WebDriver" version="2.32.0" targetFramework="net45" />
|
||||
<package id="Semver" version="2.0.4" targetFramework="net45" />
|
||||
<package id="semver" version="1.1.2" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.3.0" targetFramework="net45" />
|
||||
|
||||
@@ -5,15 +5,14 @@
|
||||
**/
|
||||
function ourPackageRepositoryResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
//var baseurl = "http://localhost:24292/webapi/packages/v1";
|
||||
var baseurl = "https://our.umbraco.org/webapi/packages/v1";
|
||||
var baseurl = Umbraco.Sys.ServerVariables.umbracoUrls.packagesRestApiBaseUrl;
|
||||
|
||||
return {
|
||||
|
||||
getDetails: function (packageId) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(baseurl + "/" + packageId),
|
||||
$http.get(baseurl + "/" + packageId + "?version=" + Umbraco.Sys.ServerVariables.application.version),
|
||||
'Failed to get package details');
|
||||
},
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
<div class="control-group" ng-class="{error: loginForm.username.$invalid}">
|
||||
<label><localize key="general_username">Username</localize></label>
|
||||
<input type="text" ng-model="login" name="username" class="-full-width-input" localize="placeholder" placeholder="@placeholders_username" />
|
||||
<input type="text" ng-model="login" name="username" class="-full-width-input" localize="placeholder" placeholder="@placeholders_usernameHint" />
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<IISExpressSSLPort>44319</IISExpressSSLPort>
|
||||
<IISExpressSSLPort>
|
||||
</IISExpressSSLPort>
|
||||
<IISExpressAnonymousAuthentication>enabled</IISExpressAnonymousAuthentication>
|
||||
<IISExpressWindowsAuthentication>disabled</IISExpressWindowsAuthentication>
|
||||
<IISExpressUseClassicPipelineMode>false</IISExpressUseClassicPipelineMode>
|
||||
@@ -348,13 +349,6 @@
|
||||
<Compile Include="..\SolutionInfo.cs">
|
||||
<Link>Properties\SolutionInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Umbraco\Install\Legacy\LoadStarterKits.ascx.cs">
|
||||
<DependentUpon>loadStarterKits.ascx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Umbraco\Install\Legacy\LoadStarterKits.ascx.designer.cs">
|
||||
<DependentUpon>loadStarterKits.ascx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Config\splashes\NoNodes.aspx.cs">
|
||||
<DependentUpon>noNodes.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
@@ -453,13 +447,6 @@
|
||||
<Compile Include="Umbraco\Developer\Packages\DirectoryBrowser.aspx.designer.cs">
|
||||
<DependentUpon>directoryBrowser.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Umbraco\Developer\Packages\StarterKits.aspx.cs">
|
||||
<DependentUpon>StarterKits.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Umbraco\Developer\Packages\StarterKits.aspx.designer.cs">
|
||||
<DependentUpon>StarterKits.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Umbraco\Developer\Python\EditPython.aspx.cs">
|
||||
<DependentUpon>editPython.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
@@ -579,9 +566,9 @@
|
||||
<Content Include="Config\Lang\sv-SE.user.xml" />
|
||||
<Content Include="Config\Lang\zh-CN.user.xml" />
|
||||
<Content Include="Umbraco\Config\Lang\cs.xml" />
|
||||
<Content Include="Umbraco\Install\Legacy\loadStarterKits.ascx" />
|
||||
<Content Include="Umbraco\ClientRedirect.aspx" />
|
||||
<Content Include="Umbraco\create.aspx" />
|
||||
<Content Include="Umbraco\Developer\Packages\installer.aspx" />
|
||||
<Content Include="Umbraco\Logout.aspx" />
|
||||
<Content Include="Umbraco\umbraco.aspx" />
|
||||
<Content Include="Umbraco_Client\Application\JQuery\jquery.unobtrusive-ajax.min.js" />
|
||||
@@ -1546,7 +1533,6 @@
|
||||
<Content Include="Umbraco_Client\Installer\Js\jquery.ui.selectmenu.js" />
|
||||
<Content Include="Umbraco\Config\Lang\ko.xml" />
|
||||
<Content Include="Umbraco\Dashboard\FeedProxy.aspx" />
|
||||
<Content Include="Umbraco\Developer\Packages\StarterKits.aspx" />
|
||||
<Content Include="Umbraco\helpRedirect.aspx" />
|
||||
<Content Include="Umbraco\Images\aboutNew.png" />
|
||||
<Content Include="Umbraco\Images\Editor\skin.gif" />
|
||||
@@ -1716,7 +1702,6 @@
|
||||
<Content Include="Umbraco_Client\Tree\Themes\Umbraco\li.gif" />
|
||||
<Content Include="Umbraco_Client\Tree\Themes\Umbraco\style.css" />
|
||||
<Content Include="Umbraco_Client\Tree\Themes\Umbraco\throbber.gif" />
|
||||
<Content Include="Umbraco\Developer\Packages\proxy.htm" />
|
||||
<Content Include="Umbraco\Developer\Xslt\xsltVisualize.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\empty.htm" />
|
||||
<Content Include="Umbraco\Dialogs\insertMasterpageContent.aspx" />
|
||||
@@ -1783,12 +1768,8 @@
|
||||
<Content Include="Umbraco\Images\Umbraco\repository.gif" />
|
||||
<Content Include="Umbraco\Images\Umbraco\uploadpackage.gif" />
|
||||
<Content Include="Umbraco_Client\Application\JQuery\jquery.autocomplete.js" />
|
||||
<Content Include="Umbraco\Developer\Packages\BrowseRepository.aspx" />
|
||||
<Content Include="Umbraco\Developer\Packages\directoryBrowser.aspx" />
|
||||
<Content Include="Umbraco\Developer\Packages\editPackage.aspx" />
|
||||
<Content Include="Umbraco\Developer\Packages\installedPackage.aspx" />
|
||||
<Content Include="Umbraco\Developer\Packages\LoadNitros.ascx" />
|
||||
<Content Include="Umbraco\Developer\Packages\SubmitPackage.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\about.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\AssignDomain.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\create.aspx" />
|
||||
@@ -1801,7 +1782,6 @@
|
||||
<Content Include="Umbraco\Dialogs\insertTable.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\moveOrCopy.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\notifications.aspx" />
|
||||
<Content Include="Umbraco\Developer\Packages\installer.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\protectPage.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\publish.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\RegexWs.aspx" />
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using System.Web.UI;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Web.Install;
|
||||
|
||||
namespace Umbraco.Web.UI.Install.Steps.Skinning
|
||||
{
|
||||
public delegate void StarterKitInstalledEventHandler();
|
||||
|
||||
public partial class LoadStarterKits : UserControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the string for the package installer web service base url
|
||||
/// </summary>
|
||||
protected string PackageInstallServiceBaseUrl { get; private set; }
|
||||
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
|
||||
//Get the URL for the package install service base url
|
||||
var umbracoPath = Core.Configuration.GlobalSettings.UmbracoMvcArea;
|
||||
var urlHelper = new UrlHelper(Context.Request.RequestContext);
|
||||
//PackageInstallServiceBaseUrl = urlHelper.Action("Index", "InstallPackage", new { area = "UmbracoInstall" });
|
||||
PackageInstallServiceBaseUrl = urlHelper.GetUmbracoApiService("Index", "InstallPackage", "UmbracoInstall");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag to show if we can connect to the repo or not
|
||||
/// </summary>
|
||||
protected bool CannotConnect { get; private set; }
|
||||
|
||||
public event StarterKitInstalledEventHandler StarterKitInstalled;
|
||||
|
||||
protected virtual void OnStarterKitInstalled()
|
||||
{
|
||||
StarterKitInstalled();
|
||||
}
|
||||
|
||||
|
||||
private readonly global::umbraco.cms.businesslogic.packager.repositories.Repository _repo;
|
||||
private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66";
|
||||
|
||||
public LoadStarterKits()
|
||||
{
|
||||
_repo = global::umbraco.cms.businesslogic.packager.repositories.Repository.getByGuid(RepoGuid);
|
||||
}
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//protected void NextStep(object sender, EventArgs e)
|
||||
//{
|
||||
// var p = (Default)this.Page;
|
||||
// //InstallHelper.RedirectToNextStep(Page, Request.GetItemAsString("installStep"));
|
||||
//}
|
||||
|
||||
protected override void OnInit(EventArgs e)
|
||||
{
|
||||
base.OnInit(e);
|
||||
|
||||
if (_repo == null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not find repository with id " + RepoGuid);
|
||||
}
|
||||
|
||||
//clear progressbar cache
|
||||
//InstallHelper.ClearProgress();
|
||||
|
||||
if (_repo.HasConnection())
|
||||
{
|
||||
try
|
||||
{
|
||||
var r = new org.umbraco.our.Repository();
|
||||
|
||||
rep_starterKits.DataSource = r.Modules();
|
||||
rep_starterKits.DataBind();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<LoadStarterKits>("Cannot connect to package repository", ex);
|
||||
CannotConnect = true;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CannotConnect = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void GotoLastStep(object sender, EventArgs e)
|
||||
{
|
||||
//InstallHelper.RedirectToLastStep(Page);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Umbraco.Web.UI.Install.Steps.Skinning {
|
||||
|
||||
|
||||
public partial class LoadStarterKits {
|
||||
|
||||
/// <summary>
|
||||
/// pl_loadStarterKits control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.PlaceHolder pl_loadStarterKits;
|
||||
|
||||
/// <summary>
|
||||
/// JsInclude1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::ClientDependency.Core.Controls.JsInclude JsInclude1;
|
||||
|
||||
/// <summary>
|
||||
/// rep_starterKits control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Repeater rep_starterKits;
|
||||
|
||||
/// <summary>
|
||||
/// LinkButton1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.LinkButton LinkButton1;
|
||||
|
||||
/// <summary>
|
||||
/// LinkButton2 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.LinkButton LinkButton2;
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
<%@ Control Language="C#" AutoEventWireup="True" CodeBehind="LoadStarterKits.ascx.cs" Inherits="Umbraco.Web.UI.Install.Steps.Skinning.LoadStarterKits" %>
|
||||
<%@ Import Namespace="Umbraco.Web.org.umbraco.our" %>
|
||||
|
||||
<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %>
|
||||
|
||||
<asp:PlaceHolder ID="pl_loadStarterKits" runat="server">
|
||||
|
||||
<umb:JsInclude ID="JsInclude1" runat="server" FilePath="installer/js/PackageInstaller.js" PathNameAlias="UmbracoClient" />
|
||||
|
||||
<% if (!CannotConnect) { %>
|
||||
<script type="text/javascript">
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
var installer = new Umbraco.Installer.PackageInstaller({
|
||||
starterKits: $("a.selectStarterKit"),
|
||||
baseUrl: "<%= PackageInstallServiceBaseUrl %>",
|
||||
serverError: $("#serverError"),
|
||||
connectionError: $("#connectionError"),
|
||||
setProgress: updateProgressBar,
|
||||
setStatusMessage: updateStatusMessage
|
||||
});
|
||||
installer.init();
|
||||
});
|
||||
})(jQuery);
|
||||
</script>
|
||||
<% } %>
|
||||
<div id="starter-kit-progress" style="display: none;">
|
||||
<h2>Installation in progress...</h2>
|
||||
<div class="loader">
|
||||
<div class="hold">
|
||||
<div class="progress-bar">
|
||||
</div>
|
||||
<span class="progress-bar-value">0%</span>
|
||||
</div>
|
||||
<strong></strong>
|
||||
</div>
|
||||
</div>
|
||||
<asp:Repeater ID="rep_starterKits" runat="server">
|
||||
<headertemplate>
|
||||
<ul class="thumbnails">
|
||||
</headertemplate>
|
||||
<itemtemplate>
|
||||
<li class="span4 add-<%# ((Package)Container.DataItem).Text.Replace(" ","").ToLower() %>">
|
||||
<div class="thumbnail" style="margin-right: 10px; height: 260px">
|
||||
<img src="http://our.umbraco.org<%# ((Package)Container.DataItem).Thumbnail %>?width=170" alt="<%# ((Package)Container.DataItem).Text %>">
|
||||
|
||||
<h4><%# ((Package)Container.DataItem).Text %></h4>
|
||||
<%# ((Package)Container.DataItem).Description %>
|
||||
|
||||
<a href="#" class="btn btn-success single-tab selectStarterKit" data-name="<%# ((Package)Container.DataItem).Text %>" title="Install <%# ((Package)Container.DataItem).Text %>" data-repoid="<%# ((Package)Container.DataItem).RepoGuid %>">
|
||||
Install
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</itemtemplate>
|
||||
<footertemplate>
|
||||
</ul>
|
||||
<%--<asp:LinkButton runat="server" ID="declineStarterKits" CssClass="declineKit" OnClientClick="return confirm('Are you sure you do not want to install a starter kit?');" OnClick="NextStep">
|
||||
No thanks, do not install a starterkit!
|
||||
</asp:LinkButton>--%>
|
||||
</footertemplate>
|
||||
</asp:Repeater>
|
||||
|
||||
</asp:PlaceHolder>
|
||||
|
||||
<div id="connectionError" style="<%= CannotConnect ? "" : "display:none;" %>">
|
||||
|
||||
<div style="padding: 0 100px 13px 5px;">
|
||||
<h2>Oops...the installer can't connect to the repository</h2>
|
||||
Starter Kits could not be fetched from the repository as there was no connection - which can occur if you are using a proxy server or firewall with certain configurations,
|
||||
or if you are not currently connected to the internet.
|
||||
<br />
|
||||
Click <strong>Continue</strong> to complete the installation then navigate to the Developer section of your Umbraco installation
|
||||
where you will find the Starter Kits listed in the Packages tree.
|
||||
</div>
|
||||
|
||||
<!-- btn box -->
|
||||
<footer class="btn-box">
|
||||
<div class="t"> </div>
|
||||
<asp:LinkButton ID="LinkButton1" class="btn-step btn btn-continue" runat="server" OnClick="GotoLastStep"><span>Continue</span></asp:LinkButton>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="serverError" style="display:none;">
|
||||
|
||||
<div style="padding: 0 100px 13px 5px;">
|
||||
<h2>Oops...the installer encountered an error</h2>
|
||||
<div class="error-message"></div>
|
||||
</div>
|
||||
|
||||
<!-- btn box -->
|
||||
<footer class="btn-box">
|
||||
<div class="t"> </div>
|
||||
<asp:LinkButton ID="LinkButton2" class="btn-step btn btn-continue" runat="server" OnClick="GotoLastStep"><span>Continue</span></asp:LinkButton>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
@@ -150,7 +150,7 @@
|
||||
<key alias="releaseDate">Udgivelsesdato</key>
|
||||
<key alias="unpublishDate">Dato for Fortryd udgivelse</key>
|
||||
<key alias="removeDate">Fjern dato</key>
|
||||
<key alias="sortDone">Sorteringrækkefølgen er opdateret</key>
|
||||
<key alias="sortDone">Sorteringsrækkefølgen er opdateret</key>
|
||||
<key alias="sortHelp">For at sortere, træk siderne eller klik på en af kolonnehovederne. Du kan vælge flere sider ved at holde "shift" eller "control" nede mens du vælger.</key>
|
||||
<key alias="statistics">Statistik</key>
|
||||
<key alias="titleOptional">Titel (valgfri)</key>
|
||||
@@ -184,7 +184,7 @@
|
||||
<key alias="updateData">Vælg en type og skriv en titel</key>
|
||||
<key alias="noDocumentTypes" version="7.0"><![CDATA[Der kunne ikke findes nogen tilladte dokument typer. Du skal tillade disse i indstillinger under <strong>"dokument typer"</strong>.]]></key>
|
||||
<key alias="noMediaTypes" version="7.0"><![CDATA[Der kunne ikke findes nogen tilladte media typer. Du skal tillade disse i indstillinger under <strong>"media typer"</strong>.]]></key>
|
||||
<key alias="documentTypeWithoutTemplate">Dokument type uden skabelon</key>
|
||||
<key alias="documentTypeWithoutTemplate">Dokumenttype uden skabelon</key>
|
||||
<key alias="newFolder">Ny mappe</key>
|
||||
<key alias="newDataType">Ny datatype</key>
|
||||
</area>
|
||||
@@ -321,6 +321,7 @@
|
||||
<key alias="search">Søg...</key>
|
||||
<key alias="filter">Filtrer...</key>
|
||||
<key alias="enterTags">Indtast nøgleord (tryk på Enter efter hvert nøgleord)...</key>
|
||||
<key alias="usernameHint">Dit brugernavn er typisk din e-mail adresse</key>
|
||||
</area>
|
||||
<area alias="editcontenttype">
|
||||
<key alias="allowAtRoot" version="7.2">Tillad på rodniveau</key>
|
||||
@@ -579,13 +580,13 @@
|
||||
<key alias="permissionsAffectedFolders">Berørte filer og foldere</key>
|
||||
<key alias="permissionsAffectedFoldersMoreInfo">Flere informationer om at opsætte rettigheder for Umbraco her</key>
|
||||
<key alias="permissionsAffectedFoldersText">Du er nødt til at give ASP.NET 'modify' rettigheder på følgende filer/foldere</key>
|
||||
<key alias="permissionsAlmostPerfect"><![CDATA[<strong>Dine rettighedsinstillinger er næsten perfekte!</strong><br/><br/>Du kan køre Umbraco uden problemer, men du vil ikke være i stand til at installere pakker, som er anbefalet for at få fuldt udbytte af Umbraco.]]></key>
|
||||
<key alias="permissionsAlmostPerfect"><![CDATA[<strong>Dine rettighedsindstillinger er næsten perfekte!</strong><br/><br/>Du kan køre Umbraco uden problemer, men du vil ikke være i stand til at installere pakker, som er anbefalet for at få fuldt udbytte af Umbraco.]]></key>
|
||||
<key alias="permissionsHowtoResolve">Hvorledes besluttes</key>
|
||||
<key alias="permissionsHowtoResolveLink">Klik her for at læse tekstversionen</key>
|
||||
<key alias="permissionsHowtoResolveText"><![CDATA[Se vores <strong>video tutorials</strong> om at opsætte folderrettigheder for Umbraco eller læs tekstversionen.]]></key>
|
||||
<key alias="permissionsMaybeAnIssue"><![CDATA[<strong>Dine rettighedsinstillinger kan være et problem!</strong><br/><br/>Du kan afvikle Umbraco uden problemer, men du vil ikke være i stand til at oprette foldere eller installere pakker, hvilket er anbefalet for at få fuldt udbytte af Umbraco.]]></key>
|
||||
<key alias="permissionsNotReady"><![CDATA[<strong>Dine rettighedsinstillinger er ikke klar til Umbraco!</strong><br/><br/>For at afvikle Umbraco er du nødt til at opdatere dine rettighedsinstillinger.]]></key>
|
||||
<key alias="permissionsPerfect"><![CDATA[<strong>Dine rettighedsinstillinger er perfekte!</strong><br/><br/>Du er nu parat til at afvikle Umbraco og installere pakker!]]></key>
|
||||
<key alias="permissionsMaybeAnIssue"><![CDATA[<strong>Dine rettighedsindstillinger kan være et problem!</strong><br/><br/>Du kan afvikle Umbraco uden problemer, men du vil ikke være i stand til at oprette foldere eller installere pakker, hvilket er anbefalet for at få fuldt udbytte af Umbraco.]]></key>
|
||||
<key alias="permissionsNotReady"><![CDATA[<strong>Dine rettighedsindstillinger er ikke klar til Umbraco!</strong><br/><br/>For at afvikle Umbraco er du nødt til at opdatere dine rettighedsindstillinger.]]></key>
|
||||
<key alias="permissionsPerfect"><![CDATA[<strong>Dine rettighedsindstillinger er perfekte!</strong><br/><br/>Du er nu parat til at afvikle Umbraco og installere pakker!]]></key>
|
||||
<key alias="permissionsResolveFolderIssues">Løser folder problem</key>
|
||||
<key alias="permissionsResolveFolderIssuesLink">Følg dette link for mere information om udfordringer med ASP.NET og oprettelse af foldere</key>
|
||||
<key alias="permissionsSettingUpPermissions">Sætter folderrettigheder op</key>
|
||||
@@ -597,7 +598,7 @@
|
||||
<key alias="runwayInstalledText"><![CDATA[Du har fundamentet på plads. Vælg hvilke moduler du ønsker at installere ovenpå det.<br/>Dette er vores liste over anbefalede moduler. Kryds dem af du ønsker at installere eller se den <a href="#" onclick="toggleModules(); return false;" id="toggleModuleList">fulde liste af moduler</a> ]]></key>
|
||||
<key alias="runwayOnlyProUsers">Kun anbefalet for erfarne brugere</key>
|
||||
<key alias="runwaySimpleSite">Jeg ønsker at begynder med et simpelt website</key>
|
||||
<key alias="runwaySimpleSiteText"><![CDATA[<p>"Runway" er et simpelt website som stiller nogle basale dokumenttyper og skabeloner til rådighed. Instaleringsprogrammet kan automatisk opsætte Runway for dig, men du kan nemt redigere, udvide eller fjerne det. Det er ikke nødvendigt og du kan sagtens bruge Umbraco uden. Men Runway tilbyder et fundament, som er baseret på 'Best Practices', som får dig igang hurtigere end nogensinde før. Hvis du vælger at installere Runway, kan du efter eget valg vælge de grundlæggende byggesten kaldet 'Runway Modules' til at forbedre dine Runway-sider.</p><p><small><em>Inkluderet med Runway:</em>Home Page, Getting Started page, Installing Modules page.<br /> <em>Valgfri Moduler:</em> Top Navigation, Sitemap, Contact, Gallery. </small></p>]]></key>
|
||||
<key alias="runwaySimpleSiteText"><![CDATA[<p>"Runway" er et simpelt website som stiller nogle basale dokumenttyper og skabeloner til rådighed. Installeringsprogrammet kan automatisk opsætte Runway for dig, men du kan nemt redigere, udvide eller fjerne det. Det er ikke nødvendigt og du kan sagtens bruge Umbraco uden. Men Runway tilbyder et fundament, som er baseret på 'Best Practices', som får dig igang hurtigere end nogensinde før. Hvis du vælger at installere Runway, kan du efter eget valg vælge de grundlæggende byggesten kaldet 'Runway Modules' til at forbedre dine Runway-sider.</p><p><small><em>Inkluderet med Runway:</em>Home Page, Getting Started page, Installing Modules page.<br /> <em>Valgfri Moduler:</em> Top Navigation, Sitemap, Contact, Gallery. </small></p>]]></key>
|
||||
<key alias="runwayWhatIsRunway">Hvad er Runway</key>
|
||||
<key alias="step1">Skridt 1/5: Acceptér licens</key>
|
||||
<key alias="step2">Skridt 2/5: Database-konfiguration</key>
|
||||
@@ -714,7 +715,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="packageRepository">Pakke opbevaringsbase</key>
|
||||
<key alias="packageUninstallConfirm">Bekræft af-installering</key>
|
||||
<key alias="packageUninstalledHeader">Pakken blev fjernet</key>
|
||||
<key alias="packageUninstalledText">Pakken er på succefuld vis blevet fjernet</key>
|
||||
<key alias="packageUninstalledText">Pakken er på succesfuld vis blevet fjernet</key>
|
||||
<key alias="packageUninstallHeader">Afinstallér pakke</key>
|
||||
<key alias="packageUninstallText">
|
||||
<![CDATA[Du kan fjerne markeringen på elementer du ikke ønsker at fjerne, på dette tidspunkt, nedenfor. Når du klikker 'bekræft' vil alle afkrydsede elemenet blive fjernet <br/>
|
||||
@@ -795,7 +796,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="addRows">Tilføj række</key>
|
||||
<key alias="addElement">Tilføj indhold</key>
|
||||
<key alias="dropElement">Slip indhold</key>
|
||||
<key alias="settingsApplied">Instillinger tilføjet</key>
|
||||
<key alias="settingsApplied">Indstillinger tilføjet</key>
|
||||
|
||||
<key alias="contentNotAllowed">Indholdet er ikke tilladt her</key>
|
||||
<key alias="contentAllowed">Indholdet er tilladt her</key>
|
||||
@@ -940,7 +941,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="tab">Faneblad</key>
|
||||
<key alias="tabname">Titel på faneblad</key>
|
||||
<key alias="tabs">Faneblade</key>
|
||||
<key alias="masterDocumentType">Master Dokument Type</key>
|
||||
<key alias="masterDocumentType">Master Dokumenttype</key>
|
||||
<key alias="createMatchingTemplate">Opret matchende skabelon</key>
|
||||
</area>
|
||||
<area alias="sort">
|
||||
@@ -1024,7 +1025,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="insertContentAreaPlaceHolder">Indsæt pladsholder for indholdsområde</key>
|
||||
|
||||
<key alias="insert">Indsæt</key>
|
||||
<key alias="insertDesc">Hvad vil du indsætte ?</key>
|
||||
<key alias="insertDesc">Hvad vil du indsætte?</key>
|
||||
|
||||
<key alias="insertDictionaryItem">Oversættelse</key>
|
||||
<key alias="insertDictionaryItemDesc">Indsætter en oversætbar tekst, som skifter efter det sprog, som websitet vises i.</key>
|
||||
|
||||
@@ -278,6 +278,7 @@
|
||||
<key alias="search">Durchsuchen ...</key>
|
||||
<key alias="filter">Filtern ...</key>
|
||||
<key alias="enterTags">Tippen, um Tags hinzuzufügen (nach jedem Tag die Eingabetaste drücken) ...</key>
|
||||
<key alias="usernameHint">Der Benutzername ist normalerweise Ihre E-Mail-Adresse</key>
|
||||
</area>
|
||||
<area alias="editcontenttype">
|
||||
<key alias="allowAtRoot" version="7.2">Auf oberster Ebene erlauben</key>
|
||||
|
||||
@@ -348,6 +348,7 @@
|
||||
<key alias="filter">Type to filter...</key>
|
||||
<key alias="enterTags">Type to add tags (press enter after each tag)...</key>
|
||||
<key alias="email">Enter your email</key>
|
||||
<key alias="usernameHint">Your username is usually your email</key>
|
||||
</area>
|
||||
<area alias="editcontenttype">
|
||||
<key alias="allowAtRoot" version="7.2">Allow at root</key>
|
||||
|
||||
@@ -1547,4 +1547,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="enabledConfirm">URL tracker has now been enabled.</key>
|
||||
<key alias="enableError">Error enabling the URL tracker, more information can be found in your log file.</key>
|
||||
</area>
|
||||
<area alias="emptyStates">
|
||||
<key alias="emptyDictionaryTree">No Dictionary items to choose from</key>
|
||||
</area>
|
||||
</language>
|
||||
|
||||
@@ -277,6 +277,7 @@
|
||||
<key alias="entername">Escribe un nombre...</key>
|
||||
<key alias="search">Escribe tu búsqueda...</key>
|
||||
<key alias="filter">Escribe para filtrar resultados...</key>
|
||||
<key alias="usernameHint">Tu nombre de usuario normalmente es tu e-mail</key>
|
||||
</area>
|
||||
<area alias="editcontenttype">
|
||||
<key alias="allowAtRoot" version="7.2">Permitir en nodo raíz</key>
|
||||
|
||||
@@ -329,6 +329,7 @@
|
||||
<key alias="filter">Filtrer...</key>
|
||||
<key alias="enterTags">Ajouter des tags (appuyer sur enter entre chaque tag)...</key>
|
||||
<key alias="email">Entrez votre email</key>
|
||||
<key alias="usernameHint">Votre nom d'utilisateur est généralement votre adresse email</key>
|
||||
</area>
|
||||
|
||||
<area alias="editcontenttype">
|
||||
|
||||
@@ -339,6 +339,7 @@
|
||||
<key alias="filter">Typ om te filteren...</key>
|
||||
<key alias="enterTags">Typ om tags toe te voegen (druk op enter na elke tag)...</key>
|
||||
<key alias="email">Voer jouw email in</key>
|
||||
<key alias="usernameHint">Jouw gebruikersnaam is meestal jouw email</key>
|
||||
</area>
|
||||
|
||||
<area alias="editcontenttype">
|
||||
|
||||
@@ -416,6 +416,9 @@
|
||||
<key alias="rteShowLabel">Показать метку</key>
|
||||
<key alias="rteWidthAndHeight">Ширина и высота</key>
|
||||
</area>
|
||||
<area alias="emptyStates">
|
||||
<key alias="emptyDictionaryTree">Нет доступных элементов словаря</key>
|
||||
</area>
|
||||
<area alias="errorHandling">
|
||||
<key alias="errorButDataWasSaved">Ваши данные сохранены, но для того, чтобы опубликовать этот документ, Вы должны сначала исправить следующие ошибки:</key>
|
||||
<key alias="errorChangingProviderPassword">Текущий провайдер ролей пользователей не поддерживает изменение пароля (необходимо свойству EnablePasswordRetrieval в файле web.config присвоить значение true)</key>
|
||||
@@ -1019,6 +1022,7 @@
|
||||
<key alias="password">Укажите пароль</key>
|
||||
<key alias="search">Что искать...</key>
|
||||
<key alias="username">Укажите имя пользователя</key>
|
||||
<key alias="usernameHint">Имя пользователя (часто это Ваш email-адрес)</key>
|
||||
</area>
|
||||
<area alias="prompt">
|
||||
<key alias="stay">Остаться</key>
|
||||
|
||||
@@ -594,6 +594,7 @@
|
||||
<key alias="search">Skriv för att söka...</key>
|
||||
<key alias="username">Fyll i ditt lösenord</key>
|
||||
<key alias="enterTags">Skriv för att lägga till taggar (och tryck enter efter varje tagg)...</key>
|
||||
<key alias="usernamehint">Ditt användarnamn är vanligtvis din e-postadress</key>
|
||||
</area>
|
||||
<area alias="publicAccess">
|
||||
<key alias="paAdvanced">Rollbaserat lösenordsskydd</key>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="../../masterpages/umbracoPage.Master" Title="Browse Repository" CodeBehind="BrowseRepository.aspx.cs" Inherits="umbraco.presentation.developer.packages.BrowseRepository" %>
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="body" runat="server">
|
||||
<cc1:UmbracoPanel id="Panel1" Text="Browse package repository" runat="server" Width="612px" Height="600px" hasMenu="false">
|
||||
<cc1:Feedback ID="fb" runat="server" />
|
||||
<asp:Literal runat="server" ID="iframeGen" />
|
||||
</cc1:UmbracoPanel>
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="footer" runat="server">
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function() {
|
||||
var frame = jQuery("#repoFrame");
|
||||
var win = jQuery(window);
|
||||
frame.height(win.height() - frame.offset().top - 40);
|
||||
frame.width(win.width() - 35);
|
||||
});
|
||||
</script>
|
||||
</asp:Content>
|
||||
@@ -1,32 +0,0 @@
|
||||
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="LoadNitros.ascx.cs" Inherits="umbraco.presentation.developer.packages.LoadNitros" %>
|
||||
|
||||
<asp:Panel id="loadNitros" runat="server">
|
||||
|
||||
<div id="list1a">
|
||||
<span id="editorCategories">
|
||||
<a class="accordianOpener">
|
||||
Editors picks
|
||||
<small>Recommended by the umbraco core team</small>
|
||||
</a>
|
||||
<div style="display: block;" class="accordianContainer">
|
||||
<asp:PlaceHolder ID="ph_recommendedHolder" runat="server" />
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span id="generatedCategories">
|
||||
<asp:Repeater ID="rep_nitros" runat="server" OnItemDataBound="onCategoryDataBound">
|
||||
<ItemTemplate>
|
||||
<a class="accordianOpener generated">
|
||||
<asp:Literal ID="lit_name" runat="server" />
|
||||
<small><asp:Literal ID="lit_desc" runat="server"/></small>
|
||||
</a>
|
||||
<div class="accordianContainer generated">
|
||||
<asp:PlaceHolder ID="ph_nitroHolder" runat="server" />
|
||||
</div>
|
||||
</ItemTemplate>
|
||||
</asp:Repeater>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<asp:Button runat="server" CssClass="loadNitrosButton" id="bt_install" OnClick="installNitros" OnClientClick="InstallPackages(this,'loadingBar'); return true;" Text="Install selected modules" />
|
||||
</asp:Panel>
|
||||
@@ -1,86 +0,0 @@
|
||||
<%@ Page Language="C#" AutoEventWireup="True" MasterPageFile="../../masterpages/umbracoPage.Master" Title="Install starter kit" CodeBehind="StarterKits.aspx.cs" Inherits="Umbraco.Web.UI.Umbraco.Developer.Packages.StarterKits" %>
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %>
|
||||
|
||||
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
|
||||
|
||||
<umb:JsInclude ID="JsInclude1" runat="server" FilePath="ui/jqueryui.js" PathNameAlias="UmbracoClient" />
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var percentComplete = 0;
|
||||
|
||||
jQuery(document).ready(function() {
|
||||
//bind to button click events
|
||||
jQuery("a.selectStarterKit").click(function() {
|
||||
jQuery(".progress-status").siblings(".install-dialog").hide();
|
||||
jQuery(".progress-status").show();
|
||||
});
|
||||
});
|
||||
|
||||
function updateProgressBar(percent) {
|
||||
percentComplete = percent;
|
||||
}
|
||||
function updateStatusMessage(message, error) {
|
||||
if (message != null && message != undefined) {
|
||||
jQuery(".progress-status").text(message + " (" + percentComplete + "%)");
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style type="text/css">
|
||||
|
||||
.progress-status {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.add-thanks
|
||||
{
|
||||
position:absolute;
|
||||
left:-2500;
|
||||
display:none !important;
|
||||
}
|
||||
|
||||
.zoom-list li {float: left; margin: 15px; display: block; width: 180px;}
|
||||
|
||||
.btn-prev, .btn-next, .paging, .btn-preview, .faik-mask , .faik-mask-ie6
|
||||
{
|
||||
display:none;
|
||||
}
|
||||
|
||||
.image {float: left; margin: 15px; display: block; width: 140px;}
|
||||
|
||||
.image .gal-drop{padding-top:10px;}
|
||||
|
||||
ul{list-style-type: none;}
|
||||
</style>
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ID="Content2" ContentPlaceHolderID="body" runat="server">
|
||||
<cc1:UmbracoPanel id="Panel1" Text="Starter kit" runat="server" Width="612px" Height="600px" hasMenu="false">
|
||||
<cc1:Feedback ID="fb" runat="server" />
|
||||
|
||||
<cc1:Pane id="StarterKitNotInstalled" Text="Install starter kit" runat="server">
|
||||
<h3>Available starter kits</h3>
|
||||
<p>You can choose from the following starter kits, each having specific functionality.</p>
|
||||
<div class="progress-status">Please wait...</div>
|
||||
<div id="connectionError"></div>
|
||||
<div id="serverError"></div>
|
||||
<div class="install-dialog">
|
||||
<asp:PlaceHolder ID="ph_starterkits" runat="server"></asp:PlaceHolder>
|
||||
</div>
|
||||
</cc1:Pane>
|
||||
|
||||
<cc1:Pane id="installationCompleted" Text="Installation completed" runat="server" Visible="false">
|
||||
<p>Installation completed succesfully</p>
|
||||
</cc1:Pane>
|
||||
|
||||
<cc1:Pane id="InstallationDirectoryNotAvailable" Text="Unable to install" runat="server" Visible="false">
|
||||
<p>We can not install starterkits when the install directory or package repository is not present.</p>
|
||||
</cc1:Pane>
|
||||
|
||||
|
||||
</cc1:UmbracoPanel>
|
||||
|
||||
|
||||
</asp:Content>
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Web.UI.Install.Steps.Skinning;
|
||||
using Umbraco.Web.UI.Pages;
|
||||
using System.IO;
|
||||
using umbraco.cms.businesslogic.packager;
|
||||
|
||||
namespace Umbraco.Web.UI.Umbraco.Developer.Packages
|
||||
{
|
||||
|
||||
|
||||
public partial class StarterKits : UmbracoEnsuredPage
|
||||
{
|
||||
private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66";
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
//check if a starter kit is already isntalled
|
||||
|
||||
var installed = InstalledPackage.GetAllInstalledPackages();
|
||||
|
||||
if (installed.Count == 0)
|
||||
{
|
||||
ShowStarterKits();
|
||||
return;
|
||||
}
|
||||
|
||||
var repo = global::umbraco.cms.businesslogic.packager.repositories.Repository.getByGuid(RepoGuid);
|
||||
if (repo.HasConnection())
|
||||
{
|
||||
try
|
||||
{
|
||||
var kits = repo.Webservice.StarterKits();
|
||||
var kitIds = kits.Select(x => x.RepoGuid).ToArray();
|
||||
|
||||
//if a starter kit is already installed show finish
|
||||
if (installed.Any(x => kitIds.Contains(Guid.Parse(x.Data.PackageGuid))))
|
||||
{
|
||||
StarterKitNotInstalled.Visible = false;
|
||||
installationCompleted.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowStarterKits();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<StarterKits>("Cannot connect to package repository", ex);
|
||||
InstallationDirectoryNotAvailable.Visible = true;
|
||||
StarterKitNotInstalled.Visible = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InstallationDirectoryNotAvailable.Visible = true;
|
||||
StarterKitNotInstalled.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowStarterKits()
|
||||
{
|
||||
if (Directory.Exists(Server.MapPath(GlobalSettings.Path.EnsureEndsWith('/') + "install/Legacy")) == false)
|
||||
{
|
||||
InstallationDirectoryNotAvailable.Visible = true;
|
||||
StarterKitNotInstalled.Visible = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var starterkitsctrl = (LoadStarterKits)LoadControl(GlobalSettings.Path.EnsureEndsWith('/') + "install/Legacy/loadStarterKits.ascx");
|
||||
|
||||
ph_starterkits.Controls.Add(starterkitsctrl);
|
||||
|
||||
StarterKitNotInstalled.Visible = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Umbraco.Web.UI.Umbraco.Developer.Packages {
|
||||
|
||||
|
||||
public partial class StarterKits {
|
||||
|
||||
/// <summary>
|
||||
/// JsInclude1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::ClientDependency.Core.Controls.JsInclude JsInclude1;
|
||||
|
||||
/// <summary>
|
||||
/// Panel1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.UmbracoPanel Panel1;
|
||||
|
||||
/// <summary>
|
||||
/// fb control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Feedback fb;
|
||||
|
||||
/// <summary>
|
||||
/// StarterKitNotInstalled control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Pane StarterKitNotInstalled;
|
||||
|
||||
/// <summary>
|
||||
/// ph_starterkits control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.PlaceHolder ph_starterkits;
|
||||
|
||||
/// <summary>
|
||||
/// installationCompleted control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Pane installationCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// InstallationDirectoryNotAvailable control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Pane InstallationDirectoryNotAvailable;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
<%@ Page Language="C#" Title="Submit package" MasterPageFile="../../masterpages/umbracoPage.Master" AutoEventWireup="true" CodeBehind="SubmitPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages.SubmitPackage" %>
|
||||
<%@ Register TagPrefix="cc2" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="footer" runat="server">
|
||||
<script type="text/javascript">
|
||||
var tb_email = document.getElementById('<%= tb_email.ClientID %>');
|
||||
|
||||
if (tb_email.value != "") {
|
||||
onRepoChange();
|
||||
}
|
||||
</script>
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="head" runat="server">
|
||||
<script type="text/javascript">
|
||||
function onRepoChange() {
|
||||
|
||||
var dropdown = document.getElementById('<%= dd_repositories.ClientID %>');
|
||||
var myindex = dropdown.selectedIndex
|
||||
var SelValue = dropdown.options[myindex].value
|
||||
var repoLogin = document.getElementById('<%= pl_repoLogin.ClientID %>');
|
||||
|
||||
if (SelValue != "") {
|
||||
|
||||
var publicRepoHelp = document.getElementById('<%= publicRepoHelp.ClientID %>');
|
||||
var privateRepoHelp = document.getElementById('<%= privateRepoHelp.ClientID %>');
|
||||
|
||||
publicRepoHelp.style.display = 'none';
|
||||
privateRepoHelp.style.display = 'none';
|
||||
|
||||
if (SelValue == "65194810-1f85-11dd-bd0b-0800200c9a66") {
|
||||
publicRepoHelp.style.display = 'block';
|
||||
} else {
|
||||
privateRepoHelp.style.display = 'block';
|
||||
}
|
||||
|
||||
repoLogin.style.display = 'block';
|
||||
|
||||
} else {
|
||||
repoLogin.style.display = 'none';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="body" runat="server">
|
||||
<cc2:UmbracoPanel ID="Panel1" Text="Submit package to repository" runat="server" Width="496px" Height="584px">
|
||||
<br />
|
||||
<cc2:Feedback ID="fb_feedback" runat="server" />
|
||||
<asp:PlaceHolder ID="feedbackControls" runat="server" Visible="false">
|
||||
<br />
|
||||
<p>
|
||||
<button onclick="window.location.href = 'editpackage.aspx?id=<%= Request.QueryString["id"] %>'; return false;">Ok</button>
|
||||
</p>
|
||||
</asp:PlaceHolder>
|
||||
|
||||
<cc2:Pane ID="Pane2" runat="server" Text="Repository">
|
||||
|
||||
<asp:Panel ID="pl_repoChoose" runat="server">
|
||||
<cc2:PropertyPanel runat="server">
|
||||
<p>Choose the repository you want to submit the package to</p>
|
||||
</cc2:PropertyPanel>
|
||||
<cc2:PropertyPanel Text="Repository" runat="server">
|
||||
<asp:DropDownList ID="dd_repositories" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
</asp:Panel>
|
||||
|
||||
<asp:Panel id="pl_repoLogin" style="display: none;" runat="server">
|
||||
<cc2:PropertyPanel ID="PropertyPanel1" runat="server">
|
||||
|
||||
<h3 style="margin-left: 0px; padding-top: 15px;">Please enter your credentials to authenticate your user.</h3>
|
||||
<p runat="server" id="publicRepoHelp" style="display: none">If you do not have a user on the umbraco package repository, you can create one <a href="http://packages.umbraco.org/create-user" target="_blank">here</a>.</p>
|
||||
<p runat="server" id="privateRepoHelp" style="display: none">If you do not have a user on this private repository, contact your repository administrator to gain access</p>
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="PropertyPanel2" runat="server" Text="Email">
|
||||
<asp:TextBox ID="tb_email" runat="server" /> <asp:RequiredFieldValidator ID="RequiredFieldValidator1" ControlToValidate="tb_email" runat="server" ErrorMessage="*" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="PropertyPanel3" runat="server" Text="Password">
|
||||
<asp:TextBox TextMode="Password" ID="tb_password" runat="server" /> <asp:RequiredFieldValidator ControlToValidate="tb_password" runat="server" ErrorMessage="*" />
|
||||
</cc2:PropertyPanel>
|
||||
</asp:Panel>
|
||||
|
||||
</cc2:Pane>
|
||||
|
||||
<cc2:Pane ID="Pane1" runat="server" Text="Documentation (.pdf only)">
|
||||
<cc2:PropertyPanel ID="PropertyPanel4" runat="server">
|
||||
<p>Upload additional documentation for your package to help new users getting started with your package</p>
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="PropertyPanel5" runat="server" Text="Documentation file">
|
||||
<asp:FileUpload ID="fu_doc" runat="server" />
|
||||
<asp:RegularExpressionValidator ID="doc_regex" runat="server" ControlToValidate="fu_doc" ValidationExpression="(.*?)\.(pdf|PDF)$" ErrorMessage="Only .pdf files are accepted" />
|
||||
</cc2:PropertyPanel>
|
||||
</cc2:Pane>
|
||||
|
||||
<asp:PlaceHolder runat="server" ID="submitControls">
|
||||
<br />
|
||||
|
||||
<div class="notice">
|
||||
<p>By clicking "submit package" below you understand that your package will be submitted to a package repository and will in some cases be publicly available to download.</p>
|
||||
<p><strong>Please notice: </strong> only packages with complete read-me, author information and install information gets considered for inclusion.</p>
|
||||
<p>The package administrators group reservers the right to decline packages based on lack of documentation, poorly written readme and missing author information</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<asp:Button ID="bt_submit" runat="server" Text="Submit package" OnClick="submitPackage" /> <em><%= umbraco.ui.Text("or") %></em> <a href="editpackage.aspx?id=<%= Request.QueryString["id"] %>"><%= umbraco.ui.Text("cancel") %></a>
|
||||
</p>
|
||||
</asp:PlaceHolder>
|
||||
|
||||
</cc2:UmbracoPanel>
|
||||
</asp:Content>
|
||||
@@ -39,7 +39,6 @@
|
||||
<asp:TextBox ID="iconUrl" runat="server" Width="230px" CssClass="guiInputText"></asp:TextBox>
|
||||
</cc2:PropertyPanel>
|
||||
<cc2:PropertyPanel runat="server" ID="pp_file" Text="Package file (.zip):">
|
||||
<asp:Button ID="bt_submitButton" runat="server" Text="Submit to repository" Visible="false" />
|
||||
<asp:Literal ID="packageUmbFile" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
<%@ Page Language="C#" MasterPageFile="../../masterpages/umbracoPage.Master" AutoEventWireup="true" CodeBehind="installedPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages.installedPackage" %>
|
||||
<%@ Register TagPrefix="cc2" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
<asp:Content ContentPlaceHolderID="head" runat="server">
|
||||
<script type="text/javascript">
|
||||
function toggleDiv(id, gotoDiv) {
|
||||
var div = document.getElementById(id);
|
||||
|
||||
if (div.style.display == "none")
|
||||
div.style.display = "block";
|
||||
|
||||
else
|
||||
div.style.display = "none";
|
||||
}
|
||||
|
||||
function openDemo(link, id) {
|
||||
UmbClientMgr.openModalWindow("http://packages.umbraco.org/viewPackageData.aspx?id=" + id, link.innerHTML, true, 750, 550)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
.propertyItemheader {
|
||||
width: 250px;
|
||||
}
|
||||
</style>
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="body" runat="server">
|
||||
|
||||
|
||||
<cc2:Tabview ID="Panel1" Text="Installed package" runat="server" Width="496px" Height="584px">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<cc2:Pane ID="pane_meta" runat="server" Text="Package meta data">
|
||||
|
||||
<cc2:PropertyPanel ID="pp_name" runat="server">
|
||||
<asp:Literal ID="lt_packagename" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
<cc2:PropertyPanel ID="pp_version" runat="server">
|
||||
<asp:Literal ID="lt_packageVersion" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
<cc2:PropertyPanel ID="pp_author" runat="server">
|
||||
<asp:Literal ID="lt_packageAuthor" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="pp_documentation" Visible="false" runat="server">
|
||||
<asp:HyperLink id="hl_docLink" Target="_blank" runat="server" />
|
||||
<asp:LinkButton id="lb_demoLink" OnClientClick="" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="pp_repository" Visible="false" runat="server">
|
||||
<asp:HyperLink id="hl_packageRepo" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="pp_readme" runat="server">
|
||||
<div style="position: relative; background: #fff; padding: 3px; border: 1px solid #ccc; width: 400px; white-space: normal !Important; overflow: auto;">
|
||||
<asp:Literal ID="lt_readme" runat="server" /></div>
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
|
||||
</cc2:Pane>
|
||||
|
||||
<cc2:Pane ID="pane_versions" runat="server" Text="Package version history" Visible="false">
|
||||
<cc2:PropertyPanel ID="pp_versions" runat="server">
|
||||
<asp:Repeater ID="rptr_versions" runat="server">
|
||||
<headertemplate><ul></headertemplate>
|
||||
<itemtemplate><li><a href="#"><%# ((umbraco.cms.businesslogic.packager.InstalledPackage)Container.DataItem).Data.Name %></a></li></itemtemplate>
|
||||
<footertemplate></ul></footertemplate>
|
||||
</asp:Repeater>
|
||||
</cc2:PropertyPanel>
|
||||
</cc2:Pane>
|
||||
|
||||
<cc2:Pane ID="pane_upgrade" runat="server" Text="Upgrade package" Visible="false">
|
||||
|
||||
<cc2:PropertyPanel runat="server">
|
||||
<p>
|
||||
<%= umbraco.ui.Text("packager", "packageUpgradeText") %>
|
||||
</p>
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="pp_upgradeInstruction" Text="Upgrade instructions" runat="server">
|
||||
<p>
|
||||
<asp:Literal ID="lt_upgradeReadme" runat="server" />
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<asp:Button ID="bt_gotoUpgrade" Text="Download update from the repository" runat="server" UseSubmitBehavior="false" />
|
||||
</p>
|
||||
</cc2:PropertyPanel>
|
||||
</cc2:Pane>
|
||||
|
||||
<cc2:Pane ID="pane_noItems" Visible="false" runat="server" Text="Uninstaller doesn't contain any items">
|
||||
<div class="guiDialogNormal" style="margin: 10px">
|
||||
|
||||
<%= umbraco.ui.Text("packager", "packageNoItemsText") %>
|
||||
|
||||
<p>
|
||||
<asp:Button ID="bt_deletePackage" OnClick="delPack" runat="server" Text="Remove uninstaller" />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</cc2:Pane>
|
||||
|
||||
|
||||
<cc2:Pane ID="pane_uninstall" runat="server" Text="Uninstall items installed by this package">
|
||||
<p>
|
||||
<%= umbraco.ui.Text("packager", "packageUninstallText") %>
|
||||
</p>
|
||||
|
||||
<cc2:PropertyPanel runat="server" Text="Document Types" ID="pp_docTypes">
|
||||
<asp:CheckBoxList ID="documentTypes" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel runat="server" Text="Templates" ID="pp_templates">
|
||||
<asp:CheckBoxList ID="templates" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel runat="server" Text="Stylesheets" ID="pp_css">
|
||||
<asp:CheckBoxList ID="stylesheets" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel runat="server" Text="Macros" ID="pp_macros">
|
||||
<asp:CheckBoxList ID="macros" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="pp_files" runat="server" Text="Files">
|
||||
<asp:CheckBoxList ID="files" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="pp_di" runat="server" Text="Dictionary Items">
|
||||
<asp:CheckBoxList ID="dictionaryItems" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="pp_dt" runat="server" Text="Data types">
|
||||
<asp:CheckBoxList ID="dataTypes" runat="server" />
|
||||
</cc2:PropertyPanel>
|
||||
|
||||
<cc2:PropertyPanel ID="pp_confirm" runat="server" Text=" ">
|
||||
<asp:Button ID="bt_confirmUninstall" OnClick="confirmUnInstall" OnClientClick="$('#loadingbar').show()" Text="Confirm uninstall" CssClass="btn btn-primary" runat="server" />
|
||||
<div id="loadingbar" style="display: none">
|
||||
<div class="umb-loader-wrapper">
|
||||
<cc2:ProgressBar ID="progbar" runat="server" Title="Please wait..." />
|
||||
</div>
|
||||
</div>
|
||||
</cc2:PropertyPanel>
|
||||
</cc2:Pane>
|
||||
|
||||
<cc2:Pane id="pane_uninstalled" runat="server" Visible="false">
|
||||
|
||||
<div class="alert alert-block">
|
||||
Package uninstall in progress, please wait while the browser is reloaded...
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
//This is all a bit zany with double encoding because we have a URL in a hash (#) url part
|
||||
// but it works and maintains query strings
|
||||
|
||||
var umbPath = "<%=umbraco.GlobalSettings.Path%>";
|
||||
setTimeout(function () {
|
||||
var mainWindow = UmbClientMgr.mainWindow();
|
||||
|
||||
//kill the tree and template cache
|
||||
if (mainWindow.UmbClientMgr) {
|
||||
mainWindow.UmbClientMgr._packageInstalled();
|
||||
}
|
||||
|
||||
var baseUrl = mainWindow.location.href.substr(0, mainWindow.location.href.indexOf("#/developer/framed/"));
|
||||
var framedUrl = baseUrl + "#/developer/framed/";
|
||||
var refreshUrl = framedUrl + encodeURIComponent(encodeURIComponent(umbPath + "/developer/packages/installer.aspx?installing=uninstalled"));
|
||||
|
||||
var redirectUrl = umbPath + "/ClientRedirect.aspx?redirectUrl=" + refreshUrl;
|
||||
|
||||
mainWindow.location.href = redirectUrl;
|
||||
}, 2000);
|
||||
</script>
|
||||
|
||||
|
||||
</cc2:Pane>
|
||||
</cc2:Tabview>
|
||||
</asp:Content>
|
||||
@@ -1,67 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" >
|
||||
<head>
|
||||
<title>Repo proxy</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
//This is a stupid way of parsing a uri
|
||||
//https://gist.github.com/jlong/2428561
|
||||
|
||||
try {
|
||||
|
||||
var parser = document.createElement('a');
|
||||
parser.href = window.location.search.substring(1);
|
||||
|
||||
// This next line may seem redundant but is required to get around a bug in IE
|
||||
// that doesn't set the parser.hostname or parser.protocol correctly for relative URLs.
|
||||
// see https://gist.github.com/jlong/2428561#gistcomment-1461205
|
||||
parser.href = parser.href;
|
||||
|
||||
// => "http:"
|
||||
if (parser.protocol && (parser.protocol.toLowerCase() != "http:" && parser.protocol.toLowerCase() != "https:")) {
|
||||
throw "invalid protocol";
|
||||
};
|
||||
|
||||
// => "example.com"
|
||||
if (!parser.hostname || parser.hostname == "") {
|
||||
throw "invalid hostname";
|
||||
}
|
||||
|
||||
//parser.port; // => "3000"
|
||||
|
||||
// => "/pathname/"
|
||||
if (!parser.pathname || ((parser.pathname.length - parser.pathname.toLowerCase().indexOf("/developer/packages/installer.aspx")) != "/developer/packages/installer.aspx".length))
|
||||
{
|
||||
throw "invalid pathname";
|
||||
}
|
||||
|
||||
// => "?search=test"
|
||||
if (!parser.search || parser.search.toLowerCase().indexOf("?repoguid") != 0) {
|
||||
throw "invalid search";
|
||||
}
|
||||
|
||||
// => "#hash"
|
||||
if (parser.hash && parser.hash != "") {
|
||||
throw "invalid hash";
|
||||
}
|
||||
|
||||
//parser.host; // => "example.com:3000"
|
||||
|
||||
if (!top.right) {
|
||||
throw "invalid document";
|
||||
}
|
||||
|
||||
top.right.document.location = window.location.search.substring(1);
|
||||
|
||||
} catch (e) {
|
||||
alert(e);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -27,7 +27,7 @@
|
||||
<script type="text/javascript" language="javascript">
|
||||
jQuery(document).ready(function() {
|
||||
jQuery("#<%=JTree.ClientID%>").PermissionsEditor({
|
||||
userId: <%=Request.QueryString["id"] %>,
|
||||
userId: <%=Request.CleanForXss("id") %>,
|
||||
pPanelSelector: "#permissionsPanel",
|
||||
replacePChkBoxSelector: "#chkChildPermissions"});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -11,9 +12,14 @@ using umbraco.BusinessLogic;
|
||||
using umbraco.cms.businesslogic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Publishing;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
using Content = Umbraco.Core.Models.Content;
|
||||
using ApplicationTree = Umbraco.Core.Models.ApplicationTree;
|
||||
using DeleteEventArgs = umbraco.cms.businesslogic.DeleteEventArgs;
|
||||
@@ -787,14 +793,39 @@ namespace Umbraco.Web.Cache
|
||||
/// </summary>
|
||||
/// <param name="events"></param>
|
||||
internal static void HandleEvents(IEnumerable<IEventDefinition> events)
|
||||
{
|
||||
foreach (var e in events)
|
||||
{
|
||||
//TODO: We should remove this in v8, this is a backwards compat hack and is needed because when we are using Deploy, the events will be raised on a background
|
||||
//thread which means that cache refreshers will also execute on a background thread and in many cases developers may be using UmbracoContext.Current in their
|
||||
//cache refresher handlers, so before we execute all of the events, we'll ensure a context
|
||||
UmbracoContext tempContext = null;
|
||||
if (UmbracoContext.Current == null)
|
||||
{
|
||||
var handler = FindHandler(e);
|
||||
if (handler == null) continue;
|
||||
|
||||
handler.Invoke(null, new[] { e.Sender, e.Args });
|
||||
var httpContext = new HttpContextWrapper(HttpContext.Current ?? new HttpContext(new SimpleWorkerRequest("temp.aspx", "", new StringWriter())));
|
||||
tempContext = UmbracoContext.EnsureContext(
|
||||
httpContext,
|
||||
ApplicationContext.Current,
|
||||
new WebSecurity(httpContext, ApplicationContext.Current),
|
||||
UmbracoConfig.For.UmbracoSettings(),
|
||||
UrlProviderResolver.Current.Providers,
|
||||
true);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var e in events)
|
||||
{
|
||||
var handler = FindHandler(e);
|
||||
if (handler == null) continue;
|
||||
|
||||
handler.Invoke(null, new[] { e.Sender, e.Args });
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (tempContext != null)
|
||||
tempContext.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -22,6 +22,7 @@ using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
@@ -224,6 +225,9 @@ namespace Umbraco.Web.Editors
|
||||
{"gridConfig", Url.Action("GetGridConfig", "BackOffice")},
|
||||
{"serverVarsJs", Url.Action("Application", "BackOffice")},
|
||||
//API URLs
|
||||
{
|
||||
"packagesRestApiBaseUrl", UmbracoConfig.For.UmbracoSettings().PackageRepositories.GetDefault().RestApiUrl
|
||||
},
|
||||
{
|
||||
"redirectUrlManagementApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<RedirectUrlManagementController>(
|
||||
controller => controller.GetEnableState())
|
||||
|
||||
@@ -58,17 +58,25 @@ namespace Umbraco.Web.Editors
|
||||
[HttpPost]
|
||||
public IHttpActionResult Uninstall(int packageId)
|
||||
{
|
||||
var pack = InstalledPackage.GetById(packageId);
|
||||
if (pack == null) return NotFound();
|
||||
|
||||
PerformUninstall(pack);
|
||||
|
||||
//now get all other packages by this name since we'll uninstall all versions
|
||||
foreach (var installed in InstalledPackage.GetAllInstalledPackages()
|
||||
.Where(x => x.Data.Name == pack.Data.Name && x.Data.Id != pack.Data.Id))
|
||||
try
|
||||
{
|
||||
//remove from teh xml
|
||||
installed.Delete(Security.GetUserId());
|
||||
var pack = InstalledPackage.GetById(packageId);
|
||||
if (pack == null) return NotFound();
|
||||
|
||||
PerformUninstall(pack);
|
||||
|
||||
//now get all other packages by this name since we'll uninstall all versions
|
||||
foreach (var installed in InstalledPackage.GetAllInstalledPackages()
|
||||
.Where(x => x.Data.Name == pack.Data.Name && x.Data.Id != pack.Data.Id))
|
||||
{
|
||||
//remove from teh xml
|
||||
installed.Delete(Security.GetUserId());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error<PackageInstallController>("Failed to uninstall.", e);
|
||||
throw;
|
||||
}
|
||||
|
||||
return Ok();
|
||||
@@ -176,7 +184,7 @@ namespace Umbraco.Web.Editors
|
||||
pack.Save();
|
||||
|
||||
// uninstall actions
|
||||
//TODO: We should probably report errors to the UI!!
|
||||
//TODO: We should probably report errors to the UI!!
|
||||
// This never happened before though, but we should do something now
|
||||
if (pack.Data.Actions.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
@@ -185,7 +193,7 @@ namespace Umbraco.Web.Editors
|
||||
var actionsXml = new XmlDocument();
|
||||
actionsXml.LoadXml("<Actions>" + pack.Data.Actions + "</Actions>");
|
||||
|
||||
LogHelper.Debug<installedPackage>("executing undo actions: {0}", () => actionsXml.OuterXml);
|
||||
LogHelper.Debug<PackageInstallController>("executing undo actions: {0}", () => actionsXml.OuterXml);
|
||||
|
||||
foreach (XmlNode n in actionsXml.DocumentElement.SelectNodes("//Action"))
|
||||
{
|
||||
@@ -196,13 +204,13 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<installedPackage>("An error occurred running undo actions", ex);
|
||||
LogHelper.Error<PackageInstallController>("An error occurred running undo actions", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<installedPackage>("An error occurred running undo actions", ex);
|
||||
LogHelper.Error<PackageInstallController>("An error occurred running undo actions", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,11 +479,7 @@ namespace Umbraco.Web.Editors
|
||||
string path = Path.Combine("packages", packageGuid + ".umb");
|
||||
if (File.Exists(IOHelper.MapPath(Path.Combine(SystemDirectories.Data, path))) == false)
|
||||
{
|
||||
//our repo guid
|
||||
using (var our = Repository.getByGuid("65194810-1f85-11dd-bd0b-0800200c9a66"))
|
||||
{
|
||||
path = our.fetch(packageGuid, Security.CurrentUser.Id);
|
||||
}
|
||||
path = Services.PackagingService.FetchPackageFile(Guid.Parse(packageGuid), UmbracoVersion.Current, Security.GetUserId());
|
||||
}
|
||||
|
||||
var model = new LocalPackageInstallModel
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Web.Http;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using umbraco;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Web.Install.Models;
|
||||
using Umbraco.Web.WebApi;
|
||||
|
||||
@@ -57,23 +58,15 @@ namespace Umbraco.Web.Install.Controllers
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public HttpResponseMessage DownloadPackageFiles(InstallPackageModel model)
|
||||
{
|
||||
var repo = global::umbraco.cms.businesslogic.packager.repositories.Repository.getByGuid(RepoGuid);
|
||||
if (repo == null)
|
||||
{
|
||||
return Json(
|
||||
new {success = false, error = "No repository found with id " + RepoGuid},
|
||||
HttpStatusCode.OK);
|
||||
}
|
||||
if (repo.HasConnection() == false)
|
||||
{
|
||||
return Json(
|
||||
new { success = false, error = "cannot_connect" },
|
||||
HttpStatusCode.OK);
|
||||
}
|
||||
var installer = new global::umbraco.cms.businesslogic.packager.Installer(UmbracoContext.Current.Security.CurrentUser.Id);
|
||||
{
|
||||
var packageFile = _applicationContext.Services.PackagingService.FetchPackageFile(
|
||||
model.KitGuid,
|
||||
UmbracoVersion.Current,
|
||||
UmbracoContext.Current.Security.CurrentUser.Id);
|
||||
|
||||
var tempFile = installer.Import(repo.fetch(model.KitGuid.ToString(), UmbracoContext.Current.Security.CurrentUser.Id));
|
||||
var installer = new global::umbraco.cms.businesslogic.packager.Installer(UmbracoContext.Current.Security.CurrentUser.Id);
|
||||
|
||||
var tempFile = installer.Import(packageFile);
|
||||
installer.LoadConfig(tempFile);
|
||||
var pId = installer.CreateManifest(tempFile, model.KitGuid.ToString(), RepoGuid);
|
||||
return Json(new
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Umbraco.Web.Install
|
||||
new DatabaseConfigureStep(_umbContext.Application),
|
||||
new DatabaseInstallStep(_umbContext.Application),
|
||||
new DatabaseUpgradeStep(_umbContext.Application),
|
||||
new StarterKitDownloadStep(_umbContext.Application),
|
||||
new StarterKitDownloadStep(_umbContext.Application, _umbContext.Security),
|
||||
new StarterKitInstallStep(_umbContext.Application, _umbContext.HttpContext),
|
||||
new StarterKitCleanupStep(_umbContext.Application),
|
||||
new SetUmbracoVersionStep(_umbContext.Application, _umbContext.HttpContext),
|
||||
|
||||
@@ -4,7 +4,9 @@ using System.Linq;
|
||||
using System.Web;
|
||||
using umbraco.cms.businesslogic.packager;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Web.Install.Models;
|
||||
using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Web.Install.InstallSteps
|
||||
{
|
||||
@@ -13,10 +15,12 @@ namespace Umbraco.Web.Install.InstallSteps
|
||||
internal class StarterKitDownloadStep : InstallSetupStep<Guid?>
|
||||
{
|
||||
private readonly ApplicationContext _applicationContext;
|
||||
private readonly WebSecurity _security;
|
||||
|
||||
public StarterKitDownloadStep(ApplicationContext applicationContext)
|
||||
public StarterKitDownloadStep(ApplicationContext applicationContext, WebSecurity security)
|
||||
{
|
||||
_applicationContext = applicationContext;
|
||||
_security = security;
|
||||
}
|
||||
|
||||
private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66";
|
||||
@@ -50,19 +54,13 @@ namespace Umbraco.Web.Install.InstallSteps
|
||||
}
|
||||
|
||||
private Tuple<string, int> DownloadPackageFiles(Guid kitGuid)
|
||||
{
|
||||
var repo = global::umbraco.cms.businesslogic.packager.repositories.Repository.getByGuid(RepoGuid);
|
||||
if (repo == null)
|
||||
{
|
||||
throw new InstallException("No repository found with id " + RepoGuid);
|
||||
}
|
||||
if (repo.HasConnection() == false)
|
||||
{
|
||||
throw new InstallException("Cannot connect to repository");
|
||||
}
|
||||
{
|
||||
var installer = new Installer();
|
||||
|
||||
var tempFile = installer.Import(repo.fetch(kitGuid.ToString()));
|
||||
//Go get the package file from the package repo
|
||||
var packageFile = _applicationContext.Services.PackagingService.FetchPackageFile(kitGuid, UmbracoVersion.Current, _security.GetUserId());
|
||||
|
||||
var tempFile = installer.Import(packageFile);
|
||||
installer.LoadConfig(tempFile);
|
||||
var pId = installer.CreateManifest(tempFile, kitGuid.ToString(), RepoGuid);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(x => x.Snippet, exp => exp.Ignore());
|
||||
|
||||
config.CreateMap<CodeFileDisplay, IPartialView>()
|
||||
.ForMember(x => x.DeletedDate, exp => exp.Ignore())
|
||||
.ForMember(x => x.Id, exp => exp.Ignore())
|
||||
.ForMember(x => x.Key, exp => exp.Ignore())
|
||||
.ForMember(x => x.Path, exp => exp.Ignore())
|
||||
@@ -40,6 +41,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(x => x.HasIdentity, exp => exp.Ignore());
|
||||
|
||||
config.CreateMap<CodeFileDisplay, Script>()
|
||||
.ForMember(x => x.DeletedDate, exp => exp.Ignore())
|
||||
.ForMember(x => x.Id, exp => exp.Ignore())
|
||||
.ForMember(x => x.Key, exp => exp.Ignore())
|
||||
.ForMember(x => x.Path, exp => exp.Ignore())
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(type => type.Key, expression => expression.Ignore())
|
||||
.ForMember(type => type.CreateDate, expression => expression.Ignore())
|
||||
.ForMember(type => type.UpdateDate, expression => expression.Ignore())
|
||||
.ForMember(type => type.DeletedDate, expression => expression.Ignore())
|
||||
.ForMember(type => type.HasIdentity, expression => expression.Ignore());
|
||||
|
||||
config.CreateMap<DocumentTypeSave, IContentType>()
|
||||
@@ -72,7 +73,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
config.CreateMap<MediaTypeSave, IMediaType>()
|
||||
//do the base mapping
|
||||
.MapBaseContentTypeSaveToEntity<MediaTypeSave, PropertyTypeBasic, IMediaType>(applicationContext)
|
||||
.ConstructUsing((source) => new MediaType(source.ParentId))
|
||||
.ConstructUsing((source) => new MediaType(source.ParentId))
|
||||
.AfterMap((source, dest) =>
|
||||
{
|
||||
ContentTypeModelMapperExtensions.AfterMapMediaTypeSaveToEntity(source, dest, applicationContext);
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(dest => dest.HasIdentity, map => map.Ignore())
|
||||
.ForMember(dest => dest.CreateDate, map => map.Ignore())
|
||||
.ForMember(dest => dest.UpdateDate, map => map.Ignore())
|
||||
.ForMember(dest => dest.DeletedDate, map => map.Ignore())
|
||||
.ForMember(dest => dest.PropertyTypes, map => map.Ignore());
|
||||
}
|
||||
|
||||
@@ -175,6 +176,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
//These get persisted as part of the saving procedure, nothing to do with the display model
|
||||
.ForMember(dto => dto.CreateDate, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.UpdateDate, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.DeletedDate, expression => expression.Ignore())
|
||||
|
||||
.ForMember(dto => dto.AllowedAsRoot, expression => expression.MapFrom(display => display.AllowAsRoot))
|
||||
.ForMember(dto => dto.CreatorId, expression => expression.Ignore())
|
||||
|
||||
@@ -108,6 +108,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(x => x.Level, expression => expression.Ignore())
|
||||
.ForMember(x => x.SortOrder, expression => expression.Ignore())
|
||||
.ForMember(x => x.CreateDate, expression => expression.Ignore())
|
||||
.ForMember(x => x.DeletedDate, expression => expression.Ignore())
|
||||
.ForMember(x => x.UpdateDate, expression => expression.Ignore());
|
||||
|
||||
//Converts a property editor to a new list of pre-value fields - used when creating a new data type or changing a data type with new pre-vals
|
||||
|
||||
@@ -55,8 +55,9 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(member => member.SortOrder, expression => expression.Ignore())
|
||||
.ForMember(member => member.AdditionalData, expression => expression.Ignore())
|
||||
.ForMember(member => member.FailedPasswordAttempts, expression => expression.Ignore())
|
||||
//TODO: Support these eventually
|
||||
.ForMember(member => member.PasswordQuestion, expression => expression.Ignore())
|
||||
.ForMember(member => member.DeletedDate, expression => expression.Ignore())
|
||||
//TODO: Support these eventually
|
||||
.ForMember(member => member.PasswordQuestion, expression => expression.Ignore())
|
||||
.ForMember(member => member.RawPasswordAnswerValue, expression => expression.Ignore());
|
||||
|
||||
//FROM IMember TO MediaItemDisplay
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(x => x.Notifications, exp => exp.Ignore());
|
||||
|
||||
config.CreateMap<TemplateDisplay, Template>()
|
||||
.ForMember(x => x.DeletedDate, exp => exp.Ignore())
|
||||
.ForMember(x => x.Key, exp => exp.Ignore())
|
||||
.ForMember(x => x.Path, exp => exp.Ignore())
|
||||
.ForMember(x => x.CreateDate, exp => exp.Ignore())
|
||||
|
||||
@@ -13,10 +13,39 @@ namespace Umbraco.Web.Mvc
|
||||
{
|
||||
public abstract class UmbracoVirtualNodeRouteHandler : IRouteHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the UmbracoContext for this route handler
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default this uses the UmbracoContext singleton, this could be overridden to check for null in the case
|
||||
/// that this handler is used for a request where an UmbracoContext is not created by default see http://issues.umbraco.org/issue/U4-9384
|
||||
/// <example>
|
||||
/// <![CDATA[
|
||||
/// protected override UmbracoContext GetUmbracoContext(RequestContext requestContext)
|
||||
/// {
|
||||
/// var ctx = base.GetUmbracoContext(requestContext);
|
||||
/// //check if context is null, we know it will be null if we are dealing with a request that
|
||||
/// //has an extension and by default no Umb ctx is created for the request
|
||||
/// if (ctx == null) {
|
||||
/// //TODO: Here you can EnsureContext , please note that the requestContext is passed in
|
||||
/// //therefore your should refrain from using other singletons like HttpContext.Current since
|
||||
/// //you will already have a reference to it. Also if you need an ApplicationContext you should
|
||||
/// //pass this in via a ctor instead of using the ApplicationContext.Current singleton.
|
||||
/// }
|
||||
/// return ctx;
|
||||
/// }
|
||||
/// ]]>
|
||||
/// </example>
|
||||
/// </remarks>
|
||||
protected virtual UmbracoContext GetUmbracoContext(RequestContext requestContext)
|
||||
{
|
||||
return UmbracoContext.Current;
|
||||
}
|
||||
|
||||
public IHttpHandler GetHttpHandler(RequestContext requestContext)
|
||||
{
|
||||
var umbracoContext = UmbracoContext.Current;
|
||||
|
||||
var umbracoContext = GetUmbracoContext(requestContext);
|
||||
|
||||
var found = FindContent(requestContext, umbracoContext);
|
||||
if (found == null) return new NotFoundHandler();
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
.GetPreValuesByDataTypeId(property.PropertyType.DataTypeDefinitionId).FirstOrDefault();
|
||||
var crops = string.IsNullOrWhiteSpace(config) ? "[]" : config;
|
||||
src = svalue;
|
||||
property.Value = "{src: '" + svalue + "', crops: " + crops + "}";
|
||||
property.Value = "{\"src\": \"" + svalue + "\", \"crops\": " + crops + "}";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ using Examine;
|
||||
using Examine.LuceneEngine.SearchCriteria;
|
||||
using Examine.Providers;
|
||||
using Lucene.Net.Documents;
|
||||
using Lucene.Net.Store;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Dynamics;
|
||||
@@ -173,6 +174,11 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
// the manager will return the singleton without throwing initialization errors, however if examine isn't configured correctly a null
|
||||
// reference error will occur because the examine settings are null.
|
||||
}
|
||||
catch (AlreadyClosedException)
|
||||
{
|
||||
//If the app domain is shutting down and the site is under heavy load the index reader will be closed and it really cannot
|
||||
//be re-opened since the app domain is shutting down. In this case we have no option but to try to load the data from the db.
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -211,13 +217,23 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
var result = searchProvider.Search(filter.Compile()).FirstOrDefault();
|
||||
if (result != null) return ConvertFromSearchResult(result);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Currently examine is throwing FileNotFound exceptions when we have a loadbalanced filestore and a node is published in umbraco
|
||||
//See this thread: http://examine.cdodeplex.com/discussions/264341
|
||||
//Catch the exception here for the time being, and just fallback to GetMedia
|
||||
//TODO: Need to fix examine in LB scenarios!
|
||||
LogHelper.Error<PublishedMediaCache>("Could not load data from Examine index for media", ex);
|
||||
if (ex is FileNotFoundException)
|
||||
{
|
||||
//Currently examine is throwing FileNotFound exceptions when we have a loadbalanced filestore and a node is published in umbraco
|
||||
//See this thread: http://examine.cdodeplex.com/discussions/264341
|
||||
//Catch the exception here for the time being, and just fallback to GetMedia
|
||||
//TODO: Need to fix examine in LB scenarios!
|
||||
LogHelper.Error<PublishedMediaCache>("Could not load data from Examine index for media", ex);
|
||||
}
|
||||
else if (ex is AlreadyClosedException)
|
||||
{
|
||||
//If the app domain is shutting down and the site is under heavy load the index reader will be closed and it really cannot
|
||||
//be re-opened since the app domain is shutting down. In this case we have no option but to try to load the data from the db.
|
||||
LogHelper.Error<PublishedMediaCache>("Could not load data from Examine index for media, the app domain is most likely in a shutdown state", ex);
|
||||
}
|
||||
else throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,11 +148,6 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
}
|
||||
}
|
||||
|
||||
public override Task RunAsync(CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool IsAsync
|
||||
{
|
||||
get { return false; }
|
||||
|
||||
@@ -540,7 +540,7 @@ namespace Umbraco.Web
|
||||
var filtered = dynamicDocumentList.Where<DynamicPublishedContent>(predicate);
|
||||
return filtered.Count() == 1;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region AsDynamic
|
||||
@@ -806,7 +806,7 @@ namespace Umbraco.Web
|
||||
public static HtmlString IsOdd(this IPublishedContent content, string valueIfTrue, string valueIfFalse)
|
||||
{
|
||||
return new HtmlString(content.IsOdd() ? valueIfTrue : valueIfFalse);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -836,7 +836,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
return content.IsNotEqual(other, valueIfTrue, string.Empty);
|
||||
}
|
||||
|
||||
|
||||
public static HtmlString IsNotEqual(this IPublishedContent content, IPublishedContent other, string valueIfTrue, string valueIfFalse)
|
||||
{
|
||||
return new HtmlString(content.IsNotEqual(other) ? valueIfTrue : valueIfFalse);
|
||||
@@ -1125,7 +1125,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
return content.Ancestors<T>(maxLevel).FirstOrDefault();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor.
|
||||
/// </summary>
|
||||
@@ -1186,7 +1186,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
return content.AncestorsOrSelf<T>(maxLevel).FirstOrDefault();
|
||||
}
|
||||
|
||||
|
||||
internal static IEnumerable<IPublishedContent> AncestorsOrSelf(this IPublishedContent content, bool orSelf, Func<IPublishedContent, bool> func)
|
||||
{
|
||||
var ancestorsOrSelf = content.EnumerateAncestors(orSelf);
|
||||
@@ -1237,7 +1237,7 @@ namespace Umbraco.Web
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return parentNodes.SelectMany(x => x.DescendantsOrSelf<T>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// as per XPath 1.0 specs §2.2,
|
||||
@@ -1285,7 +1285,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
return content.Descendants(level).OfType<T>();
|
||||
}
|
||||
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content)
|
||||
{
|
||||
return content.DescendantsOrSelf(true, null);
|
||||
@@ -1366,7 +1366,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
return content.DescendantOrSelf(level) as T;
|
||||
}
|
||||
|
||||
|
||||
internal static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content, bool orSelf, Func<IPublishedContent, bool> func)
|
||||
{
|
||||
return content.EnumerateDescendants(orSelf).Where(x => func == null || func(x));
|
||||
@@ -1390,7 +1390,7 @@ namespace Umbraco.Web
|
||||
foreach (var child2 in child.EnumerateDescendants())
|
||||
yield return child2;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: following-sibling, preceding-sibling, following, preceding + pseudo-axes up, down, next, previous
|
||||
@@ -1413,8 +1413,8 @@ namespace Umbraco.Web
|
||||
|
||||
public static IPublishedContent Up(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return string.IsNullOrEmpty(contentTypeAlias)
|
||||
? content.Parent
|
||||
return string.IsNullOrEmpty(contentTypeAlias)
|
||||
? content.Parent
|
||||
: content.Ancestor(contentTypeAlias);
|
||||
}
|
||||
|
||||
@@ -1799,13 +1799,19 @@ namespace Umbraco.Web
|
||||
return content.Children<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the content in a DataTable.
|
||||
/// </summary>
|
||||
public static IPublishedContent FirstChild<T>(this IPublishedContent content, Func<IPublishedContent, bool> predicate)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Children<T>().FirstOrDefault(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the content in a DataTable.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="contentTypeAliasFilter">An optional content type alias.</param>
|
||||
/// <returns>The children of the content.</returns>
|
||||
public static DataTable ChildrenAsTable(this IPublishedContent content, string contentTypeAliasFilter = "")
|
||||
public static DataTable ChildrenAsTable(this IPublishedContent content, string contentTypeAliasFilter = "")
|
||||
{
|
||||
return GenerateDataTable(content, contentTypeAliasFilter);
|
||||
}
|
||||
@@ -1824,7 +1830,7 @@ namespace Umbraco.Web
|
||||
: null
|
||||
: content.Children.FirstOrDefault(x => x.DocumentTypeAlias == contentTypeAliasFilter);
|
||||
if (firstNode == null)
|
||||
return new DataTable(); //no children found
|
||||
return new DataTable(); //no children found
|
||||
|
||||
//use new utility class to create table so that we don't have to maintain code in many places, just one
|
||||
var dt = Core.DataTableExtensions.GenerateDataTable(
|
||||
@@ -1964,7 +1970,7 @@ namespace Umbraco.Web
|
||||
public static CultureInfo GetCulture(this IPublishedContent content, Uri current = null)
|
||||
{
|
||||
return Models.ContentExtensions.GetCulture(UmbracoContext.Current,
|
||||
ApplicationContext.Current.Services.DomainService,
|
||||
ApplicationContext.Current.Services.DomainService,
|
||||
ApplicationContext.Current.Services.LocalizationService,
|
||||
ApplicationContext.Current.Services.ContentService,
|
||||
content.Id, content.Path,
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Umbraco.Web.Scheduling
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the managed tasks.</typeparam>
|
||||
/// <remarks>The interface is not complete and exists only to have the contravariance on T.</remarks>
|
||||
internal interface IBackgroundTaskRunner<in T> : IDisposable, IRegisteredObject
|
||||
public interface IBackgroundTaskRunner<in T> : IDisposable, IRegisteredObject
|
||||
where T : class, IBackgroundTask
|
||||
{
|
||||
bool IsCompleted { get; }
|
||||
|
||||
@@ -20,11 +20,6 @@ namespace Umbraco.Web.Scheduling
|
||||
_appContext = appContext;
|
||||
}
|
||||
|
||||
public override bool PerformRun()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task<bool> PerformRunAsync(CancellationToken token)
|
||||
{
|
||||
if (_appContext == null) return true; // repeat...
|
||||
@@ -69,10 +64,5 @@ namespace Umbraco.Web.Scheduling
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool RunsOnShutdown
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,14 @@ using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Scheduling
|
||||
{
|
||||
internal abstract class LatchedBackgroundTaskBase : DisposableObject, ILatchedBackgroundTask
|
||||
/// <summary>
|
||||
/// Provides a base class for latched background tasks.
|
||||
/// </summary>
|
||||
/// <remarks>Implement by overriding Run or RunAsync and then IsAsync accordingly,
|
||||
/// depending on whether the task is implemented as a sync or async method, and then
|
||||
/// optionnally overriding RunsOnShutdown, to indicate whether the latched task should run
|
||||
/// immediately on shutdown, or just be abandonned (default).</remarks>
|
||||
public abstract class LatchedBackgroundTaskBase : DisposableObject, ILatchedBackgroundTask
|
||||
{
|
||||
private TaskCompletionSource<bool> _latch;
|
||||
|
||||
@@ -17,12 +24,18 @@ namespace Umbraco.Web.Scheduling
|
||||
/// <summary>
|
||||
/// Implements IBackgroundTask.Run().
|
||||
/// </summary>
|
||||
public abstract void Run();
|
||||
public virtual void Run()
|
||||
{
|
||||
throw new NotSupportedException("This task cannot run synchronously.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements IBackgroundTask.RunAsync().
|
||||
/// </summary>
|
||||
public abstract Task RunAsync(CancellationToken token);
|
||||
public virtual Task RunAsync(CancellationToken token)
|
||||
{
|
||||
throw new NotSupportedException("This task cannot run asynchronously.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the background task can run asynchronously.
|
||||
@@ -49,7 +62,7 @@ namespace Umbraco.Web.Scheduling
|
||||
_latch = new TaskCompletionSource<bool>();
|
||||
}
|
||||
|
||||
public abstract bool RunsOnShutdown { get; }
|
||||
public virtual bool RunsOnShutdown { get { return false; } }
|
||||
|
||||
// the task is going to be disposed after execution,
|
||||
// unless it is latched again, thus indicating it wants to
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user