diff --git a/.hgtags b/.hgtags
index 48a3450e6e..6daa26e240 100644
--- a/.hgtags
+++ b/.hgtags
@@ -13,3 +13,6 @@ de73e687ddf6086ed52b6554676c1632865d07f2 Release-4.9.0
8d7d8609e2e4b971da99cd97f72132ce85ce3333 Release-4.9.1
f6da531fbb4c251ff61d314e2a7effb13c71e74a Release-4.10.0
20e4dff821d8ac2527a5353618fa1a23ea1d8b34 Release-4.11.0
+7f827760cb49d749616859f528d19dde64807947 Release-4.11.1
+7f827760cb49d749616859f528d19dde64807947 Release-4.11.1
+6eb5f2fb5a88aa29ea544499df9160a1b31b5638 Release-4.11.1
diff --git a/src/Umbraco.Core/PluginManager.cs b/src/Umbraco.Core/PluginManager.cs
index b0de40416b..213e2b3402 100644
--- a/src/Umbraco.Core/PluginManager.cs
+++ b/src/Umbraco.Core/PluginManager.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -7,14 +6,10 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
-using System.Web.Caching;
using System.Web.Compilation;
-using System.Xml;
using System.Xml.Linq;
-using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
-using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using umbraco.interfaces;
using File = System.IO.File;
@@ -22,754 +17,744 @@ using File = System.IO.File;
namespace Umbraco.Core
{
- ///
- /// Used to resolve all plugin types and cache them and is also used to instantiate plugin types
- ///
- ///
- ///
- /// This class should be used to resolve all plugin types, the TypeFinder should not be used directly!
- ///
- /// This class can expose extension methods to resolve custom plugins
- ///
- /// Before this class resolves any plugins it checks if the hash has changed for the DLLs in the /bin folder, if it hasn't
- /// it will use the cached resolved plugins that it has already found which means that no assembly scanning is necessary. This leads
- /// to much faster startup times.
- ///
- internal class PluginManager
- {
- private readonly ApplicationContext _appContext;
+ ///
+ /// Used to resolve all plugin types and cache them and is also used to instantiate plugin types
+ ///
+ ///
+ ///
+ /// This class should be used to resolve all plugin types, the TypeFinder should not be used directly!
+ ///
+ /// This class can expose extension methods to resolve custom plugins
+ ///
+ /// Before this class resolves any plugins it checks if the hash has changed for the DLLs in the /bin folder, if it hasn't
+ /// it will use the cached resolved plugins that it has already found which means that no assembly scanning is necessary. This leads
+ /// to much faster startup times.
+ ///
+ internal class PluginManager
+ {
+ private readonly ApplicationContext _appContext;
- ///
- /// Creates a new PluginManager with an ApplicationContext instance which ensures that the plugin xml
- /// file is cached temporarily until app startup completes.
- ///
- ///
- ///
- internal PluginManager(ApplicationContext appContext, bool detectBinChanges = true)
- : this(detectBinChanges)
- {
- if (appContext == null) throw new ArgumentNullException("appContext");
- _appContext = appContext;
- }
+ ///
+ /// Creates a new PluginManager with an ApplicationContext instance which ensures that the plugin xml
+ /// file is cached temporarily until app startup completes.
+ ///
+ ///
+ ///
+ internal PluginManager(ApplicationContext appContext, bool detectBinChanges = true)
+ : this(detectBinChanges)
+ {
+ if (appContext == null) throw new ArgumentNullException("appContext");
+ _appContext = appContext;
+ }
- ///
- /// Creates a new PluginManager
- ///
- ///
- /// If true will detect changes in the /bin folder and therefor load plugins from the
- /// cached plugins file if one is found. If false will never use the cache file for plugins
- ///
- internal PluginManager(bool detectCodeChanges = true)
- {
- _tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
- //create the folder if it doesn't exist
- if (!Directory.Exists(_tempFolder))
- {
- Directory.CreateDirectory(_tempFolder);
- }
+ ///
+ /// Creates a new PluginManager
+ ///
+ ///
+ /// If true will detect changes in the /bin folder and therefor load plugins from the
+ /// cached plugins file if one is found. If false will never use the cache file for plugins
+ ///
+ internal PluginManager(bool detectCodeChanges = true)
+ {
+ _tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
+ //create the folder if it doesn't exist
+ if (!Directory.Exists(_tempFolder))
+ {
+ Directory.CreateDirectory(_tempFolder);
+ }
- //this is a check for legacy changes, before we didn't store the TypeResolutionKind in the file which was a mistake,
- //so we need to detect if the old file is there without this attribute, if it is then we delete it
- if (DetectLegacyPluginListFile())
- {
- var filePath = GetPluginListFilePath();
- File.Delete(filePath);
- }
+ //this is a check for legacy changes, before we didn't store the TypeResolutionKind in the file which was a mistake,
+ //so we need to detect if the old file is there without this attribute, if it is then we delete it
+ if (DetectLegacyPluginListFile())
+ {
+ var filePath = GetPluginListFilePath();
+ File.Delete(filePath);
+ }
- if (detectCodeChanges)
- {
- //first check if the cached hash is 0, if it is then we ne
- //do the check if they've changed
- HaveAssembliesChanged = (CachedAssembliesHash != CurrentAssembliesHash) || CachedAssembliesHash == 0;
- //if they have changed, we need to write the new file
- if (HaveAssembliesChanged)
- {
- WriteCachePluginsHash();
- }
- }
- else
- {
- //always set to true if we're not detecting (generally only for testing)
- HaveAssembliesChanged = true;
- }
-
- }
+ if (detectCodeChanges)
+ {
+ //first check if the cached hash is 0, if it is then we ne
+ //do the check if they've changed
+ HaveAssembliesChanged = (CachedAssembliesHash != CurrentAssembliesHash) || CachedAssembliesHash == 0;
+ //if they have changed, we need to write the new file
+ if (HaveAssembliesChanged)
+ {
+ WriteCachePluginsHash();
+ }
+ }
+ else
+ {
+ //always set to true if we're not detecting (generally only for testing)
+ HaveAssembliesChanged = true;
+ }
- static PluginManager _resolver;
- static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
- private readonly string _tempFolder;
- private long _cachedAssembliesHash = -1;
- private long _currentAssembliesHash = -1;
+ }
- ///
- /// We will ensure that no matter what, only one of these is created, this is to ensure that caching always takes place
- ///
- ///
- /// The setter is generally only used for unit tests
- ///
- internal static PluginManager Current
- {
- get
- {
- using (var l = new UpgradeableReadLock(Lock))
- {
- if (_resolver == null)
- {
- l.UpgradeToWriteLock();
- _resolver = ApplicationContext.Current == null
- ? new PluginManager()
- : new PluginManager(ApplicationContext.Current);
- }
- return _resolver;
- }
- }
- set { _resolver = value; }
- }
+ static PluginManager _resolver;
+ static readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
+ private readonly string _tempFolder;
+ private long _cachedAssembliesHash = -1;
+ private long _currentAssembliesHash = -1;
- #region Hash checking methods
+ ///
+ /// We will ensure that no matter what, only one of these is created, this is to ensure that caching always takes place
+ ///
+ ///
+ /// The setter is generally only used for unit tests
+ ///
+ internal static PluginManager Current
+ {
+ get
+ {
+ using (var l = new UpgradeableReadLock(Lock))
+ {
+ if (_resolver == null)
+ {
+ l.UpgradeToWriteLock();
+ _resolver = ApplicationContext.Current == null
+ ? new PluginManager()
+ : new PluginManager(ApplicationContext.Current);
+ }
+ return _resolver;
+ }
+ }
+ set { _resolver = value; }
+ }
+
+ #region Hash checking methods
- ///
- /// Returns a bool if the assemblies in the /bin have changed since they were last hashed.
- ///
- internal bool HaveAssembliesChanged { get; private set; }
+ ///
+ /// Returns a bool if the assemblies in the /bin have changed since they were last hashed.
+ ///
+ internal bool HaveAssembliesChanged { get; private set; }
- ///
- /// Returns the currently cached hash value of the scanned assemblies in the /bin folder. Returns 0
- /// if no cache is found.
- ///
- ///
- internal long CachedAssembliesHash
- {
- get
- {
- if (_cachedAssembliesHash != -1)
- return _cachedAssembliesHash;
+ ///
+ /// Returns the currently cached hash value of the scanned assemblies in the /bin folder. Returns 0
+ /// if no cache is found.
+ ///
+ ///
+ internal long CachedAssembliesHash
+ {
+ get
+ {
+ if (_cachedAssembliesHash != -1)
+ return _cachedAssembliesHash;
- var filePath = Path.Combine(_tempFolder, "umbraco-plugins.hash");
- if (!File.Exists(filePath))
- return 0;
- var hash = File.ReadAllText(filePath, Encoding.UTF8);
- Int64 val;
- if (Int64.TryParse(hash, out val))
- {
- _cachedAssembliesHash = val;
- return _cachedAssembliesHash;
- }
- //it could not parse for some reason so we'll return 0.
- return 0;
- }
- }
+ var filePath = Path.Combine(_tempFolder, "umbraco-plugins.hash");
+ if (!File.Exists(filePath))
+ return 0;
+ var hash = File.ReadAllText(filePath, Encoding.UTF8);
+ Int64 val;
+ if (Int64.TryParse(hash, out val))
+ {
+ _cachedAssembliesHash = val;
+ return _cachedAssembliesHash;
+ }
+ //it could not parse for some reason so we'll return 0.
+ return 0;
+ }
+ }
- ///
- /// Returns the current assemblies hash based on creating a hash from the assemblies in the /bin
- ///
- ///
- internal long CurrentAssembliesHash
- {
- get
- {
- if (_currentAssembliesHash != -1)
- return _currentAssembliesHash;
+ ///
+ /// Returns the current assemblies hash based on creating a hash from the assemblies in the /bin
+ ///
+ ///
+ internal long CurrentAssembliesHash
+ {
+ get
+ {
+ if (_currentAssembliesHash != -1)
+ return _currentAssembliesHash;
- _currentAssembliesHash = GetAssembliesHash(
- new FileSystemInfo[]
+ _currentAssembliesHash = GetAssembliesHash(
+ new FileSystemInfo[]
{
//add the bin folder and everything in it
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Bin)),
//add the app code folder and everything in it
new DirectoryInfo(IOHelper.MapPath("~/App_Code")),
//add the global.asax (the app domain also monitors this, if it changes will do a full restart)
- new FileInfo(IOHelper.MapPath("~/global.asax"))
+ new FileInfo(IOHelper.MapPath("~/global.asax")),
+ //add the trees.config
+ new FileInfo(IOHelper.MapPath(SystemDirectories.Config + "/trees.config"))
}
- );
- return _currentAssembliesHash;
- }
- }
-
- ///
- /// Writes the assembly hash file
- ///
- private void WriteCachePluginsHash()
- {
- var filePath = Path.Combine(_tempFolder, "umbraco-plugins.hash");
- File.WriteAllText(filePath, CurrentAssembliesHash.ToString(), Encoding.UTF8);
- }
-
- ///
- /// Returns a unique hash for the combination of FileInfo objects passed in
- ///
- ///
- ///
- internal static long GetAssembliesHash(IEnumerable filesAndFolders)
- {
- using (DisposableTimer.TraceDuration("Determining hash of code files on disk", "Hash determined"))
- {
- var hashCombiner = new HashCodeCombiner();
- //add each unique folder to the hash
- foreach (var i in filesAndFolders.DistinctBy(x => x.FullName))
- {
- hashCombiner.AddFileSystemItem(i);
- }
- return ConvertPluginsHashFromHex(hashCombiner.GetCombinedHashCode());
- }
- }
-
- ///
- /// Converts the hash value of current plugins to long from string
- ///
- ///
- ///
- internal static long ConvertPluginsHashFromHex(string val)
- {
- long outVal;
- if (Int64.TryParse(val, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out outVal))
- {
- return outVal;
- }
- return 0;
- }
-
- ///
- /// Attempts to resolve the list of plugin + assemblies found in the runtime for the base type 'T' passed in.
- /// If the cache file doesn't exist, fails to load, is corrupt or the type 'T' element is not found then
- /// a false attempt is returned.
- ///
- ///
- ///
- internal Attempt> TryGetCachedPluginsFromFile(TypeResolutionKind resolutionType)
- {
- var filePath = GetPluginListFilePath();
- if (!File.Exists(filePath))
- return Attempt>.False;
-
- try
- {
- //we will load the xml document, if the app context exist, we will load it from the cache (which is only around for 5 minutes)
- //while the app boots up, this should save some IO time on app startup when the app context is there (which is always unless in unit tests)
- XDocument xml;
- if (_appContext != null)
- {
- xml = _appContext.ApplicationCache.GetCacheItem("umbraco-plugins.list",
- new TimeSpan(0, 0, 5, 0),
- () => XDocument.Load(filePath));
- }
- else
- {
- xml = XDocument.Load(filePath);
- }
-
-
- if (xml.Root == null)
- return Attempt>.False;
-
- var typeElement = xml.Root.Elements()
- .SingleOrDefault(x =>
- x.Name.LocalName == "baseType"
- && ((string) x.Attribute("type")) == typeof (T).FullName
- && ((string) x.Attribute("resolutionType")) == resolutionType.ToString());
-
- //return false but specify this exception type so we can detect it
- if (typeElement == null)
- return new Attempt>(new CachedPluginNotFoundInFile());
-
- //return success
- return new Attempt>(
- true,
- typeElement.Elements("add")
- .Select(x => (string) x.Attribute("type")));
- }
- catch (Exception ex)
- {
- //if the file is corrupted, etc... return false
- return new Attempt>(ex);
- }
- }
-
- private string GetPluginListFilePath()
- {
- return Path.Combine(_tempFolder, "umbraco-plugins.list");
- }
-
- ///
- /// This will return true if the plugin list file is a legacy one
- ///
- ///
- ///
- /// This method exists purely due to an error in 4.11. We were writing the plugin list file without the
- /// type resolution kind which will have caused some problems. Now we detect this legacy file and if it is detected
- /// we remove it so it can be recreated properly.
- ///
- internal bool DetectLegacyPluginListFile()
- {
- var filePath = GetPluginListFilePath();
- if (!File.Exists(filePath))
- return false;
-
- try
- {
- var xml = XDocument.Load(filePath);
- if (xml.Root == null)
- return false;
-
- var typeElement = xml.Root.Elements()
- .FirstOrDefault(x => x.Name.LocalName == "baseType");
-
- if (typeElement == null)
- return false;
-
- //now check if the typeElement is missing the resolutionType attribute
- return typeElement.Attributes().All(x => x.Name.LocalName != "resolutionType");
- }
- catch (Exception)
- {
- //if the file is corrupted, etc... return true so it is removed
- return true;
- }
- }
-
- ///
- /// Adds/Updates the type list for the base type 'T' in the cached file
- ///
- ///
- ///
- ///
- ///
- /// THIS METHOD IS NOT THREAD SAFE
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- /// ]]>
- ///
- internal void UpdateCachedPluginsFile(IEnumerable typesFound, TypeResolutionKind resolutionType)
- {
- var filePath = GetPluginListFilePath();
- XDocument xml;
- try
- {
- xml = XDocument.Load(filePath);
- }
- catch
- {
- //if there's an exception loading then this is somehow corrupt, we'll just replace it.
- File.Delete(filePath);
- //create the document and the root
- xml = new XDocument(new XElement("plugins"));
- }
- if (xml.Root == null)
- {
- //if for some reason there is no root, create it
- xml.Add(new XElement("plugins"));
- }
- //find the type 'T' element to add or update
- var typeElement = xml.Root.Elements()
- .SingleOrDefault(x =>
- x.Name.LocalName == "baseType"
- && ((string)x.Attribute("type")) == typeof(T).FullName
- && ((string)x.Attribute("resolutionType")) == resolutionType.ToString());
-
- if (typeElement == null)
- {
- //create the type element
- typeElement = new XElement("baseType",
- new XAttribute("type", typeof(T).FullName),
- new XAttribute("resolutionType", resolutionType.ToString()));
- //then add it to the root
- xml.Root.Add(typeElement);
- }
-
-
- //now we have the type element, we need to clear any previous types as children and add/update it with new ones
- typeElement.ReplaceNodes(typesFound
- .Select(x =>
- new XElement("add",
- new XAttribute("type", x.AssemblyQualifiedName))));
- //save the xml file
- xml.Save(filePath);
- }
-
- #endregion
-
- private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
- private readonly HashSet _types = new HashSet();
- private IEnumerable _assemblies;
-
- ///
- /// Returns all classes attributed with XsltExtensionAttribute attribute
- ///
- ///
- internal IEnumerable ResolveCacheRefreshers()
- {
- return ResolveTypes();
- }
-
- ///
- /// Returns all available IPropertyEditorValueConverter
- ///
- ///
- internal IEnumerable ResolvePropertyEditorValueConverters()
- {
- return ResolveTypes();
- }
-
- ///
- /// Returns all available IDataType in application
- ///
- ///
- internal IEnumerable ResolveDataTypes()
- {
- return ResolveTypes();
- }
-
- ///
- /// Returns all available IMacroGuiRendering in application
- ///
- ///
- internal IEnumerable ResolveMacroRenderings()
- {
- return ResolveTypes();
- }
-
- ///
- /// Returns all available IPackageAction in application
- ///
- ///
- internal IEnumerable ResolvePackageActions()
- {
- return ResolveTypes();
- }
-
- ///
- /// Returns all available IAction in application
- ///
- ///
- internal IEnumerable ResolveActions()
- {
- return ResolveTypes();
- }
-
- ///
- /// Returns all available IMacroPropertyTypes in application
- ///
- ///
- internal IEnumerable ResolveMacroPropertyTypes()
- {
- return ResolveTypes();
+ );
+ return _currentAssembliesHash;
+ }
}
- ///
- /// Gets/sets which assemblies to scan when type finding, generally used for unit testing, if not explicitly set
- /// this will search all assemblies known to have plugins and exclude ones known to not have them.
- ///
- internal IEnumerable AssembliesToScan
- {
- get { return _assemblies ?? (_assemblies = TypeFinder.GetAssembliesWithKnownExclusions()); }
- set { _assemblies = value; }
- }
+ ///
+ /// Writes the assembly hash file
+ ///
+ private void WriteCachePluginsHash()
+ {
+ var filePath = Path.Combine(_tempFolder, "umbraco-plugins.hash");
+ File.WriteAllText(filePath, CurrentAssembliesHash.ToString(), Encoding.UTF8);
+ }
- ///
- /// Used to resolve and create instances of the specified type based on the resolved/cached plugin types
- ///
- ///
- /// set to true if an exception is to be thrown if there is an error during instantiation
- ///
- internal IEnumerable FindAndCreateInstances(bool throwException = false)
- {
- var types = ResolveTypes();
- return CreateInstances(types, throwException);
- }
+ ///
+ /// Returns a unique hash for the combination of FileInfo objects passed in
+ ///
+ ///
+ ///
+ internal static long GetAssembliesHash(IEnumerable filesAndFolders)
+ {
+ using (DisposableTimer.TraceDuration("Determining hash of code files on disk", "Hash determined"))
+ {
+ var hashCombiner = new HashCodeCombiner();
+ //add each unique folder to the hash
+ foreach (var i in filesAndFolders.DistinctBy(x => x.FullName))
+ {
+ hashCombiner.AddFileSystemItem(i);
+ }
+ return ConvertPluginsHashFromHex(hashCombiner.GetCombinedHashCode());
+ }
+ }
- ///
- /// Used to create instances of the specified type based on the resolved/cached plugin types
- ///
- ///
- ///
- /// set to true if an exception is to be thrown if there is an error during instantiation
- ///
- internal IEnumerable CreateInstances(IEnumerable types, bool throwException = false)
- {
- //Have removed logging because it doesn't really need to be logged since the time taken is generally 0ms.
- //we want to know if it fails ever, not how long it took if it is only 0.
+ ///
+ /// Converts the hash value of current plugins to long from string
+ ///
+ ///
+ ///
+ internal static long ConvertPluginsHashFromHex(string val)
+ {
+ long outVal;
+ if (Int64.TryParse(val, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out outVal))
+ {
+ return outVal;
+ }
+ return 0;
+ }
- var typesAsArray = types.ToArray();
- //using (DisposableTimer.DebugDuration(
- // String.Format("Starting instantiation of {0} objects of type {1}", typesAsArray.Length, typeof(T).FullName),
- // String.Format("Completed instantiation of {0} objects of type {1}", typesAsArray.Length, typeof(T).FullName)))
- //{
- var instances = new List();
- foreach (var t in typesAsArray)
- {
- try
- {
- var typeInstance = (T)Activator.CreateInstance(t);
- instances.Add(typeInstance);
- }
- catch (Exception ex)
- {
+ ///
+ /// Attempts to resolve the list of plugin + assemblies found in the runtime for the base type 'T' passed in.
+ /// If the cache file doesn't exist, fails to load, is corrupt or the type 'T' element is not found then
+ /// a false attempt is returned.
+ ///
+ ///
+ ///
+ internal Attempt> TryGetCachedPluginsFromFile(TypeResolutionKind resolutionType)
+ {
+ var filePath = GetPluginListFilePath();
+ if (!File.Exists(filePath))
+ return Attempt>.False;
- LogHelper.Error(String.Format("Error creating type {0}", t.FullName), ex);
+ try
+ {
+ //we will load the xml document, if the app context exist, we will load it from the cache (which is only around for 5 minutes)
+ //while the app boots up, this should save some IO time on app startup when the app context is there (which is always unless in unit tests)
+ XDocument xml;
+ if (_appContext != null)
+ {
+ xml = _appContext.ApplicationCache.GetCacheItem("umbraco-plugins.list",
+ new TimeSpan(0, 0, 5, 0),
+ () => XDocument.Load(filePath));
+ }
+ else
+ {
+ xml = XDocument.Load(filePath);
+ }
- if (throwException)
- {
- throw ex;
- }
- }
- }
- return instances;
- //}
- }
- ///
- /// Used to create an instance of the specified type based on the resolved/cached plugin types
- ///
- ///
- ///
- ///
- ///
- internal T CreateInstance(Type type, bool throwException = false)
- {
- var instances = CreateInstances(new[] { type }, throwException);
- return instances.FirstOrDefault();
- }
+ if (xml.Root == null)
+ return Attempt>.False;
- private IEnumerable ResolveTypes(
- Func> finder,
- TypeResolutionKind resolutionType,
- bool cacheResult)
- {
- using (var readLock = new UpgradeableReadLock(_lock))
- {
- var typesFound = new List();
+ var typeElement = xml.Root.Elements()
+ .SingleOrDefault(x =>
+ x.Name.LocalName == "baseType"
+ && ((string)x.Attribute("type")) == typeof(T).FullName
+ && ((string)x.Attribute("resolutionType")) == resolutionType.ToString());
- using (DisposableTimer.TraceDuration(
- () => String.Format("Starting resolution types of {0}", typeof(T).FullName),
- () => String.Format("Completed resolution of types of {0}, found {1}", typeof(T).FullName, typesFound.Count)))
- {
- //check if the TypeList already exists, if so return it, if not we'll create it
- var typeList = _types.SingleOrDefault(x => x.IsTypeList(resolutionType));
- //if we're not caching the result then proceed, or if the type list doesn't exist then proceed
- if (!cacheResult || typeList == null)
- {
- //upgrade to a write lock since we're adding to the collection
- readLock.UpgradeToWriteLock();
+ //return false but specify this exception type so we can detect it
+ if (typeElement == null)
+ return new Attempt>(new CachedPluginNotFoundInFile());
- typeList = new TypeList(resolutionType);
+ //return success
+ return new Attempt>(
+ true,
+ typeElement.Elements("add")
+ .Select(x => (string)x.Attribute("type")));
+ }
+ catch (Exception ex)
+ {
+ //if the file is corrupted, etc... return false
+ return new Attempt>(ex);
+ }
+ }
- //we first need to look into our cache file (this has nothing to do with the 'cacheResult' parameter which caches in memory).
- //if assemblies have not changed and the cache file actually exists, then proceed to try to lookup by the cache file.
- if (!HaveAssembliesChanged && File.Exists(GetPluginListFilePath()))
- {
- var fileCacheResult = TryGetCachedPluginsFromFile(resolutionType);
+ private string GetPluginListFilePath()
+ {
+ return Path.Combine(_tempFolder, "umbraco-plugins.list");
+ }
- //here we need to identify if the CachedPluginNotFoundInFile was the exception, if it was then we need to re-scan
- //in some cases the plugin will not have been scanned for on application startup, but the assemblies haven't changed
- //so in this instance there will never be a result.
- if (fileCacheResult.Error != null && fileCacheResult.Error is CachedPluginNotFoundInFile)
- {
- //we don't have a cache for this so proceed to look them up by scanning
- LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder);
- }
- else
- {
- if (fileCacheResult.Success)
- {
- var successfullyLoadedFromCache = true;
- //we have a previous cache for this so we don't need to scan we just load what has been found in the file
- foreach (var t in fileCacheResult.Result)
- {
- try
- {
- //we use the build manager to ensure we get all types loaded, this is slightly slower than
- //Type.GetType but if the types in the assembly aren't loaded yet then we have problems with that.
- var type = BuildManager.GetType(t, true);
- typeList.AddType(type);
- }
- catch (Exception ex)
- {
- //if there are any exceptions loading types, we have to exist, this should never happen so
- //we will need to revert to scanning for types.
- successfullyLoadedFromCache = false;
- LogHelper.Error("Could not load a cached plugin type: " + t + " now reverting to re-scanning assemblies for the base type: " + typeof(T).FullName, ex);
- break;
- }
- }
- if (!successfullyLoadedFromCache)
- {
- //we need to manually load by scanning if loading from the file was not successful.
- LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder);
- }
- else
- {
- LogHelper.Debug("Loaded plugin types " + typeof(T).FullName + " from persisted cache");
- }
- }
- }
- }
- else
- {
- //we don't have a cache for this so proceed to look them up by scanning
- LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder);
- }
+ ///
+ /// This will return true if the plugin list file is a legacy one
+ ///
+ ///
+ ///
+ /// This method exists purely due to an error in 4.11. We were writing the plugin list file without the
+ /// type resolution kind which will have caused some problems. Now we detect this legacy file and if it is detected
+ /// we remove it so it can be recreated properly.
+ ///
+ internal bool DetectLegacyPluginListFile()
+ {
+ var filePath = GetPluginListFilePath();
+ if (!File.Exists(filePath))
+ return false;
- //only add the cache if we are to cache the results
- if (cacheResult)
- {
- //add the type list to the collection
- _types.Add(typeList);
- }
- }
- typesFound = typeList.GetTypes().ToList();
- }
+ try
+ {
+ var xml = XDocument.Load(filePath);
+ if (xml.Root == null)
+ return false;
- return typesFound;
- }
- }
+ var typeElement = xml.Root.Elements()
+ .FirstOrDefault(x => x.Name.LocalName == "baseType");
- ///
- /// This method invokes the finder which scans the assemblies for the types and then loads the result into the type finder.
- /// Once the results are loaded, we update the cached type xml file
- ///
- ///
- ///
- ///
- ///
- /// THIS METHODS IS NOT THREAD SAFE
- ///
- private void LoadViaScanningAndUpdateCacheFile(TypeList typeList, TypeResolutionKind resolutionKind, Func> finder)
- {
- //we don't have a cache for this so proceed to look them up by scanning
- foreach (var t in finder())
- {
- typeList.AddType(t);
- }
- UpdateCachedPluginsFile(typeList.GetTypes(), resolutionKind);
- }
+ if (typeElement == null)
+ return false;
- ///
- /// Generic method to find the specified type and cache the result
- ///
- ///
- ///
- internal IEnumerable ResolveTypes(bool cacheResult = true)
- {
- return ResolveTypes(
- () => TypeFinder.FindClassesOfType(AssembliesToScan),
- TypeResolutionKind.FindAllTypes,
- cacheResult);
- }
+ //now check if the typeElement is missing the resolutionType attribute
+ return typeElement.Attributes().All(x => x.Name.LocalName != "resolutionType");
+ }
+ catch (Exception)
+ {
+ //if the file is corrupted, etc... return true so it is removed
+ return true;
+ }
+ }
- ///
- /// Generic method to find the specified type that has an attribute and cache the result
- ///
- ///
- ///
- ///
- internal IEnumerable ResolveTypesWithAttribute(bool cacheResult = true)
- where TAttribute : Attribute
- {
- return ResolveTypes(
- () => TypeFinder.FindClassesOfTypeWithAttribute(AssembliesToScan),
- TypeResolutionKind.FindTypesWithAttribute,
- cacheResult);
- }
+ ///
+ /// Adds/Updates the type list for the base type 'T' in the cached file
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// THIS METHOD IS NOT THREAD SAFE
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// ]]>
+ ///
+ internal void UpdateCachedPluginsFile(IEnumerable typesFound, TypeResolutionKind resolutionType)
+ {
+ var filePath = GetPluginListFilePath();
+ XDocument xml;
+ try
+ {
+ xml = XDocument.Load(filePath);
+ }
+ catch
+ {
+ //if there's an exception loading then this is somehow corrupt, we'll just replace it.
+ File.Delete(filePath);
+ //create the document and the root
+ xml = new XDocument(new XElement("plugins"));
+ }
+ if (xml.Root == null)
+ {
+ //if for some reason there is no root, create it
+ xml.Add(new XElement("plugins"));
+ }
+ //find the type 'T' element to add or update
+ var typeElement = xml.Root.Elements()
+ .SingleOrDefault(x =>
+ x.Name.LocalName == "baseType"
+ && ((string)x.Attribute("type")) == typeof(T).FullName
+ && ((string)x.Attribute("resolutionType")) == resolutionType.ToString());
- ///
- /// Generic method to find any type that has the specified attribute
- ///
- ///
- ///
- internal IEnumerable ResolveAttributedTypes(bool cacheResult = true)
- where TAttribute : Attribute
- {
- return ResolveTypes(
- () => TypeFinder.FindClassesWithAttribute(AssembliesToScan),
- TypeResolutionKind.FindAttributedTypes,
- cacheResult);
- }
+ if (typeElement == null)
+ {
+ //create the type element
+ typeElement = new XElement("baseType",
+ new XAttribute("type", typeof(T).FullName),
+ new XAttribute("resolutionType", resolutionType.ToString()));
+ //then add it to the root
+ xml.Root.Add(typeElement);
+ }
- ///
- /// Used for unit tests
- ///
- ///
- internal HashSet GetTypeLists()
- {
- return _types;
- }
+
+ //now we have the type element, we need to clear any previous types as children and add/update it with new ones
+ typeElement.ReplaceNodes(typesFound.Select(x => new XElement("add", new XAttribute("type", x.AssemblyQualifiedName))));
+ //save the xml file
+ xml.Save(filePath);
+ }
+
+ #endregion
+
+ private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
+ private readonly HashSet _types = new HashSet();
+ private IEnumerable _assemblies;
+
+ ///
+ /// Returns all classes attributed with XsltExtensionAttribute attribute
+ ///
+ ///
+ internal IEnumerable ResolveCacheRefreshers()
+ {
+ return ResolveTypes();
+ }
+
+ ///
+ /// Returns all available IPropertyEditorValueConverter
+ ///
+ ///
+ internal IEnumerable ResolvePropertyEditorValueConverters()
+ {
+ return ResolveTypes();
+ }
+
+ ///
+ /// Returns all available IDataType in application
+ ///
+ ///
+ internal IEnumerable ResolveDataTypes()
+ {
+ return ResolveTypes();
+ }
+
+ ///
+ /// Returns all available IMacroGuiRendering in application
+ ///
+ ///
+ internal IEnumerable ResolveMacroRenderings()
+ {
+ return ResolveTypes();
+ }
+
+ ///
+ /// Returns all available IPackageAction in application
+ ///
+ ///
+ internal IEnumerable ResolvePackageActions()
+ {
+ return ResolveTypes();
+ }
+
+ ///
+ /// Returns all available IAction in application
+ ///
+ ///
+ internal IEnumerable ResolveActions()
+ {
+ return ResolveTypes();
+ }
+
+ ///
+ /// Gets/sets which assemblies to scan when type finding, generally used for unit testing, if not explicitly set
+ /// this will search all assemblies known to have plugins and exclude ones known to not have them.
+ ///
+ internal IEnumerable AssembliesToScan
+ {
+ get { return _assemblies ?? (_assemblies = TypeFinder.GetAssembliesWithKnownExclusions()); }
+ set { _assemblies = value; }
+ }
+
+ ///
+ /// Used to resolve and create instances of the specified type based on the resolved/cached plugin types
+ ///
+ ///
+ /// set to true if an exception is to be thrown if there is an error during instantiation
+ ///
+ internal IEnumerable FindAndCreateInstances(bool throwException = false)
+ {
+ var types = ResolveTypes();
+ return CreateInstances(types, throwException);
+ }
+
+ ///
+ /// Used to create instances of the specified type based on the resolved/cached plugin types
+ ///
+ ///
+ ///
+ /// set to true if an exception is to be thrown if there is an error during instantiation
+ ///
+ internal IEnumerable CreateInstances(IEnumerable types, bool throwException = false)
+ {
+ //Have removed logging because it doesn't really need to be logged since the time taken is generally 0ms.
+ //we want to know if it fails ever, not how long it took if it is only 0.
+
+ var typesAsArray = types.ToArray();
+ //using (DisposableTimer.DebugDuration(
+ // String.Format("Starting instantiation of {0} objects of type {1}", typesAsArray.Length, typeof(T).FullName),
+ // String.Format("Completed instantiation of {0} objects of type {1}", typesAsArray.Length, typeof(T).FullName)))
+ //{
+ var instances = new List();
+ foreach (var t in typesAsArray)
+ {
+ try
+ {
+ var typeInstance = (T)Activator.CreateInstance(t);
+ instances.Add(typeInstance);
+ }
+ catch (Exception ex)
+ {
+
+ LogHelper.Error(String.Format("Error creating type {0}", t.FullName), ex);
+
+ if (throwException)
+ {
+ throw ex;
+ }
+ }
+ }
+ return instances;
+ //}
+ }
+
+ ///
+ /// Used to create an instance of the specified type based on the resolved/cached plugin types
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal T CreateInstance(Type type, bool throwException = false)
+ {
+ var instances = CreateInstances(new[] { type }, throwException);
+ return instances.FirstOrDefault();
+ }
+
+ private IEnumerable ResolveTypes(
+ Func> finder,
+ TypeResolutionKind resolutionType,
+ bool cacheResult)
+ {
+ using (var readLock = new UpgradeableReadLock(_lock))
+ {
+ var typesFound = new List();
+
+ using (DisposableTimer.TraceDuration(
+ () => String.Format("Starting resolution types of {0}", typeof(T).FullName),
+ () => String.Format("Completed resolution of types of {0}, found {1}", typeof(T).FullName, typesFound.Count)))
+ {
+ //check if the TypeList already exists, if so return it, if not we'll create it
+ var typeList = _types.SingleOrDefault(x => x.IsTypeList(resolutionType));
+ //if we're not caching the result then proceed, or if the type list doesn't exist then proceed
+ if (!cacheResult || typeList == null)
+ {
+ //upgrade to a write lock since we're adding to the collection
+ readLock.UpgradeToWriteLock();
+
+ typeList = new TypeList(resolutionType);
+
+ //we first need to look into our cache file (this has nothing to do with the 'cacheResult' parameter which caches in memory).
+ //if assemblies have not changed and the cache file actually exists, then proceed to try to lookup by the cache file.
+ if (!HaveAssembliesChanged && File.Exists(GetPluginListFilePath()))
+ {
+ var fileCacheResult = TryGetCachedPluginsFromFile(resolutionType);
+
+ //here we need to identify if the CachedPluginNotFoundInFile was the exception, if it was then we need to re-scan
+ //in some cases the plugin will not have been scanned for on application startup, but the assemblies haven't changed
+ //so in this instance there will never be a result.
+ if (fileCacheResult.Error != null && fileCacheResult.Error is CachedPluginNotFoundInFile)
+ {
+ //we don't have a cache for this so proceed to look them up by scanning
+ LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder);
+ }
+ else
+ {
+ if (fileCacheResult.Success)
+ {
+ var successfullyLoadedFromCache = true;
+ //we have a previous cache for this so we don't need to scan we just load what has been found in the file
+ foreach (var t in fileCacheResult.Result)
+ {
+ try
+ {
+ //we use the build manager to ensure we get all types loaded, this is slightly slower than
+ //Type.GetType but if the types in the assembly aren't loaded yet then we have problems with that.
+ var type = BuildManager.GetType(t, true);
+ typeList.AddType(type);
+ }
+ catch (Exception ex)
+ {
+ //if there are any exceptions loading types, we have to exist, this should never happen so
+ //we will need to revert to scanning for types.
+ successfullyLoadedFromCache = false;
+ LogHelper.Error("Could not load a cached plugin type: " + t + " now reverting to re-scanning assemblies for the base type: " + typeof(T).FullName, ex);
+ break;
+ }
+ }
+ if (!successfullyLoadedFromCache)
+ {
+ //we need to manually load by scanning if loading from the file was not successful.
+ LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder);
+ }
+ else
+ {
+ LogHelper.Debug("Loaded plugin types " + typeof(T).FullName + " from persisted cache");
+ }
+ }
+ }
+ }
+ else
+ {
+ //we don't have a cache for this so proceed to look them up by scanning
+ LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder);
+ }
+
+ //only add the cache if we are to cache the results
+ if (cacheResult)
+ {
+ //add the type list to the collection
+ _types.Add(typeList);
+ }
+ }
+ typesFound = typeList.GetTypes().ToList();
+ }
+
+ return typesFound;
+ }
+ }
+
+ ///
+ /// This method invokes the finder which scans the assemblies for the types and then loads the result into the type finder.
+ /// Once the results are loaded, we update the cached type xml file
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// THIS METHODS IS NOT THREAD SAFE
+ ///
+ private void LoadViaScanningAndUpdateCacheFile(TypeList typeList, TypeResolutionKind resolutionKind, Func> finder)
+ {
+ //we don't have a cache for this so proceed to look them up by scanning
+ foreach (var t in finder())
+ {
+ typeList.AddType(t);
+ }
+ UpdateCachedPluginsFile(typeList.GetTypes(), resolutionKind);
+ }
+
+ ///
+ /// Generic method to find the specified type and cache the result
+ ///
+ ///
+ ///
+ internal IEnumerable ResolveTypes(bool cacheResult = true)
+ {
+ return ResolveTypes(
+ () => TypeFinder.FindClassesOfType(AssembliesToScan),
+ TypeResolutionKind.FindAllTypes,
+ cacheResult);
+ }
+
+ ///
+ /// Generic method to find the specified type that has an attribute and cache the result
+ ///
+ ///
+ ///
+ ///
+ internal IEnumerable ResolveTypesWithAttribute(bool cacheResult = true)
+ where TAttribute : Attribute
+ {
+ return ResolveTypes(
+ () => TypeFinder.FindClassesOfTypeWithAttribute(AssembliesToScan),
+ TypeResolutionKind.FindTypesWithAttribute,
+ cacheResult);
+ }
+
+ ///
+ /// Generic method to find any type that has the specified attribute
+ ///
+ ///
+ ///
+ internal IEnumerable ResolveAttributedTypes(bool cacheResult = true)
+ where TAttribute : Attribute
+ {
+ return ResolveTypes(
+ () => TypeFinder.FindClassesWithAttribute(AssembliesToScan),
+ TypeResolutionKind.FindAttributedTypes,
+ cacheResult);
+ }
+
+ ///
+ /// Used for unit tests
+ ///
+ ///
+ internal HashSet GetTypeLists()
+ {
+ return _types;
+ }
- #region Private classes/Enums
+ #region Private classes/Enums
- ///
- /// The type of resolution being invoked
- ///
- internal enum TypeResolutionKind
- {
- FindAllTypes,
- FindAttributedTypes,
- FindTypesWithAttribute
- }
+ ///
+ /// The type of resolution being invoked
+ ///
+ internal enum TypeResolutionKind
+ {
+ FindAllTypes,
+ FindAttributedTypes,
+ FindTypesWithAttribute
+ }
- internal abstract class TypeList
- {
- public abstract void AddType(Type t);
- public abstract bool IsTypeList(TypeResolutionKind resolutionType);
- public abstract IEnumerable GetTypes();
- }
+ internal abstract class TypeList
+ {
+ public abstract void AddType(Type t);
+ public abstract bool IsTypeList(TypeResolutionKind resolutionType);
+ public abstract IEnumerable GetTypes();
+ }
- internal class TypeList : TypeList
- {
- private readonly TypeResolutionKind _resolutionType;
+ internal class TypeList : TypeList
+ {
+ private readonly TypeResolutionKind _resolutionType;
- public TypeList(TypeResolutionKind resolutionType)
- {
- _resolutionType = resolutionType;
- }
+ public TypeList(TypeResolutionKind resolutionType)
+ {
+ _resolutionType = resolutionType;
+ }
- private readonly List _types = new List();
+ private readonly List _types = new List();
- public override void AddType(Type t)
- {
- //if the type is an attribute type we won't do the type check because typeof is going to be the
- //attribute type whereas the 't' type is the object type found with the attribute.
- if (_resolutionType == TypeResolutionKind.FindAttributedTypes || t.IsType())
- {
- _types.Add(t);
- }
- }
+ public override void AddType(Type t)
+ {
+ //if the type is an attribute type we won't do the type check because typeof is going to be the
+ //attribute type whereas the 't' type is the object type found with the attribute.
+ if (_resolutionType == TypeResolutionKind.FindAttributedTypes || t.IsType())
+ {
+ _types.Add(t);
+ }
+ }
- ///
- /// Returns true if the current TypeList is of the same type and of the same type
- ///
- ///
- ///
- ///
- public override bool IsTypeList(TypeResolutionKind resolutionType)
- {
- return _resolutionType == resolutionType && (typeof (T)).IsType();
- }
+ ///
+ /// Returns true if the current TypeList is of the same type and of the same type
+ ///
+ ///
+ ///
+ ///
+ public override bool IsTypeList(TypeResolutionKind resolutionType)
+ {
+ return _resolutionType == resolutionType && (typeof(T)).IsType();
+ }
- public override IEnumerable GetTypes()
- {
- return _types;
- }
- }
-
- ///
- /// This class is used simply to determine that a plugin was not found in the cache plugin list with the specified
- /// TypeResolutionKind.
- ///
- internal class CachedPluginNotFoundInFile : Exception
- {
-
- }
-
- #endregion
- }
+ public override IEnumerable GetTypes()
+ {
+ return _types;
+ }
+ }
+
+ ///
+ /// This class is used simply to determine that a plugin was not found in the cache plugin list with the specified
+ /// TypeResolutionKind.
+ ///
+ internal class CachedPluginNotFoundInFile : Exception
+ {
+
+ }
+
+ #endregion
+ }
}
diff --git a/src/Umbraco.Tests/PluginManagerTests.cs b/src/Umbraco.Tests/PluginManagerTests.cs
index 4dbaae98de..4b690d6271 100644
--- a/src/Umbraco.Tests/PluginManagerTests.cs
+++ b/src/Umbraco.Tests/PluginManagerTests.cs
@@ -24,21 +24,21 @@ using umbraco.cms;
namespace Umbraco.Tests
{
- [TestFixture]
- public class PluginManagerTests
- {
+ [TestFixture]
+ public class PluginManagerTests
+ {
- [SetUp]
- public void Initialize()
- {
- TestHelper.SetupLog4NetForTests();
+ [SetUp]
+ public void Initialize()
+ {
+ TestHelper.SetupLog4NetForTests();
- //this ensures its reset
- PluginManager.Current = new PluginManager(false);
+ //this ensures its reset
+ PluginManager.Current = new PluginManager(false);
- //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
- //TODO: Should probably update this so it only searches this assembly and add custom types to be found
- PluginManager.Current.AssembliesToScan = new[]
+ //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
+ //TODO: Should probably update this so it only searches this assembly and add custom types to be found
+ PluginManager.Current.AssembliesToScan = new[]
{
this.GetType().Assembly,
typeof(ApplicationStartupHandler).Assembly,
@@ -58,314 +58,314 @@ namespace Umbraco.Tests
typeof(UmbracoContext).Assembly,
typeof(BaseDataType).Assembly
};
- }
+ }
- private DirectoryInfo PrepareFolder()
- {
- var assDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
- var dir = Directory.CreateDirectory(Path.Combine(assDir.FullName, "PluginManager", Guid.NewGuid().ToString("N")));
- foreach (var f in dir.GetFiles())
- {
- f.Delete();
- }
- return dir;
- }
+ private DirectoryInfo PrepareFolder()
+ {
+ var assDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
+ var dir = Directory.CreateDirectory(Path.Combine(assDir.FullName, "PluginManager", Guid.NewGuid().ToString("N")));
+ foreach (var f in dir.GetFiles())
+ {
+ f.Delete();
+ }
+ return dir;
+ }
- //[Test]
- //public void Scan_Vs_Load_Benchmark()
- //{
- // var pluginManager = new PluginManager(false);
- // var watch = new Stopwatch();
- // watch.Start();
- // for (var i = 0; i < 1000; i++)
- // {
- // var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
- // var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
- // var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
- // var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
- // }
- // watch.Stop();
- // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
- // watch.Start();
- // for (var i = 0; i < 1000; i++)
- // {
- // var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
- // var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
- // var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
- // var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
- // }
- // watch.Stop();
- // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
- // watch.Reset();
- // watch.Start();
- // for (var i = 0; i < 1000; i++)
- // {
- // var refreshers = pluginManager.ResolveTypes(false);
- // }
- // watch.Stop();
- // Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds);
- //}
+ //[Test]
+ //public void Scan_Vs_Load_Benchmark()
+ //{
+ // var pluginManager = new PluginManager(false);
+ // var watch = new Stopwatch();
+ // watch.Start();
+ // for (var i = 0; i < 1000; i++)
+ // {
+ // var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
+ // var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
+ // var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
+ // var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
+ // }
+ // watch.Stop();
+ // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
+ // watch.Start();
+ // for (var i = 0; i < 1000; i++)
+ // {
+ // var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
+ // var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
+ // var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
+ // var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
+ // }
+ // watch.Stop();
+ // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
+ // watch.Reset();
+ // watch.Start();
+ // for (var i = 0; i < 1000; i++)
+ // {
+ // var refreshers = pluginManager.ResolveTypes(false);
+ // }
+ // watch.Stop();
+ // Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds);
+ //}
- ////NOTE: This test shows that Type.GetType is 100% faster than Assembly.Load(..).GetType(...) so we'll use that :)
- //[Test]
- //public void Load_Type_Benchmark()
- //{
- // var watch = new Stopwatch();
- // watch.Start();
- // for (var i = 0; i < 1000; i++)
- // {
- // var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
- // var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
- // var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
- // var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
- // }
- // watch.Stop();
- // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
- // watch.Reset();
- // watch.Start();
- // for (var i = 0; i < 1000; i++)
- // {
- // var type2 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
- // .GetType("umbraco.macroCacheRefresh");
- // var type3 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
- // .GetType("umbraco.templateCacheRefresh");
- // var type4 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
- // .GetType("umbraco.presentation.cache.MediaLibraryRefreshers");
- // var type5 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
- // .GetType("umbraco.presentation.cache.pageRefresher");
- // }
- // watch.Stop();
- // Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds);
- // watch.Reset();
- // watch.Start();
- // for (var i = 0; i < 1000; i++)
- // {
- // var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
- // var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
- // var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
- // var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
- // }
- // watch.Stop();
- // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
- //}
+ ////NOTE: This test shows that Type.GetType is 100% faster than Assembly.Load(..).GetType(...) so we'll use that :)
+ //[Test]
+ //public void Load_Type_Benchmark()
+ //{
+ // var watch = new Stopwatch();
+ // watch.Start();
+ // for (var i = 0; i < 1000; i++)
+ // {
+ // var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
+ // var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
+ // var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
+ // var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
+ // }
+ // watch.Stop();
+ // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
+ // watch.Reset();
+ // watch.Start();
+ // for (var i = 0; i < 1000; i++)
+ // {
+ // var type2 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
+ // .GetType("umbraco.macroCacheRefresh");
+ // var type3 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
+ // .GetType("umbraco.templateCacheRefresh");
+ // var type4 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
+ // .GetType("umbraco.presentation.cache.MediaLibraryRefreshers");
+ // var type5 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
+ // .GetType("umbraco.presentation.cache.pageRefresher");
+ // }
+ // watch.Stop();
+ // Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds);
+ // watch.Reset();
+ // watch.Start();
+ // for (var i = 0; i < 1000; i++)
+ // {
+ // var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
+ // var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
+ // var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
+ // var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
+ // }
+ // watch.Stop();
+ // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
+ //}
- [Test]
- public void Detect_Legacy_Plugin_File_List()
- {
- var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
- var manager = new PluginManager(false);
- var filePath = Path.Combine(tempFolder, "umbraco-plugins.list");
- File.WriteAllText(filePath, @"
+ [Test]
+ public void Detect_Legacy_Plugin_File_List()
+ {
+ var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
+ var manager = new PluginManager(false);
+ var filePath = Path.Combine(tempFolder, "umbraco-plugins.list");
+ File.WriteAllText(filePath, @"
");
- Assert.IsTrue(manager.DetectLegacyPluginListFile());
+ Assert.IsTrue(manager.DetectLegacyPluginListFile());
- File.Delete(filePath);
+ File.Delete(filePath);
- //now create a valid one
- File.WriteAllText(filePath, @"
+ //now create a valid one
+ File.WriteAllText(filePath, @"
");
- Assert.IsFalse(manager.DetectLegacyPluginListFile());
- }
+ Assert.IsFalse(manager.DetectLegacyPluginListFile());
+ }
- [Test]
- public void Create_Cached_Plugin_File()
- {
- var types = new[] {typeof (PluginManager), typeof (PluginManagerTests), typeof (UmbracoContext)};
+ [Test]
+ public void Create_Cached_Plugin_File()
+ {
+ var types = new[] { typeof(PluginManager), typeof(PluginManagerTests), typeof(UmbracoContext) };
- var manager = new PluginManager(false);
- //yes this is silly, none of these types inherit from string, but this is just to test the xml file format
- manager.UpdateCachedPluginsFile(types, PluginManager.TypeResolutionKind.FindAllTypes);
+ var manager = new PluginManager(false);
+ //yes this is silly, none of these types inherit from string, but this is just to test the xml file format
+ manager.UpdateCachedPluginsFile(types, PluginManager.TypeResolutionKind.FindAllTypes);
- var plugins = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAllTypes);
- var diffType = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAttributedTypes);
+ var plugins = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAllTypes);
+ var diffType = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAttributedTypes);
- Assert.IsTrue(plugins.Success);
- //this will be false since there is no cache of that type resolution kind
- Assert.IsFalse(diffType.Success);
+ Assert.IsTrue(plugins.Success);
+ //this will be false since there is no cache of that type resolution kind
+ Assert.IsFalse(diffType.Success);
- Assert.AreEqual(3, plugins.Result.Count());
- var shouldContain = types.Select(x => x.AssemblyQualifiedName);
- //ensure they are all found
- Assert.IsTrue(plugins.Result.ContainsAll(shouldContain));
- }
+ Assert.AreEqual(3, plugins.Result.Count());
+ var shouldContain = types.Select(x => x.AssemblyQualifiedName);
+ //ensure they are all found
+ Assert.IsTrue(plugins.Result.ContainsAll(shouldContain));
+ }
- [Test]
- public void PluginHash_From_String()
- {
- var s = "hello my name is someone".GetHashCode().ToString("x", CultureInfo.InvariantCulture);
- var output = PluginManager.ConvertPluginsHashFromHex(s);
- Assert.AreNotEqual(0, output);
- }
+ [Test]
+ public void PluginHash_From_String()
+ {
+ var s = "hello my name is someone".GetHashCode().ToString("x", CultureInfo.InvariantCulture);
+ var output = PluginManager.ConvertPluginsHashFromHex(s);
+ Assert.AreNotEqual(0, output);
+ }
- [Test]
- public void Get_Plugins_Hash()
- {
- //Arrange
- var dir = PrepareFolder();
- var d1 = dir.CreateSubdirectory("1");
- var d2 = dir.CreateSubdirectory("2");
- var d3 = dir.CreateSubdirectory("3");
- var d4 = dir.CreateSubdirectory("4");
- var f1 = new FileInfo(Path.Combine(d1.FullName, "test1.dll"));
- var f2 = new FileInfo(Path.Combine(d1.FullName, "test2.dll"));
- var f3 = new FileInfo(Path.Combine(d2.FullName, "test1.dll"));
- var f4 = new FileInfo(Path.Combine(d2.FullName, "test2.dll"));
- var f5 = new FileInfo(Path.Combine(d3.FullName, "test1.dll"));
- var f6 = new FileInfo(Path.Combine(d3.FullName, "test2.dll"));
- var f7 = new FileInfo(Path.Combine(d4.FullName, "test1.dll"));
- f1.CreateText().Close();
- f2.CreateText().Close();
- f3.CreateText().Close();
- f4.CreateText().Close();
- f5.CreateText().Close();
- f6.CreateText().Close();
- f7.CreateText().Close();
- var list1 = new[] { f1, f2, f3, f4, f5, f6 };
- var list2 = new[] { f1, f3, f5 };
- var list3 = new[] { f1, f3, f5, f7 };
+ [Test]
+ public void Get_Plugins_Hash()
+ {
+ //Arrange
+ var dir = PrepareFolder();
+ var d1 = dir.CreateSubdirectory("1");
+ var d2 = dir.CreateSubdirectory("2");
+ var d3 = dir.CreateSubdirectory("3");
+ var d4 = dir.CreateSubdirectory("4");
+ var f1 = new FileInfo(Path.Combine(d1.FullName, "test1.dll"));
+ var f2 = new FileInfo(Path.Combine(d1.FullName, "test2.dll"));
+ var f3 = new FileInfo(Path.Combine(d2.FullName, "test1.dll"));
+ var f4 = new FileInfo(Path.Combine(d2.FullName, "test2.dll"));
+ var f5 = new FileInfo(Path.Combine(d3.FullName, "test1.dll"));
+ var f6 = new FileInfo(Path.Combine(d3.FullName, "test2.dll"));
+ var f7 = new FileInfo(Path.Combine(d4.FullName, "test1.dll"));
+ f1.CreateText().Close();
+ f2.CreateText().Close();
+ f3.CreateText().Close();
+ f4.CreateText().Close();
+ f5.CreateText().Close();
+ f6.CreateText().Close();
+ f7.CreateText().Close();
+ var list1 = new[] { f1, f2, f3, f4, f5, f6 };
+ var list2 = new[] { f1, f3, f5 };
+ var list3 = new[] { f1, f3, f5, f7 };
- //Act
- var hash1 = PluginManager.GetAssembliesHash(list1);
- var hash2 = PluginManager.GetAssembliesHash(list2);
- var hash3 = PluginManager.GetAssembliesHash(list3);
+ //Act
+ var hash1 = PluginManager.GetAssembliesHash(list1);
+ var hash2 = PluginManager.GetAssembliesHash(list2);
+ var hash3 = PluginManager.GetAssembliesHash(list3);
- //Assert
- Assert.AreNotEqual(hash1, hash2);
- Assert.AreNotEqual(hash1, hash3);
- Assert.AreNotEqual(hash2, hash3);
+ //Assert
+ Assert.AreNotEqual(hash1, hash2);
+ Assert.AreNotEqual(hash1, hash3);
+ Assert.AreNotEqual(hash2, hash3);
- Assert.AreEqual(hash1, PluginManager.GetAssembliesHash(list1));
- }
+ Assert.AreEqual(hash1, PluginManager.GetAssembliesHash(list1));
+ }
- [Test]
- public void Ensure_Only_One_Type_List_Created()
- {
- var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
- var foundTypes2 = PluginManager.Current.ResolveFindMeTypes();
- Assert.AreEqual(1,
- PluginManager.Current.GetTypeLists()
- .Count(x => x.IsTypeList(PluginManager.TypeResolutionKind.FindAllTypes)));
- }
+ [Test]
+ public void Ensure_Only_One_Type_List_Created()
+ {
+ var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
+ var foundTypes2 = PluginManager.Current.ResolveFindMeTypes();
+ Assert.AreEqual(1,
+ PluginManager.Current.GetTypeLists()
+ .Count(x => x.IsTypeList(PluginManager.TypeResolutionKind.FindAllTypes)));
+ }
- [Test]
- public void Resolves_Types()
- {
- var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
- Assert.AreEqual(2, foundTypes1.Count());
- }
+ [Test]
+ public void Resolves_Types()
+ {
+ var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
+ Assert.AreEqual(2, foundTypes1.Count());
+ }
- [Test]
- public void Resolves_Attributed_Trees()
- {
- var trees = PluginManager.Current.ResolveAttributedTrees();
- Assert.AreEqual(27, trees.Count());
- }
+ [Test]
+ public void Resolves_Attributed_Trees()
+ {
+ var trees = PluginManager.Current.ResolveAttributedTrees();
+ Assert.AreEqual(27, trees.Count());
+ }
- [Test]
- public void Resolves_Actions()
- {
- var actions = PluginManager.Current.ResolveActions();
- Assert.AreEqual(37, actions.Count());
- }
+ [Test]
+ public void Resolves_Actions()
+ {
+ var actions = PluginManager.Current.ResolveActions();
+ Assert.AreEqual(37, actions.Count());
+ }
- [Test]
- public void Resolves_Trees()
- {
- var trees = PluginManager.Current.ResolveTrees();
- Assert.AreEqual(36, trees.Count());
- }
+ [Test]
+ public void Resolves_Trees()
+ {
+ var trees = PluginManager.Current.ResolveTrees();
+ Assert.AreEqual(36, trees.Count());
+ }
- [Test]
- public void Resolves_Applications()
- {
- var apps = PluginManager.Current.ResolveApplications();
- Assert.AreEqual(7, apps.Count());
- }
+ [Test]
+ public void Resolves_Applications()
+ {
+ var apps = PluginManager.Current.ResolveApplications();
+ Assert.AreEqual(7, apps.Count());
+ }
- [Test]
- public void Resolves_Action_Handlers()
- {
- var types = PluginManager.Current.ResolveActionHandlers();
- Assert.AreEqual(1, types.Count());
- }
+ [Test]
+ public void Resolves_Action_Handlers()
+ {
+ var types = PluginManager.Current.ResolveActionHandlers();
+ Assert.AreEqual(1, types.Count());
+ }
- [Test]
- public void Resolves_DataTypes()
- {
- var types = PluginManager.Current.ResolveDataTypes();
- Assert.AreEqual(37, types.Count());
- }
+ [Test]
+ public void Resolves_DataTypes()
+ {
+ var types = PluginManager.Current.ResolveDataTypes();
+ Assert.AreEqual(37, types.Count());
+ }
- [Test]
- public void Resolves_RazorDataTypeModels()
- {
- var types = PluginManager.Current.ResolveRazorDataTypeModels();
- Assert.AreEqual(2, types.Count());
- }
+ [Test]
+ public void Resolves_RazorDataTypeModels()
+ {
+ var types = PluginManager.Current.ResolveRazorDataTypeModels();
+ Assert.AreEqual(2, types.Count());
+ }
- [Test]
- public void Resolves_RestExtensions()
- {
- var types = PluginManager.Current.ResolveRestExtensions();
- Assert.AreEqual(2, types.Count());
- }
+ [Test]
+ public void Resolves_RestExtensions()
+ {
+ var types = PluginManager.Current.ResolveRestExtensions();
+ Assert.AreEqual(2, types.Count());
+ }
- [Test]
- public void Resolves_LegacyRestExtensions()
- {
- var types = PluginManager.Current.ResolveLegacyRestExtensions();
- Assert.AreEqual(1, types.Count());
- }
+ [Test]
+ public void Resolves_LegacyRestExtensions()
+ {
+ var types = PluginManager.Current.ResolveLegacyRestExtensions();
+ Assert.AreEqual(1, types.Count());
+ }
- [Test]
- public void Resolves_XsltExtensions()
- {
- var types = PluginManager.Current.ResolveXsltExtensions();
- Assert.AreEqual(1, types.Count());
- }
+ [Test]
+ public void Resolves_XsltExtensions()
+ {
+ var types = PluginManager.Current.ResolveXsltExtensions();
+ Assert.AreEqual(1, types.Count());
+ }
- [XsltExtension("Blah.Blah")]
- public class MyXsltExtension
- {
+ [XsltExtension("Blah.Blah")]
+ public class MyXsltExtension
+ {
- }
+ }
- [umbraco.presentation.umbracobase.RestExtension("Blah")]
- public class MyLegacyRestExtension
- {
-
- }
+ [umbraco.presentation.umbracobase.RestExtension("Blah")]
+ public class MyLegacyRestExtension
+ {
- [Umbraco.Web.BaseRest.RestExtension("Blah")]
- public class MyRestExtesion
- {
-
- }
+ }
- public interface IFindMe
- {
+ [Umbraco.Web.BaseRest.RestExtension("Blah")]
+ public class MyRestExtesion
+ {
- }
+ }
- public class FindMe1 : IFindMe
- {
+ public interface IFindMe
+ {
- }
+ }
- public class FindMe2 : IFindMe
- {
+ public class FindMe1 : IFindMe
+ {
- }
+ }
- }
+ public class FindMe2 : IFindMe
+ {
+
+ }
+
+ }
}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
index 09f7669e06..eeae94e920 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
@@ -36,11 +36,16 @@
Add new Domain
+ Invalid hostname
Domain
New domain '%0%' has been created
Domain '%0%' is deleted
Domain '%0%' has already been assigned
- ei: yourdomain.com, www.yourdomain.com
+
+
+ https://www.example.com/, example.com/en, etc. Use * to match
+ any domain and just set the culture.]]>
+
Domain '%0%' has been updated
Edit Current Domains
@@ -69,6 +74,7 @@
Save and publish
Save and send for approval
Preview
+ Preview is disabled because there's no template assigned
Choose style
Show styles
Insert table
@@ -88,7 +94,7 @@
This item is not published
Last published
Media Type
- Link to media item(s)
+ Link to media item(s)
Member Group
Role
Member Type
@@ -164,18 +170,24 @@
The website cache will be refreshed. All published content will be updated, while unpublished content will stay unpublished.
Number of columns
Number of rows
- Set a placeholder id by setting an ID on your placeholder you can inject content into this template from child templates,
- by refering this ID using a <asp:content /> element.]]>
- Select a placeholder id from the list below. You can only
- choose Id's from the current template's master.]]>
+
+ Set a placeholder id by setting an ID on your placeholder you can inject content into this template from child templates,
+ by refering this ID using a <asp:content /> element.]]>
+
+
+ Select a placeholder id from the list below. You can only
+ choose Id's from the current template's master.]]>
+
Click on the image to see full size
Pick item
View Cache Item
-
+ %0%' below
You can add additional languages under the 'languages' in the menu on the left
- ]]>
+ ]]>
+
Culture Name
@@ -340,34 +352,45 @@
Could not save the web.config file. Please modify the connection string manually.
Your database has been found and is identified as
Database configuration
-
+ install button to install the Umbraco %0% database
- ]]>
+ ]]>
+
Next to proceed.]]>
- Database not found! Please check that the information in the "connection string" of the “web.config” file is correct.
+
+ Database not found! Please check that the information in the "connection string" of the “web.config” file is correct.
To proceed, please edit the "web.config" file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named "umbracoDbDSN" and save the file.
Click the retry button when
done.
- More information on editing web.config here.
]]>
-
+ More information on editing web.config here.]]>
+
+
+
Please contact your ISP if necessary.
- If you're installing on a local machine or server you might need information from your system administrator.]]>
-
+
+
+
Press the upgrade button to upgrade your database to Umbraco %0%
Don't worry - no content will be deleted and everything will continue working afterwards!
- ]]>
- Press Next to
- proceed. ]]>
+ ]]>
+
+
+ Press Next to
+ proceed. ]]>
+
next to continue the configuration wizard]]>
The Default users’ password needs to be changed!]]>
The Default user has been disabled or has no access to umbraco!No further actions needs to be taken. Click Next to proceed.]]>
The Default user's password has been successfully changed since the installation!No further actions needs to be taken. Click Next to proceed.]]>
The password is changed!
-
+
umbraco creates a default user with a login ('admin') and password ('default'). It's important that the password is
changed to something unique.
@@ -375,48 +398,64 @@
This step will check the default user's password and suggest if it needs to be changed.
- ]]>
+ ]]>
+
Get a great start, watch our introduction videos
By clicking the next button (or modifying the umbracoConfigurationStatus in web.config), you accept the license for this software as specified in the box below. Notice that this umbraco distribution consists of two different licenses, the open source MIT license for the framework and the umbraco freeware license that covers the UI.
Not installed yet.
Affected files and folders
More information on setting up permissions for umbraco here
You need to grant ASP.NET modify permissions to the following files/folders
- Your permission settings are almost perfect!
- You can run umbraco without problems, but you will not be able to install packages which are recommended to take full advantage of umbraco.]]>
+
+ Your permission settings are almost perfect!
+ You can run umbraco without problems, but you will not be able to install packages which are recommended to take full advantage of umbraco.]]>
+
How to Resolve
Click here to read the text version
video tutorial on setting up folder permissions for umbraco or read the text version.]]>
- Your permission settings might be an issue!
+
+ Your permission settings might be an issue!
- You can run umbraco without problems, but you will not be able to create folders or install packages which are recommended to take full advantage of umbraco.]]>
- Your permission settings are not ready for umbraco!
+ You can run umbraco without problems, but you will not be able to create folders or install packages which are recommended to take full advantage of umbraco.]]>
+
+
+ Your permission settings are not ready for umbraco!
- In order to run umbraco, you'll need to update your permission settings.]]>
- Your permission settings are perfect!
- You are ready to run umbraco and install packages!]]>
+ In order to run umbraco, you'll need to update your permission settings.]]>
+
+
+ Your permission settings are perfect!
+ You are ready to run umbraco and install packages!]]>
+
Resolving folder issue
Follow this link for more information on problems with ASP.NET and creating folders
Setting up folder permissions
-
+
+ ]]>
+
I want to start from scratch
-
+ learn how)
You can still choose to install Runway later on. Please go to the Developer section and choose Packages.
- ]]>
+ ]]>
+
You’ve just set up a clean Umbraco platform. What do you want to do next?
Runway is installed
-
+
This is our list of recommended modules, check off the ones you would like to install, or view the full list of modules
- ]]>
+ ]]>
+
Only recommended for experienced users
I want to start with a simple website
-
+
"Runway" is a simple website providing some basic document types and templates. The installer can set up Runway for you automatically,
but you can easily edit, extend or remove it. It’s not necessary and you can perfectly use Umbraco without it. However,
@@ -427,7 +466,8 @@
Included with Runway: Home page, Getting Started page, Installing Modules page.
Optional Modules: Top Navigation, Sitemap, Contact, Gallery.
- ]]>
+ ]]>
+
What is Runway
Step 1/5 Accept license
Step 2/5: Database configuration
@@ -435,24 +475,36 @@
Step 4/5: Check umbraco security
Step 5/5: Umbraco is ready to get you started
Thank you for choosing umbraco
- Browse your new site
-You installed Runway, so why not see how your new website looks.]]>
- Further help and information
-Get help from our award winning community, browse the documentation or watch some free videos on how to build a simple site, how to use packages and a quick guide to the umbraco terminology]]>
+
+ Browse your new site
+You installed Runway, so why not see how your new website looks.]]>
+
+
+ Further help and information
+Get help from our award winning community, browse the documentation or watch some free videos on how to build a simple site, how to use packages and a quick guide to the umbraco terminology]]>
+
Umbraco %0% is installed and ready for use
- /web.config file and update the AppSetting key umbracoConfigurationStatus in the bottom to the value of '%0%'.]]>
- started instantly by clicking the "Launch Umbraco" button below.
If you are new to umbraco,
-you can find plenty of resources on our getting started pages.]]>
- Launch Umbraco
-To manage your website, simply open the umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]>
+
+ /web.config file and update the AppSetting key umbracoConfigurationStatus in the bottom to the value of '%0%'.]]>
+
+
+ started instantly by clicking the "Launch Umbraco" button below.
If you are new to umbraco,
+you can find plenty of resources on our getting started pages.]]>
+
+
+ Launch Umbraco
+To manage your website, simply open the umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]>
+
Connection to database failed.
Umbraco Version 3
Umbraco Version 4
Watch
- umbraco %0% for a fresh install or upgrading from version 3.0.
+
+ umbraco %0% for a fresh install or upgrading from version 3.0.
- Press "next" to start the wizard.]]>
+ Press "next" to start the wizard.]]>
+
Culture Code
@@ -486,7 +538,8 @@ To manage your website, simply open the umbraco back office and start adding con
Edit your notification for %0%
-
+
- Hi %0%
+ ]]>
+
+
+ Hi %0%
This is an automated mail to inform you that the task '%1%'
has been performed on the page '%2%'
@@ -529,23 +584,28 @@ To manage your website, simply open the umbraco back office and start adding con
Have a nice day!
Cheers from the umbraco robot
-
]]>
+ ]]>
+
[%0%] Notification about %1% performed on %2%
Notifications
-
+
button and locating the package. umbraco packages usually have a ".umb" or ".zip" extension.
- ]]>
+ ]]>
+
Author
Demonstration
Documentation
Package meta data
Package name
Package doesn't contain any items
-
- You can safely remove this from the system by clicking "uninstall package" below.]]>
+
+
+ You can safely remove this from the system by clicking "uninstall package" below.]]>
+
No upgrades available
Package options
Package readme
@@ -554,9 +614,11 @@ To manage your website, simply open the umbraco back office and start adding con
Package was uninstalled
The package was successfully uninstalled
Uninstall package
-
+
+
Notice: any documents, media etc depending on the items you remove, will stop working, and could lead to system instability,
- so uninstall with caution. If in doubt, contact the package author.]]>
+ so uninstall with caution. If in doubt, contact the package author.]]>
+
Download update from the repository
Upgrade package
Upgrade instructions
@@ -589,18 +651,27 @@ To manage your website, simply open the umbraco back office and start adding con
If you just want to setup simple protection using a single login and password
-
+
+ ]]>
+
+
+
+
Include unpublished child pages
Publishing in progress - please wait...
%0% out of %1% pages have been published...
%0% has been published
%0% and subpages have been published
Publish %0% and all its subpages
- ok to publish %0% and thereby making it's content publicly available.
+
+ ok to publish %0% and thereby making it's content publicly available.
You can publish this page and all it's sub-pages by checking publish all children below.
- ]]>
+ ]]>
+
Add external link
@@ -652,6 +723,9 @@ To manage your website, simply open the umbraco back office and start adding con
Tab
Tab Title
Tabs
+ Master Content Type enabled
+ This Content Type uses
+ as a Master Content Type. Tabs from Master Content Types are not shown and can only be edited on the Master Content Type itself
Sorting complete.
@@ -686,7 +760,7 @@ To manage your website, simply open the umbraco back office and start adding con
Template saved
Error saving user (check log)
User Saved
- User type saved
+ User type saved
File not saved
file could not be saved. Please check file permissions
File saved
@@ -732,7 +806,7 @@ To manage your website, simply open the umbraco back office and start adding con
Choose field
Convert Linebreaks
Replaces linebreaks with html-tag <br>
- Custom Fields
+ Custom Fields
Yes, Date only
Format as date
HTML encode
@@ -746,7 +820,7 @@ To manage your website, simply open the umbraco back office and start adding con
Recursive
Remove Paragraph tags
Will remove any <P> in the beginning and end of the text
- Standard Fields
+ Standard Fields
Uppercase
URL encode
Will format special characters in URLs
@@ -756,10 +830,12 @@ To manage your website, simply open the umbraco back office and start adding con
Tasks assigned to you
- assigned to you. To see a detailed view including comments, click on "Details" or just the page name.
+
+ assigned to you. To see a detailed view including comments, click on "Details" or just the page name.
You can also download the page as XML directly by clicking the "Download Xml" link.
To close a translation task, please go to the Details view and click the "Close" button.
- ]]>
+ ]]>
+
close task
Translation details
Download all translation tasks as xml
@@ -767,7 +843,8 @@ To manage your website, simply open the umbraco back office and start adding con
Download xml DTD
Fields
Include subpages
-
+
+ ]]>
+
[%0%] Translation task for %1%
No translator users found. Please create a translator user before you start sending content to translation
Tasks created by you
- created by you. To see a detailed view including comments,
+
+ created by you. To see a detailed view including comments,
click on "Details" or just the page name. You can also download the page as XML directly by clicking the "Download Xml" link.
To close a translation task, please go to the Details view and click the "Close" button.
- ]]>
+ ]]>
+
The page '%0%' has been send to translation
Send the page '%0%' to translation
Assigned by
@@ -821,7 +901,7 @@ To manage your website, simply open the umbraco back office and start adding con
Member Types
Document Types
Packages
- Packages
+ Packages
Python Files
Install from repository
Install Runway
@@ -842,6 +922,8 @@ To manage your website, simply open the umbraco back office and start adding con
Administrator
Category field
Change Your Password
+ Change Your Password
+ Confirm new password
You can change your password for accessing the Umbraco Back Office by filling out the form below and click the 'Change Password' button
Content Channel
Redirect to canvas on login
@@ -859,9 +941,9 @@ To manage your website, simply open the umbraco back office and start adding con
Your password has been changed!
Please confirm the new password
Enter your new password
- Your new password cannot be blank!
- Current password
- Invalid current password
+ Your new password cannot be blank!
+ Current password
+ Invalid current password
There was a difference between the new password and the confirmed password. Please try again!
The confirmed password doesn't match the new password!
Replace child node permssions
diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/AssignDomain.aspx b/src/Umbraco.Web.UI/umbraco/dialogs/AssignDomain.aspx
index 7154a241c1..a2ecac4be2 100644
--- a/src/Umbraco.Web.UI/umbraco/dialogs/AssignDomain.aspx
+++ b/src/Umbraco.Web.UI/umbraco/dialogs/AssignDomain.aspx
@@ -22,6 +22,7 @@
+
<%= umbraco.ui.Text("assignDomain", "domainHelp") %>
diff --git a/src/Umbraco.Web/Routing/DomainHelper.cs b/src/Umbraco.Web/Routing/DomainHelper.cs
index 8720008392..7c1f22a820 100644
--- a/src/Umbraco.Web/Routing/DomainHelper.cs
+++ b/src/Umbraco.Web/Routing/DomainHelper.cs
@@ -44,9 +44,29 @@ namespace Umbraco.Web.Routing
private static bool IsWildcardDomain(Domain d)
{
+ // supporting null or whitespace for backward compatibility,
+ // although we should not allow ppl to create them anymore
return string.IsNullOrWhiteSpace(d.Name) || d.Name.StartsWith("*");
}
+ private static Domain SanitizeForBackwardCompatibility(Domain d)
+ {
+ // this is a _really_ nasty one that should be removed in 6.x
+ // some people were using hostnames such as "/en" which happened to work pre-4.10
+ // but make _no_ sense at all... and 4.10 throws on them, so here we just try
+ // to find a way so 4.11 does not throw.
+ // but, really.
+ // no.
+ var context = System.Web.HttpContext.Current;
+ if (context != null && d.Name.StartsWith("/"))
+ {
+ // turn /en into http://whatever.com/en so it becomes a parseable uri
+ var authority = context.Request.Url.GetLeftPart(UriPartial.Authority);
+ d.Name = authority + d.Name;
+ }
+ return d;
+ }
+
///
/// Finds the domain that best matches the current uri, into an enumeration of domains.
///
@@ -62,6 +82,7 @@ namespace Umbraco.Web.Routing
var scheme = current == null ? Uri.UriSchemeHttp : current.Scheme;
var domainsAndUris = domains
.Where(d => !IsWildcardDomain(d))
+ .Select(d => SanitizeForBackwardCompatibility(d))
.Select(d => new { Domain = d, UriString = UriUtility.EndPathWithSlash(UriUtility.StartWithScheme(d.Name, scheme)) })
.OrderByDescending(t => t.UriString)
.Select(t => new DomainAndUri { Domain = t.Domain, Uri = new Uri(t.UriString) });
@@ -102,6 +123,7 @@ namespace Umbraco.Web.Routing
var scheme = current == null ? Uri.UriSchemeHttp : current.Scheme;
var domainsAndUris = domains
.Where(d => !IsWildcardDomain(d))
+ .Select(d => SanitizeForBackwardCompatibility(d))
.Select(d => new { Domain = d, UriString = UriUtility.TrimPathEndSlash(UriUtility.StartWithScheme(d.Name, scheme)) })
.OrderByDescending(t => t.UriString)
.Select(t => new DomainAndUri { Domain = t.Domain, Uri = new Uri(t.UriString) });
@@ -117,11 +139,12 @@ namespace Umbraco.Web.Routing
public static bool ExistsDomainInPath(Domain current, string path)
{
var domains = Domain.GetDomains();
+ var stopNodeId = current == null ? -1 : current.RootNodeId;
return path.Split(',')
.Reverse()
.Select(id => int.Parse(id))
- .TakeWhile(id => id != current.RootNodeId)
+ .TakeWhile(id => id != stopNodeId)
.Any(id => domains.Any(d => d.RootNodeId == id && !IsWildcardDomain(d)));
}
@@ -134,20 +157,21 @@ namespace Umbraco.Web.Routing
/// The deepest wildcard in the path, or null.
public static Domain LookForWildcardDomain(IEnumerable domains, string path, int? rootNodeId)
{
- var nodeIds = path.Split(',').Select(p => int.Parse(p)).Reverse();
- rootNodeId = rootNodeId ?? -1; // every paths begin with -1
+ var nodeIds = path.Split(',').Select(p => int.Parse(p)).Skip(1).Reverse();
foreach (var nodeId in nodeIds)
{
- if (nodeId == rootNodeId) // stop at current domain or root
- break;
-
- // supporting null or whitespace for backward compatibility,
- // although we should not allow ppl to create them anymore
var domain = domains.Where(d => d.RootNodeId == nodeId && IsWildcardDomain(d)).FirstOrDefault();
if (domain != null)
return domain;
+
+ // stop at current domain root if any
+ // "When you perform comparisons with nullable types, if the value of one of the nullable
+ // types is null and the other is not, all comparisons evaluate to false."
+ if (nodeId == rootNodeId)
+ break;
}
+
return null;
}
diff --git a/src/Umbraco.Web/Routing/LookupByNiceUrl.cs b/src/Umbraco.Web/Routing/LookupByNiceUrl.cs
index 68201051bb..d802555387 100644
--- a/src/Umbraco.Web/Routing/LookupByNiceUrl.cs
+++ b/src/Umbraco.Web/Routing/LookupByNiceUrl.cs
@@ -82,13 +82,9 @@ namespace Umbraco.Web.Routing
docreq.PublishedContent = node;
LogHelper.Debug("Query matches, id={0}", () => docreq.DocumentId);
- var iscanon = true;
- if (docreq.HasDomain)
- {
- iscanon = !DomainHelper.ExistsDomainInPath(docreq.Domain, node.Path);
- if (!iscanon)
- LogHelper.Debug("Non canonical url");
- }
+ var iscanon = !DomainHelper.ExistsDomainInPath(docreq.Domain, node.Path);
+ if (!iscanon)
+ LogHelper.Debug("Non canonical url");
// do not store if previewing or if non-canonical
if (!docreq.RoutingContext.UmbracoContext.InPreviewMode && iscanon)
diff --git a/src/Umbraco.Web/Routing/NiceUrlProvider.cs b/src/Umbraco.Web/Routing/NiceUrlProvider.cs
index a3a3f622fe..0ac02197c3 100644
--- a/src/Umbraco.Web/Routing/NiceUrlProvider.cs
+++ b/src/Umbraco.Web/Routing/NiceUrlProvider.cs
@@ -278,7 +278,7 @@ namespace Umbraco.Web.Routing
{
// domains were found : return absolute urls
// ignore vdir at that point
- uris.AddRange(domainUris.Select(domainUri => new Uri(domainUri.GetLeftPart(UriPartial.Path).TrimEnd('/') + path)));
+ uris.AddRange(domainUris.Select(domainUri => new Uri(CombinePaths(domainUri.GetLeftPart(UriPartial.Path), path))));
}
// UriFromUmbraco will handle vdir
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index ac9c9361e5..b949df8da7 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -1925,7 +1925,9 @@
-
+
+ ASPXCodeBehind
+
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx
index 7154a241c1..a2ecac4be2 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx
@@ -22,6 +22,7 @@
+
<%= umbraco.ui.Text("assignDomain", "domainHelp") %>
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx.cs
index 7c9d0f71c9..f663fdee0d 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx.cs
@@ -58,6 +58,10 @@ namespace umbraco.dialogs
LanguageValidator.ErrorMessage = ui.Text("defaultdialogs", "requiredField", base.getUser()) + "
";
DomainValidator.ErrorMessage = ui.Text("defaultdialogs", "requiredField", base.getUser());
+ DomainValidator2.ErrorMessage = ui.Text("assignDomain", "invalidDomain", base.getUser());
+ //DomainValidator2.ValidationExpression = @"^(?i:http[s]?://)?([-\w]+(\.[-\w]+)*)(:\d+)?(/[-\w]*)?$";
+ DomainValidator2.ValidationExpression = @"^(\*|((?i:http[s]?://)?([-\w]+(\.[-\w]+)*)(:\d+)?(/[-\w]*)?))$";
+
Languages.Items.Add(new ListItem(ui.Text("general", "choose", base.getUser()), ""));
foreach (Language l in Language.getAll)
{
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx.designer.cs
index 6b4692dbdd..07464f0501 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx.designer.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain.aspx.designer.cs
@@ -57,6 +57,15 @@ namespace umbraco.dialogs {
///
protected global::System.Web.UI.WebControls.RequiredFieldValidator DomainValidator;
+ ///
+ /// DomainValidator2 control.
+ ///
+ ///
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ ///
+ protected global::System.Web.UI.WebControls.RegularExpressionValidator DomainValidator2;
+
///
/// prop_lang control.
///
diff --git a/src/umbraco.cms/businesslogic/Packager/Installer.cs b/src/umbraco.cms/businesslogic/Packager/Installer.cs
index 9f4376fdee..ba8419448d 100644
--- a/src/umbraco.cms/businesslogic/Packager/Installer.cs
+++ b/src/umbraco.cms/businesslogic/Packager/Installer.cs
@@ -77,7 +77,7 @@ namespace umbraco.cms.businesslogic.packager
public bool ContainsMacroConflict { get { return _containsMacroConflict; } }
public IDictionary ConflictingMacroAliases { get { return _conflictingMacroAliases; } }
-
+
public bool ContainsUnsecureFiles { get { return _containUnsecureFiles; } }
public List UnsecureFiles { get { return _unsecureFiles; } }
@@ -146,7 +146,7 @@ namespace umbraco.cms.businesslogic.packager
_macros.Add(MacroToAdd);
}
-
+
///
/// Imports the specified package
@@ -155,38 +155,39 @@ namespace umbraco.cms.businesslogic.packager
///
public string Import(string InputFile)
{
- using (DisposableTimer.DebugDuration(
- () => "Importing package file " + InputFile,
- () => "Package file " + InputFile + "imported"))
- {
- string tempDir = "";
- if (File.Exists(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile)))
- {
- FileInfo fi = new FileInfo(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile));
- // Check if the file is a valid package
- if (fi.Extension.ToLower() == ".umb")
- {
- try
- {
- tempDir = unPack(fi.FullName);
- LoadConfig(tempDir);
- }
- catch (Exception unpackE)
- {
- throw new Exception("Error unpacking extension...", unpackE);
- }
- }
- else
- throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download.");
- }
- else
- throw new Exception("Error - file not found. Could find file named '" + IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile) + "'");
- return tempDir;
- }
+ using (DisposableTimer.DebugDuration(
+ () => "Importing package file " + InputFile,
+ () => "Package file " + InputFile + "imported"))
+ {
+ string tempDir = "";
+ if (File.Exists(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile)))
+ {
+ FileInfo fi = new FileInfo(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile));
+ // Check if the file is a valid package
+ if (fi.Extension.ToLower() == ".umb")
+ {
+ try
+ {
+ tempDir = unPack(fi.FullName);
+ LoadConfig(tempDir);
+ }
+ catch (Exception unpackE)
+ {
+ throw new Exception("Error unpacking extension...", unpackE);
+ }
+ }
+ else
+ throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download.");
+ }
+ else
+ throw new Exception("Error - file not found. Could find file named '" + IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile) + "'");
+ return tempDir;
+ }
}
- public int CreateManifest(string tempDir, string guid, string repoGuid) {
+ public int CreateManifest(string tempDir, string guid, string repoGuid)
+ {
//This is the new improved install rutine, which chops up the process into 3 steps, creating the manifest, moving files, and finally handling umb objects
string _packName = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/name"));
string _packAuthor = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/name"));
@@ -222,266 +223,268 @@ namespace umbraco.cms.businesslogic.packager
insPack.Data.PackageGuid = guid; //the package unique key.
insPack.Data.RepositoryGuid = repoGuid; //the repository unique key, if the package is a file install, the repository will not get logged.
insPack.Save();
-
+
return insPack.Data.Id;
}
- public void InstallFiles(int packageId, string tempDir)
- {
- using (DisposableTimer.DebugDuration(
- () => "Installing package files for package id " + packageId + " into temp folder " + tempDir,
- () => "Package file installation complete for package id " + packageId))
- {
- //retrieve the manifest to continue installation
- packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId);
+ public void InstallFiles(int packageId, string tempDir)
+ {
+ using (DisposableTimer.DebugDuration(
+ () => "Installing package files for package id " + packageId + " into temp folder " + tempDir,
+ () => "Package file installation complete for package id " + packageId))
+ {
+ //retrieve the manifest to continue installation
+ packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId);
- // Move files
- //string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath;
- string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
+ // Move files
+ //string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath;
+ string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//file"))
- {
- //we enclose the whole file-moving to ensure that the entire installer doesn't crash
- try
- {
- String destPath = getFileName(basePath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")));
- String sourceFile = getFileName(tempDir, xmlHelper.GetNodeValue(n.SelectSingleNode("guid")));
- String destFile = getFileName(destPath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//file"))
+ {
+ //we enclose the whole file-moving to ensure that the entire installer doesn't crash
+ try
+ {
+ String destPath = getFileName(basePath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")));
+ String sourceFile = getFileName(tempDir, xmlHelper.GetNodeValue(n.SelectSingleNode("guid")));
+ String destFile = getFileName(destPath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
- // Create the destination directory if it doesn't exist
- if (!Directory.Exists(destPath))
- Directory.CreateDirectory(destPath);
- //If a file with this name exists, delete it
- else if (File.Exists(destFile))
- File.Delete(destFile);
+ // Create the destination directory if it doesn't exist
+ if (!Directory.Exists(destPath))
+ Directory.CreateDirectory(destPath);
+ //If a file with this name exists, delete it
+ else if (File.Exists(destFile))
+ File.Delete(destFile);
- // Move the file
- File.Move(sourceFile, destFile);
+ // Move the file
+ File.Move(sourceFile, destFile);
- //PPH log file install
- insPack.Data.Files.Add(xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
- }
- catch (Exception ex)
- {
- Log.Add(LogTypes.Error, -1, "Package install error: " + ex.ToString());
- }
- }
+ //PPH log file install
+ insPack.Data.Files.Add(xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
+ }
+ catch (Exception ex)
+ {
+ Log.Add(LogTypes.Error, -1, "Package install error: " + ex.ToString());
+ }
+ }
- insPack.Save();
- }
+ insPack.Save();
+ }
}
- public void InstallBusinessLogic(int packageId, string tempDir) {
+ public void InstallBusinessLogic(int packageId, string tempDir)
+ {
- using (DisposableTimer.DebugDuration(
- () => "Installing business logic for package id " + packageId + " into temp folder " + tempDir,
- () => "Package business logic installation complete for package id " + packageId))
- {
- //retrieve the manifest to continue installation
- packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId);
- bool saveNeeded = false;
+ using (DisposableTimer.DebugDuration(
+ () => "Installing business logic for package id " + packageId + " into temp folder " + tempDir,
+ () => "Package business logic installation complete for package id " + packageId))
+ {
+ //retrieve the manifest to continue installation
+ packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId);
+ bool saveNeeded = false;
- //Install DataTypes
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//DataType"))
- {
- cms.businesslogic.datatype.DataTypeDefinition newDtd = cms.businesslogic.datatype.DataTypeDefinition.Import(n);
+ //Install DataTypes
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//DataType"))
+ {
+ cms.businesslogic.datatype.DataTypeDefinition newDtd = cms.businesslogic.datatype.DataTypeDefinition.Import(n);
- if (newDtd != null)
- {
- insPack.Data.DataTypes.Add(newDtd.Id.ToString());
- saveNeeded = true;
- }
- }
+ if (newDtd != null)
+ {
+ insPack.Data.DataTypes.Add(newDtd.Id.ToString());
+ saveNeeded = true;
+ }
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- //Install languages
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//Language"))
- {
- language.Language newLang = language.Language.Import(n);
+ //Install languages
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//Language"))
+ {
+ language.Language newLang = language.Language.Import(n);
- if (newLang != null)
- {
- insPack.Data.Languages.Add(newLang.id.ToString());
- saveNeeded = true;
- }
- }
+ if (newLang != null)
+ {
+ insPack.Data.Languages.Add(newLang.id.ToString());
+ saveNeeded = true;
+ }
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- //Install dictionary items
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("./DictionaryItems/DictionaryItem"))
- {
- Dictionary.DictionaryItem newDi = Dictionary.DictionaryItem.Import(n);
+ //Install dictionary items
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("./DictionaryItems/DictionaryItem"))
+ {
+ Dictionary.DictionaryItem newDi = Dictionary.DictionaryItem.Import(n);
- if (newDi != null)
- {
- insPack.Data.DictionaryItems.Add(newDi.id.ToString());
- saveNeeded = true;
- }
- }
+ if (newDi != null)
+ {
+ insPack.Data.DictionaryItems.Add(newDi.id.ToString());
+ saveNeeded = true;
+ }
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- // Install macros
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//macro"))
- {
- cms.businesslogic.macro.Macro m = cms.businesslogic.macro.Macro.Import(n);
+ // Install macros
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//macro"))
+ {
+ cms.businesslogic.macro.Macro m = cms.businesslogic.macro.Macro.Import(n);
- if (m != null)
- {
- insPack.Data.Macros.Add(m.Id.ToString());
- saveNeeded = true;
- }
- }
+ if (m != null)
+ {
+ insPack.Data.Macros.Add(m.Id.ToString());
+ saveNeeded = true;
+ }
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- // Get current user, with a fallback
- User u = new User(0);
- if (!string.IsNullOrEmpty(BasePages.UmbracoEnsuredPage.umbracoUserContextID))
- {
- if (BasePages.UmbracoEnsuredPage.ValidateUserContextID(BasePages.UmbracoEnsuredPage.umbracoUserContextID))
- {
- u = User.GetCurrent();
- }
- }
+ // Get current user, with a fallback
+ User u = new User(0);
+ if (!string.IsNullOrEmpty(BasePages.UmbracoEnsuredPage.umbracoUserContextID))
+ {
+ if (BasePages.UmbracoEnsuredPage.ValidateUserContextID(BasePages.UmbracoEnsuredPage.umbracoUserContextID))
+ {
+ u = User.GetCurrent();
+ }
+ }
- // Add Templates
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template"))
- {
- var t = Template.Import(n, u);
+ // Add Templates
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template"))
+ {
+ var t = Template.Import(n, u);
- insPack.Data.Templates.Add(t.Id.ToString());
+ insPack.Data.Templates.Add(t.Id.ToString());
- saveNeeded = true;
- }
+ saveNeeded = true;
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- //NOTE: SD: I'm pretty sure the only thing the below script does is ensure that the Master template Id is set
- // in the database, but this is also duplicating the saving of the design content since the above Template.Import
- // already does this. I've left this for now because I'm not sure the reprocussions of removing it but seems there
- // is a lot of excess database calls happening here.
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template"))
- {
- string master = xmlHelper.GetNodeValue(n.SelectSingleNode("Master"));
- template.Template t = template.Template.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Alias")));
- if (master.Trim() != "")
- {
- template.Template masterTemplate = template.Template.GetByAlias(master);
- if (masterTemplate != null)
- {
- t.MasterTemplate = template.Template.GetByAlias(master).Id;
- //SD: This appears to always just save an empty template because the design isn't set yet
- // this fixes an issue now that we have MVC because if there is an empty template and MVC is
- // the default, it will create a View not a master page and then the system will try to route via
- // MVC which means that the package will not work anymore.
- // The code below that imports the templates should suffice because it's actually importing
- // template data not just blank data.
+ //NOTE: SD: I'm pretty sure the only thing the below script does is ensure that the Master template Id is set
+ // in the database, but this is also duplicating the saving of the design content since the above Template.Import
+ // already does this. I've left this for now because I'm not sure the reprocussions of removing it but seems there
+ // is a lot of excess database calls happening here.
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template"))
+ {
+ string master = xmlHelper.GetNodeValue(n.SelectSingleNode("Master"));
+ template.Template t = template.Template.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Alias")));
+ if (master.Trim() != "")
+ {
+ template.Template masterTemplate = template.Template.GetByAlias(master);
+ if (masterTemplate != null)
+ {
+ t.MasterTemplate = template.Template.GetByAlias(master).Id;
+ //SD: This appears to always just save an empty template because the design isn't set yet
+ // this fixes an issue now that we have MVC because if there is an empty template and MVC is
+ // the default, it will create a View not a master page and then the system will try to route via
+ // MVC which means that the package will not work anymore.
+ // The code below that imports the templates should suffice because it's actually importing
+ // template data not just blank data.
- //if (UmbracoSettings.UseAspNetMasterPages)
- // t.SaveMasterPageFile(t.Design);
- }
- }
- // Master templates can only be generated when their master is known
- if (UmbracoSettings.UseAspNetMasterPages)
- {
- t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design")));
- t.SaveMasterPageFile(t.Design);
- }
- }
+ //if (UmbracoSettings.UseAspNetMasterPages)
+ // t.SaveMasterPageFile(t.Design);
+ }
+ }
+ // Master templates can only be generated when their master is known
+ if (UmbracoSettings.UseAspNetMasterPages)
+ {
+ t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design")));
+ t.SaveMasterPageFile(t.Design);
+ }
+ }
- // Add documenttypes
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType"))
- {
- ImportDocumentType(n, u, false);
- saveNeeded = true;
- }
+ // Add documenttypes
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType"))
+ {
+ ImportDocumentType(n, u, false);
+ saveNeeded = true;
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- // Add documenttype structure
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType"))
- {
- DocumentType dt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Alias")));
- if (dt != null)
- {
- ArrayList allowed = new ArrayList();
- foreach (XmlNode structure in n.SelectNodes("Structure/DocumentType"))
- {
- DocumentType dtt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(structure));
- if (dtt != null)
- allowed.Add(dtt.Id);
- }
+ // Add documenttype structure
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType"))
+ {
+ DocumentType dt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Alias")));
+ if (dt != null)
+ {
+ ArrayList allowed = new ArrayList();
+ foreach (XmlNode structure in n.SelectNodes("Structure/DocumentType"))
+ {
+ DocumentType dtt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(structure));
+ if (dtt != null)
+ allowed.Add(dtt.Id);
+ }
- int[] adt = new int[allowed.Count];
- for (int i = 0; i < allowed.Count; i++)
- adt[i] = (int)allowed[i];
- dt.AllowedChildContentTypeIDs = adt;
+ int[] adt = new int[allowed.Count];
+ for (int i = 0; i < allowed.Count; i++)
+ adt[i] = (int)allowed[i];
+ dt.AllowedChildContentTypeIDs = adt;
- //PPH we log the document type install here.
- insPack.Data.Documenttypes.Add(dt.Id.ToString());
- saveNeeded = true;
- }
- }
+ //PPH we log the document type install here.
+ insPack.Data.Documenttypes.Add(dt.Id.ToString());
+ saveNeeded = true;
+ }
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- // Stylesheets
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Stylesheets/Stylesheet"))
- {
- StyleSheet s = StyleSheet.Import(n, u);
+ // Stylesheets
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Stylesheets/Stylesheet"))
+ {
+ StyleSheet s = StyleSheet.Import(n, u);
- insPack.Data.Stylesheets.Add(s.Id.ToString());
- saveNeeded = true;
- }
+ insPack.Data.Stylesheets.Add(s.Id.ToString());
+ saveNeeded = true;
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- // Documents
- foreach (XmlElement n in _packageConfig.DocumentElement.SelectNodes("Documents/DocumentSet [@importMode = 'root']/*"))
- {
- insPack.Data.ContentNodeId = cms.businesslogic.web.Document.Import(-1, u, n).ToString();
- }
+ // Documents
+ foreach (XmlElement n in _packageConfig.DocumentElement.SelectNodes("Documents/DocumentSet [@importMode = 'root']/*"))
+ {
+ insPack.Data.ContentNodeId = cms.businesslogic.web.Document.Import(-1, u, n).ToString();
+ }
- //Package Actions
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action"))
- {
+ //Package Actions
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action"))
+ {
- if (n.Attributes["undo"] == null || n.Attributes["undo"].Value == "true")
- {
- insPack.Data.Actions += n.OuterXml;
- Log.Add(LogTypes.Debug, -1, HttpUtility.HtmlEncode(n.OuterXml));
- }
+ if (n.Attributes["undo"] == null || n.Attributes["undo"].Value == "true")
+ {
+ insPack.Data.Actions += n.OuterXml;
+ Log.Add(LogTypes.Debug, -1, HttpUtility.HtmlEncode(n.OuterXml));
+ }
- if (n.Attributes["runat"] != null && n.Attributes["runat"].Value == "install")
- {
- try
- {
- packager.PackageAction.RunPackageAction(insPack.Data.Name, n.Attributes["alias"].Value, n);
- }
- catch
- {
+ if (n.Attributes["runat"] != null && n.Attributes["runat"].Value == "install")
+ {
+ try
+ {
+ packager.PackageAction.RunPackageAction(insPack.Data.Name, n.Attributes["alias"].Value, n);
+ }
+ catch
+ {
- }
- }
- }
+ }
+ }
+ }
- // Trigger update of Apps / Trees config.
- // (These are ApplicationStartupHandlers so just instantiating them will trigger them)
- new ApplicationRegistrar();
- new ApplicationTreeRegistrar();
+ // Trigger update of Apps / Trees config.
+ // (These are ApplicationStartupHandlers so just instantiating them will trigger them)
+ new ApplicationRegistrar();
+ new ApplicationTreeRegistrar();
- insPack.Save();
- }
+ insPack.Save();
+ }
}
- public void InstallCleanUp(int packageId, string tempDir) {
+ public void InstallCleanUp(int packageId, string tempDir)
+ {
//this will contain some logic to clean up all those old folders
@@ -495,12 +498,12 @@ namespace umbraco.cms.businesslogic.packager
{
//PPH added logging of installs, this adds all install info in the installedPackages config file.
string _packName = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/name"));
- string _packAuthor= xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/name"));
+ string _packAuthor = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/name"));
string _packAuthorUrl = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/website"));
string _packVersion = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/version"));
string _packReadme = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/readme"));
string _packLicense = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/license "));
-
+
//Create a new package instance to record all the installed package adds - this is the same format as the created packages has.
//save the package meta data
@@ -512,10 +515,11 @@ namespace umbraco.cms.businesslogic.packager
insPack.Data.License = _packLicense;
insPack.Data.PackageGuid = guid; //the package unique key.
insPack.Data.RepositoryGuid = repoGuid; //the repository unique key, if the package is a file install, the repository will not get logged.
-
-
+
+
//Install languages
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//Language")) {
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//Language"))
+ {
language.Language newLang = language.Language.Import(n);
if (newLang != null)
@@ -523,11 +527,12 @@ namespace umbraco.cms.businesslogic.packager
}
//Install dictionary items
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("./DictionaryItems/DictionaryItem")) {
- Dictionary.DictionaryItem newDi = Dictionary.DictionaryItem.Import(n);
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("./DictionaryItems/DictionaryItem"))
+ {
+ Dictionary.DictionaryItem newDi = Dictionary.DictionaryItem.Import(n);
- if (newDi != null)
- insPack.Data.DictionaryItems.Add(newDi.id.ToString());
+ if (newDi != null)
+ insPack.Data.DictionaryItems.Add(newDi.id.ToString());
}
// Install macros
@@ -535,7 +540,7 @@ namespace umbraco.cms.businesslogic.packager
{
cms.businesslogic.macro.Macro m = cms.businesslogic.macro.Macro.Import(n);
- if(m != null)
+ if (m != null)
insPack.Data.Macros.Add(m.Id.ToString());
}
@@ -570,8 +575,8 @@ namespace umbraco.cms.businesslogic.packager
template.Template t = template.Template.MakeNew(xmlHelper.GetNodeValue(n.SelectSingleNode("Name")), u);
t.Alias = xmlHelper.GetNodeValue(n.SelectSingleNode("Alias"));
- t.ImportDesign( xmlHelper.GetNodeValue(n.SelectSingleNode("Design")) );
-
+ t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design")));
+
insPack.Data.Templates.Add(t.Id.ToString());
}
@@ -583,14 +588,16 @@ namespace umbraco.cms.businesslogic.packager
if (master.Trim() != "")
{
template.Template masterTemplate = template.Template.GetByAlias(master);
- if (masterTemplate != null) {
+ if (masterTemplate != null)
+ {
t.MasterTemplate = template.Template.GetByAlias(master).Id;
if (UmbracoSettings.UseAspNetMasterPages)
t.SaveMasterPageFile(t.Design);
}
}
// Master templates can only be generated when their master is known
- if (UmbracoSettings.UseAspNetMasterPages) {
+ if (UmbracoSettings.UseAspNetMasterPages)
+ {
t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design")));
t.SaveMasterPageFile(t.Design);
}
@@ -649,27 +656,32 @@ namespace umbraco.cms.businesslogic.packager
}
// Documents
- foreach (XmlElement n in _packageConfig.DocumentElement.SelectNodes("Documents/DocumentSet [@importMode = 'root']/*")) {
+ foreach (XmlElement n in _packageConfig.DocumentElement.SelectNodes("Documents/DocumentSet [@importMode = 'root']/*"))
+ {
cms.businesslogic.web.Document.Import(-1, u, n);
//PPH todo log document install...
}
-
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action [@runat != 'uninstall']")) {
- try {
+
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action [@runat != 'uninstall']"))
+ {
+ try
+ {
packager.PackageAction.RunPackageAction(_packName, n.Attributes["alias"].Value, n);
- } catch { }
+ }
+ catch { }
}
//saving the uninstall actions untill the package is uninstalled.
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action [@undo != false()]")) {
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action [@undo != false()]"))
+ {
insPack.Data.Actions += n.OuterXml;
}
-
-
+
+
insPack.Save();
-
-
+
+
}
public static void ImportDocumentType(XmlNode n, BusinessLogic.User u, bool ImportStructure)
@@ -680,7 +692,7 @@ namespace umbraco.cms.businesslogic.packager
dt = DocumentType.MakeNew(u, xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Name")));
dt.Alias = xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Alias"));
-
+
//Master content type
DocumentType mdt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Master")));
if (mdt != null)
@@ -691,7 +703,7 @@ namespace umbraco.cms.businesslogic.packager
dt.Text = xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Name"));
}
-
+
// Info
dt.IconUrl = xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Icon"));
dt.Thumbnail = xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Thumbnail"));
@@ -735,7 +747,7 @@ namespace umbraco.cms.businesslogic.packager
for (int t = 0; t < tabs.Length; t++)
tabNames += tabs[t].Caption + ";";
-
+
Hashtable ht = new Hashtable();
foreach (XmlNode t in n.SelectNodes("Tabs/Tab"))
@@ -759,19 +771,24 @@ namespace umbraco.cms.businesslogic.packager
// Generic Properties
datatype.controls.Factory f = new datatype.controls.Factory();
foreach (XmlNode gp in n.SelectNodes("GenericProperties/GenericProperty"))
- {
+ {
int dfId = 0;
Guid dtId = new Guid(xmlHelper.GetNodeValue(gp.SelectSingleNode("Type")));
- if (gp.SelectSingleNode("Definition") != null && !string.IsNullOrEmpty(xmlHelper.GetNodeValue(gp.SelectSingleNode("Definition")))) {
+ if (gp.SelectSingleNode("Definition") != null && !string.IsNullOrEmpty(xmlHelper.GetNodeValue(gp.SelectSingleNode("Definition"))))
+ {
Guid dtdId = new Guid(xmlHelper.GetNodeValue(gp.SelectSingleNode("Definition")));
if (CMSNode.IsNode(dtdId))
dfId = new CMSNode(dtdId).Id;
- }
- if (dfId == 0) {
- try {
+ }
+ if (dfId == 0)
+ {
+ try
+ {
dfId = findDataTypeDefinitionFromType(ref dtId);
- } catch {
+ }
+ catch
+ {
throw new Exception(String.Format("Could not find datatype with id {0}.", dtId));
}
}
@@ -867,22 +884,22 @@ namespace umbraco.cms.businesslogic.packager
//to support virtual dirs we try to lookup the file...
path = IOHelper.FindFile(path);
-
+
Debug.Assert(path != null && path.Length >= 1);
Debug.Assert(fileName != null && fileName.Length >= 1);
path = path.Replace('/', '\\');
- fileName = fileName.Replace('/','\\');
+ fileName = fileName.Replace('/', '\\');
// Does filename start with a slash? Does path end with one?
bool fileNameStartsWithSlash = (fileName[0] == Path.DirectorySeparatorChar);
- bool pathEndsWithSlash = (path[path.Length-1] == Path.DirectorySeparatorChar);
+ bool pathEndsWithSlash = (path[path.Length - 1] == Path.DirectorySeparatorChar);
// Path ends with a slash
if (pathEndsWithSlash)
{
- if(!fileNameStartsWithSlash)
+ if (!fileNameStartsWithSlash)
// No double slash, just concatenate
return path + fileName;
else
@@ -931,27 +948,29 @@ namespace umbraco.cms.businesslogic.packager
_reqPatch = int.Parse(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/requirements/patch").FirstChild.Value);
_authorName = _packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/name").FirstChild.Value;
_authorUrl = _packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/website").FirstChild.Value;
-
+
string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
-
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//file")) {
+
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//file"))
+ {
bool badFile = false;
string destPath = getFileName(basePath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")));
string destFile = getFileName(destPath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
- if (destPath.ToLower().Contains( IOHelper.DirSepChar + "app_code"))
+ if (destPath.ToLower().Contains(IOHelper.DirSepChar + "app_code"))
badFile = true;
- if (destPath.ToLower().Contains(IOHelper.DirSepChar + "bin"))
+ if (destPath.ToLower().Contains(IOHelper.DirSepChar + "bin"))
badFile = true;
- if (destFile.ToLower().EndsWith(".dll"))
- badFile = true;
+ if (destFile.ToLower().EndsWith(".dll"))
+ badFile = true;
- if (badFile) {
- _containUnsecureFiles = true;
- _unsecureFiles.Add(xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
- }
+ if (badFile)
+ {
+ _containUnsecureFiles = true;
+ _unsecureFiles.Add(xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
+ }
}
//this will check for existing macros with the same alias
@@ -1075,7 +1094,8 @@ namespace umbraco.cms.businesslogic.packager
}
- public static void updatePackageInfo(Guid Package, int VersionMajor, int VersionMinor, int VersionPatch, User User) {
+ public static void updatePackageInfo(Guid Package, int VersionMajor, int VersionMinor, int VersionPatch, User User)
+ {
}
}
@@ -1156,7 +1176,7 @@ namespace umbraco.cms.businesslogic.packager
if (Id == 0)
{
// The method is synchronized
- SqlHelper.ExecuteNonQuery("INSERT INTO umbracoInstalledPackages (uninstalled, upgradeId, installDate, userId, versionMajor, versionMinor, versionPatch) VALUES (@uninstalled, @upgradeId, @installDate, @userId, @versionMajor, @versionMinor, @versionPatch)",values);
+ SqlHelper.ExecuteNonQuery("INSERT INTO umbracoInstalledPackages (uninstalled, upgradeId, installDate, userId, versionMajor, versionMinor, versionPatch) VALUES (@uninstalled, @upgradeId, @installDate, @userId, @versionMajor, @versionMinor, @versionPatch)", values);
Id = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM umbracoInstalledPackages");
}
@@ -1180,7 +1200,7 @@ namespace umbraco.cms.businesslogic.packager
get { return _uninstalled; }
set { _uninstalled = value; }
}
-
+
private User _user;
@@ -1189,7 +1209,7 @@ namespace umbraco.cms.businesslogic.packager
get { return _user; }
set { _user = value; }
}
-
+
private DateTime _installDate;
@@ -1198,7 +1218,7 @@ namespace umbraco.cms.businesslogic.packager
get { return _installDate; }
set { _installDate = value; }
}
-
+
private int _id;
@@ -1207,7 +1227,7 @@ namespace umbraco.cms.businesslogic.packager
get { return _id; }
set { _id = value; }
}
-
+
private int _upgradeId;
@@ -1216,7 +1236,7 @@ namespace umbraco.cms.businesslogic.packager
get { return _upgradeId; }
set { _upgradeId = value; }
}
-
+
private Guid _packageId;
@@ -1225,7 +1245,7 @@ namespace umbraco.cms.businesslogic.packager
get { return _packageId; }
set { _packageId = value; }
}
-
+
private int _versionPatch;
@@ -1234,7 +1254,7 @@ namespace umbraco.cms.businesslogic.packager
get { return _versionPatch; }
set { _versionPatch = value; }
}
-
+
private int _versionMinor;
@@ -1243,7 +1263,7 @@ namespace umbraco.cms.businesslogic.packager
get { return _versionMinor; }
set { _versionMinor = value; }
}
-
+
private int _versionMajor;
@@ -1254,6 +1274,6 @@ namespace umbraco.cms.businesslogic.packager
}
-
+
}
}
diff --git a/src/umbraco.cms/businesslogic/template/ViewHelper.cs b/src/umbraco.cms/businesslogic/template/ViewHelper.cs
index f428aeaa5c..8de24710b7 100644
--- a/src/umbraco.cms/businesslogic/template/ViewHelper.cs
+++ b/src/umbraco.cms/businesslogic/template/ViewHelper.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
+using System.IO;
using System.Linq;
using System.Text;
using Umbraco.Core.IO;
@@ -27,7 +25,7 @@ namespace umbraco.cms.businesslogic.template
if (File.Exists(path))
{
- System.IO.TextReader tr = new StreamReader(path);
+ TextReader tr = new StreamReader(path);
viewContent = tr.ReadToEnd();
tr.Close();
}
@@ -37,14 +35,14 @@ namespace umbraco.cms.businesslogic.template
internal static string CreateViewFile(Template t, bool overWrite = false)
{
- string viewContent = "";
+ string viewContent;
string path = IOHelper.MapPath(ViewPath(t.Alias));
- if (!File.Exists(path) || overWrite)
+ if (File.Exists(path) == false || overWrite)
viewContent = SaveTemplateToFile(t, t.Alias);
else
{
- System.IO.TextReader tr = new StreamReader(path);
+ TextReader tr = new StreamReader(path);
viewContent = tr.ReadToEnd();
tr.Close();
}
@@ -55,7 +53,7 @@ namespace umbraco.cms.businesslogic.template
internal static string SaveTemplateToFile(Template template, string currentAlias)
{
var design = EnsureInheritedLayout(template);
- System.IO.File.WriteAllText(IOHelper.MapPath(ViewPath(template.Alias)), design, Encoding.UTF8);
+ File.WriteAllText(IOHelper.MapPath(ViewPath(template.Alias)), design, Encoding.UTF8);
return template.Design;
}
@@ -64,7 +62,7 @@ namespace umbraco.cms.businesslogic.template
{
var path = IOHelper.MapPath(ViewPath(t.Alias));
- if (!string.IsNullOrEmpty(currentAlias) && currentAlias != t.Alias)
+ if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != t.Alias)
{
//NOTE: I don't think this is needed for MVC, this was ported over from the
// masterpages helper but I think only relates to when templates are stored in the db.
@@ -78,31 +76,29 @@ namespace umbraco.cms.businesslogic.template
//then kill the old file..
var oldFile = IOHelper.MapPath(ViewPath(currentAlias));
- if (System.IO.File.Exists(oldFile))
- System.IO.File.Delete(oldFile);
+ if (File.Exists(oldFile))
+ File.Delete(oldFile);
}
- System.IO.File.WriteAllText(path, t.Design, Encoding.UTF8);
+ File.WriteAllText(path, t.Design, Encoding.UTF8);
return t.Design;
}
internal static void RemoveViewFile(string alias)
{
- if (!string.IsNullOrWhiteSpace(alias))
+ if (string.IsNullOrWhiteSpace(alias) == false)
{
var file = IOHelper.MapPath(ViewPath(alias));
- if (System.IO.File.Exists(file))
- System.IO.File.Delete(file);
+ if (File.Exists(file))
+ File.Delete(file);
}
}
public static string ViewPath(string alias)
{
- return Umbraco.Core.IO.SystemDirectories.MvcViews + "/" + alias.Replace(" ", "") + ".cshtml";
+ return SystemDirectories.MvcViews + "/" + alias.Replace(" ", "") + ".cshtml";
}
-
-
private static string EnsureInheritedLayout(Template template)
{
string design = template.Design;
@@ -115,8 +111,7 @@ namespace umbraco.cms.businesslogic.template
}";
if (template.MasterTemplate > 0)
- design = design.Replace("null", "\"" + new Template(template.MasterTemplate).Alias.Replace(" ", "") + "\"");
-
+ design = design.Replace("null", string.Format("\"{0}.cshtml\"", new Template(template.MasterTemplate).Alias.Replace(" ", "")));
}
return design;