Merge remote-tracking branch 'origin/temp8' into temp8-U4-11384
This commit is contained in:
@@ -29,8 +29,7 @@ namespace Umbraco.Core.Components
|
||||
/// <param name="container">The application container.</param>
|
||||
public BootLoader(IServiceContainer container)
|
||||
{
|
||||
if (container == null) throw new ArgumentNullException(nameof(container));
|
||||
_container = container;
|
||||
_container = container ?? throw new ArgumentNullException(nameof(container));
|
||||
_proflog = container.GetInstance<ProfilingLogger>();
|
||||
_logger = container.GetInstance<ILogger>();
|
||||
}
|
||||
@@ -176,8 +175,7 @@ namespace Umbraco.Core.Components
|
||||
foreach (var attr in componentType.GetCustomAttributes<EnableComponentAttribute>())
|
||||
{
|
||||
var type = attr.EnabledType ?? componentType;
|
||||
EnableInfo enableInfo;
|
||||
if (enabled.TryGetValue(type, out enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
|
||||
if (enabled.TryGetValue(type, out var enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
|
||||
var weight = type == componentType ? 1 : 2;
|
||||
if (enableInfo.Weight > weight) continue;
|
||||
|
||||
@@ -188,8 +186,7 @@ namespace Umbraco.Core.Components
|
||||
{
|
||||
var type = attr.DisabledType ?? componentType;
|
||||
if (type == typeof(UmbracoCoreComponent)) throw new InvalidOperationException("Cannot disable UmbracoCoreComponent.");
|
||||
EnableInfo enableInfo;
|
||||
if (enabled.TryGetValue(type, out enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
|
||||
if (enabled.TryGetValue(type, out var enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
|
||||
var weight = type == componentType ? 1 : 2;
|
||||
if (enableInfo.Weight > weight) continue;
|
||||
|
||||
|
||||
@@ -97,14 +97,14 @@ namespace Umbraco.Core.Events
|
||||
|
||||
public bool Equals(CancellableObjectEventArgs<T> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (other is null) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && EqualityComparer<T>.Default.Equals(EventObject, other.EventObject);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (obj is null) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((CancellableObjectEventArgs<T>)obj);
|
||||
@@ -154,7 +154,7 @@ namespace Umbraco.Core.Events
|
||||
|
||||
public bool Equals(CancellableEnumerableObjectEventArgs<T> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (other is null) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return EventObject.SequenceEqual(other.EventObject);
|
||||
@@ -162,7 +162,7 @@ namespace Umbraco.Core.Events
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (obj is null) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((CancellableEnumerableObjectEventArgs<T>)obj);
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Events
|
||||
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
|
||||
/// </param>
|
||||
public MoveEventArgs(bool canCancel, EventMessages eventMessages, params MoveEventInfo<TEntity>[] moveInfo)
|
||||
: base(default(TEntity), canCancel, eventMessages)
|
||||
: base(default, canCancel, eventMessages)
|
||||
{
|
||||
if (moveInfo.FirstOrDefault() == null)
|
||||
{
|
||||
@@ -27,7 +27,6 @@ namespace Umbraco.Core.Events
|
||||
MoveInfoCollection = moveInfo;
|
||||
//assign the legacy props
|
||||
EventObject = moveInfo.First().Entity;
|
||||
ParentId = moveInfo.First().NewParentId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -38,7 +37,7 @@ namespace Umbraco.Core.Events
|
||||
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
|
||||
/// </param>
|
||||
public MoveEventArgs(EventMessages eventMessages, params MoveEventInfo<TEntity>[] moveInfo)
|
||||
: base(default(TEntity), eventMessages)
|
||||
: base(default, eventMessages)
|
||||
{
|
||||
if (moveInfo.FirstOrDefault() == null)
|
||||
{
|
||||
@@ -48,7 +47,6 @@ namespace Umbraco.Core.Events
|
||||
MoveInfoCollection = moveInfo;
|
||||
//assign the legacy props
|
||||
EventObject = moveInfo.First().Entity;
|
||||
ParentId = moveInfo.First().NewParentId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -59,7 +57,7 @@ namespace Umbraco.Core.Events
|
||||
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
|
||||
/// </param>
|
||||
public MoveEventArgs(bool canCancel, params MoveEventInfo<TEntity>[] moveInfo)
|
||||
: base(default(TEntity), canCancel)
|
||||
: base(default, canCancel)
|
||||
{
|
||||
if (moveInfo.FirstOrDefault() == null)
|
||||
{
|
||||
@@ -69,7 +67,6 @@ namespace Umbraco.Core.Events
|
||||
MoveInfoCollection = moveInfo;
|
||||
//assign the legacy props
|
||||
EventObject = moveInfo.First().Entity;
|
||||
ParentId = moveInfo.First().NewParentId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -79,7 +76,7 @@ namespace Umbraco.Core.Events
|
||||
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
|
||||
/// </param>
|
||||
public MoveEventArgs(params MoveEventInfo<TEntity>[] moveInfo)
|
||||
: base(default(TEntity))
|
||||
: base(default)
|
||||
{
|
||||
if (moveInfo.FirstOrDefault() == null)
|
||||
{
|
||||
@@ -89,22 +86,17 @@ namespace Umbraco.Core.Events
|
||||
MoveInfoCollection = moveInfo;
|
||||
//assign the legacy props
|
||||
EventObject = moveInfo.First().Entity;
|
||||
ParentId = moveInfo.First().NewParentId;
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload that specifies the MoveEventInfo object")]
|
||||
public MoveEventArgs(TEntity eventObject, bool canCancel, int parentId)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
ParentId = parentId;
|
||||
}
|
||||
{ }
|
||||
|
||||
[Obsolete("Use the overload that specifies the MoveEventInfo object")]
|
||||
public MoveEventArgs(TEntity eventObject, int parentId)
|
||||
: base(eventObject)
|
||||
{
|
||||
ParentId = parentId;
|
||||
}
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all MoveEventInfo objects used to create the object
|
||||
@@ -124,7 +116,6 @@ namespace Umbraco.Core.Events
|
||||
|
||||
//assign the legacy props
|
||||
EventObject = first.Entity;
|
||||
ParentId = first.NewParentId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,22 +128,16 @@ namespace Umbraco.Core.Events
|
||||
get { return EventObject; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Id of the object's new parent
|
||||
/// </summary>
|
||||
[Obsolete("Retrieve the ParentId from the MoveInfoCollection property instead")]
|
||||
public int ParentId { get; private set; }
|
||||
|
||||
public bool Equals(MoveEventArgs<TEntity> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (other is null) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && MoveInfoCollection.Equals(other.MoveInfoCollection);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (obj is null) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((MoveEventArgs<TEntity>) obj);
|
||||
|
||||
@@ -115,6 +115,9 @@ namespace Umbraco.Core.IO
|
||||
if (FileExists(file) == false) return;
|
||||
DeleteFile(file);
|
||||
|
||||
#pragma warning disable 162 // unreachable code
|
||||
// Not implemented yet, so need to disable warnings
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
||||
if (UseTheNewMediaPathScheme == false)
|
||||
{
|
||||
// old scheme: filepath is "<int>/<filename>" OR "<int>-<filename>"
|
||||
@@ -130,6 +133,7 @@ namespace Umbraco.Core.IO
|
||||
var dir = Path.GetDirectoryName(file);
|
||||
DeleteDirectory(dir, true);
|
||||
}
|
||||
#pragma warning restore 162
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -155,6 +159,9 @@ namespace Umbraco.Core.IO
|
||||
filename = IOHelper.SafeFileName(filename.ToLowerInvariant());
|
||||
|
||||
string folder;
|
||||
#pragma warning disable 162 // unreachable code
|
||||
// Not implemented yet, so need to disable warnings
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
||||
if (UseTheNewMediaPathScheme == false)
|
||||
{
|
||||
// old scheme: filepath is "<int>/<filename>" OR "<int>-<filename>"
|
||||
@@ -169,6 +176,7 @@ namespace Umbraco.Core.IO
|
||||
// for a single content cannot store two different files with the same name
|
||||
folder = Combine(cuid, puid).ToHexString(/*'/', 2, 4*/); // could use ext to fragment path eg 12/e4/f2/...
|
||||
}
|
||||
#pragma warning restore 162
|
||||
|
||||
var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
|
||||
? Path.Combine(folder, filename).Replace('\\', '/')
|
||||
@@ -213,9 +221,8 @@ namespace Umbraco.Core.IO
|
||||
var sep = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories ? "/" : "-";
|
||||
var pos = prevpath.IndexOf(sep, StringComparison.Ordinal);
|
||||
var s = pos > 0 ? prevpath.Substring(0, pos) : null;
|
||||
int ignored;
|
||||
|
||||
var folder = (pos > 0 && int.TryParse(s, out ignored)) ? s : GetNextFolder();
|
||||
var folder = (pos > 0 && int.TryParse(s, out _)) ? s : GetNextFolder();
|
||||
|
||||
// ReSharper disable once AssignNullToNotNullAttribute
|
||||
var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
|
||||
@@ -246,8 +253,7 @@ namespace Umbraco.Core.IO
|
||||
var directories = GetDirectories("");
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
long folderNumber;
|
||||
if (long.TryParse(directory, out folderNumber) && folderNumber > _folderCounter)
|
||||
if (long.TryParse(directory, out var folderNumber) && folderNumber > _folderCounter)
|
||||
_folderCounter = folderNumber;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ namespace Umbraco.Core.Logging
|
||||
}
|
||||
|
||||
// obsolete but that's the one that's called ;-(
|
||||
[Obsolete]
|
||||
public override MiniProfiler Start(ProfileLevel level, string sessionName = null)
|
||||
{
|
||||
return Start(sessionName);
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
{
|
||||
SaveConnectionString(EmbeddedDatabaseConnectionString, Constants.DbProviderNames.SqlCe, logger);
|
||||
|
||||
var path = Path.Combine(GlobalSettings.FullPathToRoot, "App_Data", "Umbraco.sdf");
|
||||
var path = Path.Combine(IOHelper.GetRootDirectorySafe(), "App_Data", "Umbraco.sdf");
|
||||
if (File.Exists(path) == false)
|
||||
{
|
||||
// this should probably be in a "using (new SqlCeEngine)" clause but not sure
|
||||
@@ -173,8 +173,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
/// <param name="databaseProvider">The name the provider (Sql, Sql Azure, Sql Ce, MySql).</param>
|
||||
public void ConfigureDatabaseConnection(string server, string databaseName, string user, string password, string databaseProvider)
|
||||
{
|
||||
string providerName;
|
||||
var connectionString = GetDatabaseConnectionString(server, databaseName, user, password, databaseProvider, out providerName);
|
||||
var connectionString = GetDatabaseConnectionString(server, databaseName, user, password, databaseProvider, out var providerName);
|
||||
|
||||
SaveConnectionString(connectionString, providerName, _logger);
|
||||
_databaseFactory.Configure(connectionString, providerName);
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
// save new state
|
||||
if (forceState)
|
||||
_keyValueService.SetValue(StateValueKey, state);
|
||||
else
|
||||
else if (currentState != state)
|
||||
_keyValueService.SetValue(StateValueKey, currentState, state);
|
||||
|
||||
// run post-migrations
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_7_5_0
|
||||
{
|
||||
@@ -14,19 +15,23 @@ namespace Umbraco.Core.Migrations.Upgrade.V_7_5_0
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
// these have been obsoleted, need to copy the values here
|
||||
var stylesheetPropertyObjectType = new Guid("5555da4f-a123-42b2-4488-dcdfb25e4111");
|
||||
var stylesheetObjectType = new Guid("9F68DA4F-A3A8-44C2-8226-DCBD125E4840");
|
||||
|
||||
//Clear all stylesheet data if the tables exist
|
||||
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
|
||||
if (tables.InvariantContains("cmsStylesheetProperty"))
|
||||
{
|
||||
Delete.FromTable("cmsStylesheetProperty").AllRows().Do();
|
||||
Delete.FromTable("umbracoNode").Row(new { nodeObjectType = Constants.ObjectTypes.StylesheetProperty }).Do();
|
||||
Delete.FromTable("umbracoNode").Row(new { nodeObjectType = stylesheetPropertyObjectType }).Do();
|
||||
|
||||
Delete.Table("cmsStylesheetProperty").Do();
|
||||
}
|
||||
if (tables.InvariantContains("cmsStylesheet"))
|
||||
{
|
||||
Delete.FromTable("cmsStylesheet").AllRows().Do();
|
||||
Delete.FromTable("umbracoNode").Row(new { nodeObjectType = Constants.ObjectTypes.Stylesheet }).Do();
|
||||
Delete.FromTable("umbracoNode").Row(new { nodeObjectType = stylesheetObjectType }).Do();
|
||||
|
||||
Delete.Table("cmsStylesheet").Do();
|
||||
}
|
||||
|
||||
@@ -31,13 +31,13 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
return new PublishedContentType(contentType, this);
|
||||
}
|
||||
|
||||
// for tests - fixme what's the point of the factory here?
|
||||
// for tests
|
||||
internal PublishedContentType CreateContentType(int id, string alias, IEnumerable<PublishedPropertyType> propertyTypes, ContentVariation variations = ContentVariation.InvariantNeutral)
|
||||
{
|
||||
return new PublishedContentType(id, alias, PublishedItemType.Content, Enumerable.Empty<string>(), propertyTypes, variations);
|
||||
}
|
||||
|
||||
// for tests - fixme what's the point of the factory here?
|
||||
// for tests
|
||||
internal PublishedContentType CreateContentType(int id, string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes, ContentVariation variations = ContentVariation.InvariantNeutral)
|
||||
{
|
||||
return new PublishedContentType(id, alias, PublishedItemType.Content, compositionAliases, propertyTypes, variations);
|
||||
@@ -84,15 +84,6 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
return dataType;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void NotifyDataTypeChanges()
|
||||
{
|
||||
lock (_publishedDataTypesLocker)
|
||||
{
|
||||
_publishedDataTypes = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void NotifyDataTypeChanges(int[] ids)
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Umbraco.Core.Packaging
|
||||
|
||||
public PackageInstallation(IPackagingService packagingService, IMacroService macroService,
|
||||
IFileService fileService, IPackageExtraction packageExtraction)
|
||||
: this(packagingService, macroService, fileService, packageExtraction, GlobalSettings.FullPathToRoot)
|
||||
: this(packagingService, macroService, fileService, packageExtraction, IOHelper.GetRootDirectorySafe())
|
||||
{}
|
||||
|
||||
public PackageInstallation(IPackagingService packagingService, IMacroService macroService,
|
||||
@@ -212,9 +212,8 @@ namespace Umbraco.Core.Packaging
|
||||
|
||||
private XDocument GetConfigXmlDoc(string packageFilePath)
|
||||
{
|
||||
string filePathInPackage;
|
||||
string configXmlContent = _packageExtraction.ReadTextFileFromArchive(packageFilePath,
|
||||
Constants.Packaging.PackageXmlFileName, out filePathInPackage);
|
||||
var configXmlContent = _packageExtraction.ReadTextFileFromArchive(packageFilePath,
|
||||
Constants.Packaging.PackageXmlFileName, out _);
|
||||
|
||||
return XDocument.Parse(configXmlContent);
|
||||
}
|
||||
@@ -294,15 +293,13 @@ namespace Umbraco.Core.Packaging
|
||||
};
|
||||
|
||||
|
||||
XAttribute attr = elemet.Attribute(Constants.Packaging.RunatNodeAttribute);
|
||||
var attr = elemet.Attribute(Constants.Packaging.RunatNodeAttribute);
|
||||
|
||||
ActionRunAt runAt;
|
||||
if (attr != null && Enum.TryParse(attr.Value, true, out runAt)) { packageAction.RunAt = runAt; }
|
||||
if (attr != null && Enum.TryParse(attr.Value, true, out ActionRunAt runAt)) { packageAction.RunAt = runAt; }
|
||||
|
||||
attr = elemet.Attribute(Constants.Packaging.UndoNodeAttribute);
|
||||
|
||||
bool undo;
|
||||
if (attr != null && bool.TryParse(attr.Value, out undo)) { packageAction.Undo = undo; }
|
||||
if (attr != null && bool.TryParse(attr.Value, out var undo)) { packageAction.Undo = undo; }
|
||||
|
||||
|
||||
return packageAction;
|
||||
@@ -570,8 +567,7 @@ namespace Umbraco.Core.Packaging
|
||||
|
||||
private static int IntValue(XElement xElement, int defaultValue = 0)
|
||||
{
|
||||
int val;
|
||||
return xElement == null ? defaultValue : int.TryParse(xElement.Value, out val) ? val : defaultValue;
|
||||
return xElement == null ? defaultValue : int.TryParse(xElement.Value, out var val) ? val : defaultValue;
|
||||
}
|
||||
|
||||
private static string UpdatePathPlaceholders(string path)
|
||||
|
||||
@@ -916,6 +916,82 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
#endregion
|
||||
|
||||
#region Hints
|
||||
|
||||
/// <summary>
|
||||
/// Appends the relevant ForUpdate hint.
|
||||
/// </summary>
|
||||
/// <param name="sql">The Sql statement.</param>
|
||||
/// <returns>The Sql statement.</returns>
|
||||
public static Sql<ISqlContext> ForUpdate(this Sql<ISqlContext> sql)
|
||||
{
|
||||
// MySql wants "FOR UPDATE" at the end, and T-Sql wants "WITH (UPDLOCK)" in the FROM statement,
|
||||
// and we want to implement it in the least expensive way, so parsing the entire string here is
|
||||
// a no, so we use reflection to work on the Sql expression before it is built.
|
||||
// TODO propose a clean way to do that type of thing in NPoco
|
||||
|
||||
if (sql.SqlContext.DatabaseType.IsMySql())
|
||||
{
|
||||
sql.Append("FOR UPDATE");
|
||||
return sql;
|
||||
}
|
||||
|
||||
// go find the first FROM clause, and append the lock hint
|
||||
Sql s = sql;
|
||||
var updated = false;
|
||||
|
||||
while (s != null)
|
||||
{
|
||||
var sqlText = SqlInspector.GetSqlText(s);
|
||||
if (sqlText.StartsWith("FROM ", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
SqlInspector.SetSqlText(s, sqlText + " WITH (UPDLOCK)");
|
||||
updated = true;
|
||||
break;
|
||||
}
|
||||
|
||||
s = SqlInspector.GetSqlRhs(sql);
|
||||
}
|
||||
|
||||
if (updated)
|
||||
SqlInspector.Reset(sql);
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sql Inspection
|
||||
|
||||
private static SqlInspectionUtilities _sqlInspector;
|
||||
|
||||
private static SqlInspectionUtilities SqlInspector => _sqlInspector ?? (_sqlInspector = new SqlInspectionUtilities());
|
||||
|
||||
private class SqlInspectionUtilities
|
||||
{
|
||||
private readonly Func<Sql, string> _getSqlText;
|
||||
private readonly Action<Sql, string> _setSqlText;
|
||||
private readonly Func<Sql, Sql> _getSqlRhs;
|
||||
private readonly Action<Sql, string> _setSqlFinal;
|
||||
|
||||
public SqlInspectionUtilities()
|
||||
{
|
||||
(_getSqlText, _setSqlText) = ReflectionUtilities.EmitFieldGetterAndSetter<Sql, string>("_sql");
|
||||
_getSqlRhs = ReflectionUtilities.EmitFieldGetter<Sql, Sql>("_rhs");
|
||||
_setSqlFinal = ReflectionUtilities.EmitFieldSetter<Sql, string>("_sqlFinal");
|
||||
}
|
||||
|
||||
public string GetSqlText(Sql sql) => _getSqlText(sql);
|
||||
|
||||
public void SetSqlText(Sql sql, string sqlText) => _setSqlText(sql, sqlText);
|
||||
|
||||
public Sql GetSqlRhs(Sql sql) => _getSqlRhs(sql);
|
||||
|
||||
public void Reset(Sql sql) => _setSqlFinal(sql, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utilities
|
||||
|
||||
private static string[] GetColumns<TDto>(this Sql<ISqlContext> sql, string tableAlias = null, string referenceName = null, Expression<Func<TDto, object>>[] columnExpressions = null, bool withAlias = true)
|
||||
|
||||
@@ -191,7 +191,20 @@ ORDER BY colName";
|
||||
|
||||
public bool ValidateLoginSession(int userId, Guid sessionId)
|
||||
{
|
||||
var found = Database.FirstOrDefault<UserLoginDto>("WHERE sessionId=@sessionId", new {sessionId = sessionId});
|
||||
// with RepeatableRead transaction mode, read-then-update operations can
|
||||
// cause deadlocks, and the ForUpdate() hint is required to tell the database
|
||||
// to acquire an exclusive lock when reading
|
||||
|
||||
// that query is going to run a *lot*, make it a template
|
||||
var t = SqlContext.Templates.Get("Umbraco.Core.UserRepository.ValidateLoginSession", s => s
|
||||
.Select<UserLoginDto>()
|
||||
.From<UserLoginDto>()
|
||||
.Where<UserLoginDto>(x => x.SessionId == SqlTemplate.Arg<Guid>("sessionId"))
|
||||
.ForUpdate());
|
||||
|
||||
var sql = t.Sql(sessionId);
|
||||
|
||||
var found = Database.Query<UserLoginDto>(sql).FirstOrDefault();
|
||||
if (found == null || found.UserId != userId || found.LoggedOutUtc.HasValue)
|
||||
return false;
|
||||
|
||||
@@ -211,34 +224,21 @@ ORDER BY colName";
|
||||
|
||||
public int ClearLoginSessions(int userId)
|
||||
{
|
||||
//TODO: I know this doesn't follow the normal repository conventions which would require us to crete a UserSessionRepository
|
||||
//and also business logic models for these objects but that's just so overkill for what we are doing
|
||||
//and now that everything is properly in a transaction (Scope) there doesn't seem to be much reason for using that anymore
|
||||
var count = Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoUserLogin WHERE userId=@userId", new { userId = userId });
|
||||
Database.Execute("DELETE FROM umbracoUserLogin WHERE userId=@userId", new {userId = userId});
|
||||
return count;
|
||||
return Database.Delete<UserLoginDto>(Sql().Where<UserLoginDto>(x => x.UserId == userId));
|
||||
}
|
||||
|
||||
public int ClearLoginSessions(TimeSpan timespan)
|
||||
{
|
||||
//TODO: I know this doesn't follow the normal repository conventions which would require us to crete a UserSessionRepository
|
||||
//and also business logic models for these objects but that's just so overkill for what we are doing
|
||||
//and now that everything is properly in a transaction (Scope) there doesn't seem to be much reason for using that anymore
|
||||
|
||||
var fromDate = DateTime.UtcNow - timespan;
|
||||
|
||||
var count = Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoUserLogin WHERE lastValidatedUtc=@fromDate", new { fromDate = fromDate });
|
||||
Database.Execute("DELETE FROM umbracoUserLogin WHERE lastValidatedUtc=@fromDate", new { fromDate = fromDate });
|
||||
return count;
|
||||
return Database.Delete<UserLoginDto>(Sql().Where<UserLoginDto>(x => x.LastValidatedUtc < fromDate));
|
||||
}
|
||||
|
||||
public void ClearLoginSession(Guid sessionId)
|
||||
{
|
||||
//TODO: I know this doesn't follow the normal repository conventions which would require us to crete a UserSessionRepository
|
||||
//and also business logic models for these objects but that's just so overkill for what we are doing
|
||||
//and now that everything is properly in a transaction (Scope) there doesn't seem to be much reason for using that anymore
|
||||
Database.Execute("UPDATE umbracoUserLogin SET loggedOutUtc=@now WHERE sessionId=@sessionId",
|
||||
new { now = DateTime.UtcNow, sessionId = sessionId });
|
||||
// fixme why is that one updating and not deleting?
|
||||
Database.Execute(Sql()
|
||||
.Update<UserLoginDto>(u => u.Set(x => x.LoggedOutUtc, DateTime.UtcNow))
|
||||
.Where<UserLoginDto>(x => x.SessionId == sessionId));
|
||||
}
|
||||
|
||||
protected override IEnumerable<IUser> PerformGetAll(params int[] ids)
|
||||
@@ -718,7 +718,7 @@ ORDER BY colName";
|
||||
if (string.IsNullOrWhiteSpace(orderBy)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(orderBy));
|
||||
|
||||
Sql<ISqlContext> filterSql = null;
|
||||
var customFilterWheres = filter != null ? filter.GetWhereClauses().ToArray() : null;
|
||||
var customFilterWheres = filter?.GetWhereClauses().ToArray();
|
||||
var hasCustomFilter = customFilterWheres != null && customFilterWheres.Length > 0;
|
||||
if (hasCustomFilter
|
||||
|| includeUserGroups != null && includeUserGroups.Length > 0
|
||||
|
||||
@@ -34,7 +34,8 @@ using System.Runtime.InteropServices;
|
||||
[assembly: InternalsVisibleTo("Umbraco.Forms.Web")]
|
||||
|
||||
// Umbraco Headless
|
||||
[assembly: InternalsVisibleTo("Umbraco.Headless")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Headless")]
|
||||
|
||||
// v8
|
||||
[assembly: InternalsVisibleTo("Umbraco.Compat7")]
|
||||
// code analysis
|
||||
// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]
|
||||
|
||||
@@ -21,6 +21,96 @@ namespace Umbraco.Core
|
||||
/// </remarks>
|
||||
public static partial class ReflectionUtilities
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Emits a field getter.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDeclaring">The declaring type.</typeparam>
|
||||
/// <typeparam name="TValue">The field type.</typeparam>
|
||||
/// <param name="fieldName">The name of the field.</param>
|
||||
/// <returns>A field getter function.</returns>
|
||||
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="fieldName"/> is null or empty.</exception>
|
||||
/// <exception cref="InvalidOperationException">Occurs when the field does not exist.</exception>
|
||||
/// <exception cref="ArgumentException">Occurs when <typeparamref name="TValue"/> does not match the type of the field.</exception>
|
||||
public static Func<TDeclaring, TValue> EmitFieldGetter<TDeclaring, TValue>(string fieldName)
|
||||
{
|
||||
var field = GetField<TDeclaring, TValue>(fieldName);
|
||||
return EmitFieldGetter<TDeclaring, TValue>(field);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Emits a field setter.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDeclaring">The declaring type.</typeparam>
|
||||
/// <typeparam name="TValue">The field type.</typeparam>
|
||||
/// <param name="fieldName">The name of the field.</param>
|
||||
/// <returns>A field setter action.</returns>
|
||||
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="fieldName"/> is null or empty.</exception>
|
||||
/// <exception cref="InvalidOperationException">Occurs when the field does not exist.</exception>
|
||||
/// <exception cref="ArgumentException">Occurs when <typeparamref name="TValue"/> does not match the type of the field.</exception>
|
||||
public static Action<TDeclaring, TValue> EmitFieldSetter<TDeclaring, TValue>(string fieldName)
|
||||
{
|
||||
var field = GetField<TDeclaring, TValue>(fieldName);
|
||||
return EmitFieldSetter<TDeclaring, TValue>(field);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Emits a field getter and setter.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDeclaring">The declaring type.</typeparam>
|
||||
/// <typeparam name="TValue">The field type.</typeparam>
|
||||
/// <param name="fieldName">The name of the field.</param>
|
||||
/// <returns>A field getter and setter functions.</returns>
|
||||
/// <exception cref="ArgumentNullOrEmptyException">Occurs when <paramref name="fieldName"/> is null or empty.</exception>
|
||||
/// <exception cref="InvalidOperationException">Occurs when the field does not exist.</exception>
|
||||
/// <exception cref="ArgumentException">Occurs when <typeparamref name="TValue"/> does not match the type of the field.</exception>
|
||||
public static (Func<TDeclaring, TValue>, Action<TDeclaring, TValue>) EmitFieldGetterAndSetter<TDeclaring, TValue>(string fieldName)
|
||||
{
|
||||
var field = GetField<TDeclaring, TValue>(fieldName);
|
||||
return (EmitFieldGetter<TDeclaring, TValue>(field), EmitFieldSetter<TDeclaring, TValue>(field));
|
||||
}
|
||||
|
||||
private static FieldInfo GetField<TDeclaring, TValue>(string fieldName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(fieldName)) throw new ArgumentNullOrEmptyException(nameof(fieldName));
|
||||
|
||||
// get the field
|
||||
var field = typeof(TDeclaring).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (field == null) throw new InvalidOperationException($"Could not find field {typeof(TDeclaring)}.{fieldName}.");
|
||||
|
||||
// validate field type
|
||||
if (field.FieldType != typeof(TValue)) // strict
|
||||
throw new ArgumentException($"Value type {typeof(TValue)} does not match field {typeof(TDeclaring)}.{fieldName} type {field.FieldType}.");
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
private static Func<TDeclaring, TValue> EmitFieldGetter<TDeclaring, TValue>(FieldInfo field)
|
||||
{
|
||||
// emit
|
||||
var (dm, ilgen) = CreateIlGenerator(field.DeclaringType?.Module, new [] { typeof(TDeclaring) }, typeof(TValue));
|
||||
ilgen.Emit(OpCodes.Ldarg_0);
|
||||
ilgen.Emit(OpCodes.Ldfld, field);
|
||||
ilgen.Return();
|
||||
|
||||
return (Func<TDeclaring, TValue>) (object) dm.CreateDelegate(typeof(Func<TDeclaring, TValue>));
|
||||
}
|
||||
|
||||
private static Action<TDeclaring, TValue> EmitFieldSetter<TDeclaring, TValue>(FieldInfo field)
|
||||
{
|
||||
// emit
|
||||
var (dm, ilgen) = CreateIlGenerator(field.DeclaringType?.Module, new [] { typeof(TDeclaring), typeof(TValue) }, typeof(void));
|
||||
ilgen.Emit(OpCodes.Ldarg_0);
|
||||
ilgen.Emit(OpCodes.Ldarg_1);
|
||||
ilgen.Emit(OpCodes.Stfld, field);
|
||||
ilgen.Return();
|
||||
|
||||
return (Action<TDeclaring, TValue>) (object) dm.CreateDelegate(typeof(Action<TDeclaring, TValue>));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
@@ -207,7 +297,7 @@ namespace Umbraco.Core
|
||||
/// is specified and does not match the function's returned type.</exception>
|
||||
public static TLambda EmitCtor<TLambda>(bool mustExist = true, Type declaring = null)
|
||||
{
|
||||
(_, var lambdaParameters, var lambdaReturned) = AnalyzeLambda<TLambda>(true, true);
|
||||
var (_, lambdaParameters, lambdaReturned) = AnalyzeLambda<TLambda>(true, true);
|
||||
|
||||
// determine returned / declaring type
|
||||
if (declaring == null) declaring = lambdaReturned;
|
||||
@@ -239,7 +329,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (ctor == null) throw new ArgumentNullException(nameof(ctor));
|
||||
|
||||
(_, var lambdaParameters, var lambdaReturned) = AnalyzeLambda<TLambda>(true, true);
|
||||
var (_, lambdaParameters, lambdaReturned) = AnalyzeLambda<TLambda>(true, true);
|
||||
|
||||
return EmitCtorSafe<TLambda>(lambdaParameters, lambdaReturned, ctor);
|
||||
}
|
||||
@@ -281,7 +371,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (ctor == null) throw new ArgumentNullException(nameof(ctor));
|
||||
|
||||
(_, var lambdaParameters, var lambdaReturned) = AnalyzeLambda<TLambda>(true, true);
|
||||
var (_, lambdaParameters, lambdaReturned) = AnalyzeLambda<TLambda>(true, true);
|
||||
|
||||
// emit - unsafe - use lambda's args and assume they are correct
|
||||
return EmitCtor<TLambda>(lambdaReturned, lambdaParameters, ctor);
|
||||
@@ -293,7 +383,7 @@ namespace Umbraco.Core
|
||||
var ctorParameters = GetParameters(ctor);
|
||||
|
||||
// emit
|
||||
(var dm, var ilgen) = CreateIlGenerator(ctor.DeclaringType?.Module, lambdaParameters, declaring);
|
||||
var (dm, ilgen) = CreateIlGenerator(ctor.DeclaringType?.Module, lambdaParameters, declaring);
|
||||
EmitLdargs(ilgen, lambdaParameters, ctorParameters);
|
||||
ilgen.Emit(OpCodes.Newobj, ctor); // ok to just return, it's only objects
|
||||
ilgen.Return();
|
||||
@@ -342,7 +432,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(methodName)) throw new ArgumentNullOrEmptyException(nameof(methodName));
|
||||
|
||||
(var lambdaDeclaring, var lambdaParameters, var lambdaReturned) = AnalyzeLambda<TLambda>(true, out var isFunction);
|
||||
var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda<TLambda>(true, out var isFunction);
|
||||
|
||||
// get the method infos
|
||||
var method = declaring.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, lambdaParameters, null);
|
||||
@@ -374,7 +464,7 @@ namespace Umbraco.Core
|
||||
var methodParameters = method.GetParameters().Select(x => x.ParameterType).ToArray();
|
||||
|
||||
var isStatic = method.IsStatic;
|
||||
(var lambdaDeclaring, var lambdaParameters, var lambdaReturned) = AnalyzeLambda<TLambda>(isStatic, out var isFunction);
|
||||
var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda<TLambda>(isStatic, out var isFunction);
|
||||
|
||||
// if not static, then the first lambda arg must be the method declaring type
|
||||
if (!isStatic && (methodDeclaring == null || !methodDeclaring.IsAssignableFrom(lambdaDeclaring)))
|
||||
@@ -408,7 +498,7 @@ namespace Umbraco.Core
|
||||
if (method == null) throw new ArgumentNullException(nameof(method));
|
||||
|
||||
var isStatic = method.IsStatic;
|
||||
(var lambdaDeclaring, var lambdaParameters, var lambdaReturned) = AnalyzeLambda<TLambda>(isStatic, out _);
|
||||
var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda<TLambda>(isStatic, out _);
|
||||
|
||||
// emit - unsafe - use lambda's args and assume they are correct
|
||||
return EmitMethod<TLambda>(lambdaDeclaring, lambdaReturned, lambdaParameters, method);
|
||||
@@ -433,7 +523,7 @@ namespace Umbraco.Core
|
||||
throw new ArgumentNullOrEmptyException(nameof(methodName));
|
||||
|
||||
// validate lambda type
|
||||
(var lambdaDeclaring, var lambdaParameters, var lambdaReturned) = AnalyzeLambda<TLambda>(false, out var isFunction);
|
||||
var (lambdaDeclaring, lambdaParameters, lambdaReturned) = AnalyzeLambda<TLambda>(false, out var isFunction);
|
||||
|
||||
// get the method infos
|
||||
var method = lambdaDeclaring.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, lambdaParameters, null);
|
||||
@@ -464,7 +554,7 @@ namespace Umbraco.Core
|
||||
var methodArgTypes = GetParameters(method, withDeclaring: !method.IsStatic);
|
||||
|
||||
// emit IL
|
||||
(var dm, var ilgen) = CreateIlGenerator(method.DeclaringType?.Module, parameters, lambdaReturned);
|
||||
var (dm, ilgen) = CreateIlGenerator(method.DeclaringType?.Module, parameters, lambdaReturned);
|
||||
EmitLdargs(ilgen, parameters, methodArgTypes);
|
||||
ilgen.CallMethod(method);
|
||||
EmitOutputAdapter(ilgen, lambdaReturned, method.ReturnType);
|
||||
@@ -486,7 +576,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
var typeLambda = typeof(TLambda);
|
||||
|
||||
(var declaring, var parameters, var returned) = AnalyzeLambda<TLambda>(isStatic, out var maybeFunction);
|
||||
var (declaring, parameters, returned) = AnalyzeLambda<TLambda>(isStatic, out var maybeFunction);
|
||||
|
||||
if (isFunction)
|
||||
{
|
||||
|
||||
@@ -45,8 +45,8 @@ namespace Umbraco.Core.Runtime
|
||||
public virtual void Boot(ServiceContainer container)
|
||||
{
|
||||
// some components may want to initialize with the UmbracoApplicationBase
|
||||
// well, they should not - we should not do this - however, Compat7 wants
|
||||
// it, so let's do it, but we should remove this eventually.
|
||||
// well, they should not - we should not do this
|
||||
// TODO remove this eventually.
|
||||
container.RegisterInstance(_app);
|
||||
|
||||
Compose(container);
|
||||
|
||||
@@ -68,13 +68,10 @@ namespace Umbraco.Core.Strings
|
||||
/// <summary>
|
||||
/// Flag mask for encoding.
|
||||
/// </summary>
|
||||
CodeMask = Unicode | Utf8 | Ascii | TryAscii,
|
||||
|
||||
/// <summary>
|
||||
/// Unicode encoding.
|
||||
/// </summary>
|
||||
[Obsolete("Use .Utf8 instead.")]
|
||||
Unicode = 0x0100,
|
||||
CodeMask = Utf8 | Ascii | TryAscii,
|
||||
|
||||
// Unicode encoding is obsolete, use Utf8
|
||||
//Unicode = 0x0100,
|
||||
|
||||
/// <summary>
|
||||
/// Utf8 encoding.
|
||||
|
||||
@@ -160,7 +160,10 @@ namespace Umbraco.Core
|
||||
_runtime = null;
|
||||
}
|
||||
|
||||
Current.Reset(); // dispose the container and everything
|
||||
// dispose the container and everything
|
||||
// but first, capture the looger!
|
||||
var logger = Current.Logger;
|
||||
Current.Reset();
|
||||
|
||||
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted) return;
|
||||
|
||||
@@ -183,12 +186,12 @@ namespace Umbraco.Core
|
||||
|
||||
var shutdownMsg = $"Application shutdown. Details: {HostingEnvironment.ShutdownReason}\r\n\r\n_shutDownMessage={shutDownMessage}\r\n\r\n_shutDownStack={shutDownStack}";
|
||||
|
||||
Current.Logger.Info<UmbracoApplicationBase>(shutdownMsg);
|
||||
logger.Info<UmbracoApplicationBase>(shutdownMsg);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//if for some reason that fails, then log the normal output
|
||||
Current.Logger.Info<UmbracoApplicationBase>("Application shutdown. Reason: " + HostingEnvironment.ShutdownReason);
|
||||
logger.Info<UmbracoApplicationBase>("Application shutdown. Reason: " + HostingEnvironment.ShutdownReason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,16 +4,11 @@ namespace Umbraco.Examine.Config
|
||||
{
|
||||
public sealed class IndexSets : ConfigurationSection
|
||||
{
|
||||
|
||||
#region Singleton definition
|
||||
|
||||
protected IndexSets() { }
|
||||
static IndexSets()
|
||||
{
|
||||
Instance = ConfigurationManager.GetSection(SectionName) as IndexSets;
|
||||
private IndexSets() { }
|
||||
|
||||
}
|
||||
public static IndexSets Instance { get; }
|
||||
public static IndexSets Instance { get; } = ConfigurationManager.GetSection(SectionName) as IndexSets;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -23,4 +18,4 @@ namespace Umbraco.Examine.Config
|
||||
[ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)]
|
||||
public IndexSetCollection Sets => (IndexSetCollection)base[""];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,3 +8,7 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
// Umbraco Cms
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests")]
|
||||
|
||||
// code analysis
|
||||
// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]
|
||||
|
||||
@@ -294,8 +294,7 @@ namespace Umbraco.Examine
|
||||
|
||||
do
|
||||
{
|
||||
long total;
|
||||
var descendants = MediaService.GetPagedDescendants(mediaParentId, pageIndex, pageSize, out total);
|
||||
var descendants = MediaService.GetPagedDescendants(mediaParentId, pageIndex, pageSize, out _);
|
||||
|
||||
//if specific types are declared we need to post filter them
|
||||
//TODO: Update the service layer to join the cmsContentType table so we can query by content type too
|
||||
|
||||
@@ -5,13 +5,11 @@ using Umbraco.ModelsBuilder.Umbraco;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Api
|
||||
{
|
||||
// internal to be used by Umbraco.ModelsBuilder.Api project
|
||||
internal static class ApiHelper
|
||||
{
|
||||
public static Dictionary<string, string> GetModels(string modelsNamespace, IDictionary<string, string> files)
|
||||
public static Dictionary<string, string> GetModels(UmbracoServices umbracoServices, string modelsNamespace, IDictionary<string, string> files)
|
||||
{
|
||||
var umbraco = ModelsBuilderComponent.Umbraco;
|
||||
var typeModels = umbraco.GetAllTypes();
|
||||
var typeModels = umbracoServices.GetAllTypes();
|
||||
|
||||
var parseResult = new CodeParser().ParseWithReferencedAssemblies(files);
|
||||
var builder = new TextBuilder(typeModels, parseResult, modelsNamespace);
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.ModelsBuilder.Building;
|
||||
using Umbraco.ModelsBuilder.Configuration;
|
||||
using Umbraco.ModelsBuilder.Umbraco;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Api
|
||||
{
|
||||
@@ -28,6 +24,13 @@ namespace Umbraco.ModelsBuilder.Api
|
||||
{
|
||||
public const string ControllerArea = "ModelsBuilder";
|
||||
|
||||
private readonly UmbracoServices _umbracoServices;
|
||||
|
||||
public ModelsBuilderApiController(UmbracoServices umbracoServices)
|
||||
{
|
||||
_umbracoServices = umbracoServices;
|
||||
}
|
||||
|
||||
// invoked by the API
|
||||
[System.Web.Http.HttpPost] // use the http one, not mvc, with api controllers!
|
||||
[ApiBasicAuthFilter("developer")] // have to use our own, non-cookie-based, auth
|
||||
@@ -60,7 +63,7 @@ namespace Umbraco.ModelsBuilder.Api
|
||||
if (!checkResult.Success)
|
||||
return checkResult.Result;
|
||||
|
||||
var models = ApiHelper.GetModels(data.Namespace, data.Files);
|
||||
var models = ApiHelper.GetModels(_umbracoServices, data.Namespace, data.Files);
|
||||
|
||||
return Request.CreateResponse(HttpStatusCode.OK, models, Configuration.Formatters.JsonFormatter);
|
||||
}
|
||||
|
||||
@@ -8,3 +8,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: Guid("7020a059-c0d1-43a0-8efd-23591a0c9af6")]
|
||||
|
||||
// code analysis
|
||||
// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]
|
||||
|
||||
@@ -87,11 +87,10 @@
|
||||
<Compile Include="RenameContentTypeAttribute.cs" />
|
||||
<Compile Include="RenamePropertyTypeAttribute.cs" />
|
||||
<Compile Include="TypeExtensions.cs" />
|
||||
<Compile Include="Umbraco\Application.cs" />
|
||||
<Compile Include="Umbraco\UmbracoServices.cs" />
|
||||
<Compile Include="Umbraco\HashCombiner.cs" />
|
||||
<Compile Include="Umbraco\HashHelper.cs" />
|
||||
<Compile Include="Umbraco\LiveModelsProvider.cs" />
|
||||
<Compile Include="Umbraco\ModelsBuilderApplication.cs" />
|
||||
<Compile Include="Umbraco\ModelsBuilderBackOfficeController.cs" />
|
||||
<Compile Include="Umbraco\ModelsBuilderComponent.cs" />
|
||||
<Compile Include="Umbraco\ModelsGenerationError.cs" />
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
// supports LiveDll and LiveAppData - but not PureLive
|
||||
public sealed class LiveModelsProvider
|
||||
{
|
||||
private static UmbracoServices _umbracoServices;
|
||||
private static Mutex _mutex;
|
||||
private static int _req;
|
||||
|
||||
@@ -30,12 +31,14 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Install()
|
||||
internal static void Install(UmbracoServices umbracoServices)
|
||||
{
|
||||
// just be sure
|
||||
if (!IsEnabled)
|
||||
return;
|
||||
|
||||
_umbracoServices = umbracoServices;
|
||||
|
||||
// initialize mutex
|
||||
// ApplicationId will look like "/LM/W3SVC/1/Root/AppName"
|
||||
// name is system-wide and must be less than 260 chars
|
||||
@@ -110,11 +113,11 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
var config = UmbracoConfig.For.ModelsBuilder();
|
||||
|
||||
// EnableDllModels will recycle the app domain - but this request will end properly
|
||||
ModelsBuilderBackOfficeController.GenerateModels(modelsDirectory, config.ModelsMode.IsAnyDll() ? bin : null);
|
||||
ModelsBuilderBackOfficeController.GenerateModels(_umbracoServices, modelsDirectory, config.ModelsMode.IsAnyDll() ? bin : null);
|
||||
}
|
||||
}
|
||||
|
||||
// have to do this because it's the only way to subscribe to EndRequest
|
||||
// have to do this because it's the only way to subscribe to EndRequest,
|
||||
// module is installed by assembly attribute at the top of this file
|
||||
public class LiveModelsProviderModule : IHttpModule
|
||||
{
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using LightInject;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
using Umbraco.ModelsBuilder.Configuration;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.UI.JavaScript;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Umbraco
|
||||
{
|
||||
/// <summary>
|
||||
/// Installs ModelsBuilder into the Umbraco site.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Don't bother installing at all, if not RuntimeLevel.Run.</para>
|
||||
/// </remarks>
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
public class ModelsBuilderApplication : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
{
|
||||
private IRuntimeState _runtimeState;
|
||||
|
||||
public override void Compose(Composition composition)
|
||||
{
|
||||
var config = UmbracoConfig.For.ModelsBuilder();
|
||||
|
||||
if (config.ModelsMode == ModelsMode.PureLive)
|
||||
InstallLiveModels(composition.Container);
|
||||
else if (config.EnableFactory)
|
||||
InstallDefaultModelsFactory(composition.Container);
|
||||
|
||||
// always setup the dashboard
|
||||
InstallServerVars();
|
||||
}
|
||||
|
||||
public void Initialize(IRuntimeState runtimeState)
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
|
||||
var config = UmbracoConfig.For.ModelsBuilder();
|
||||
|
||||
if (config.Enable)
|
||||
FileService.SavingTemplate += FileService_SavingTemplate;
|
||||
|
||||
if (config.ModelsMode.IsLiveNotPure())
|
||||
LiveModelsProvider.Install();
|
||||
|
||||
if (config.FlagOutOfDateModels)
|
||||
OutOfDateModelsStatus.Install();
|
||||
}
|
||||
|
||||
private void InstallDefaultModelsFactory(IServiceContainer container)
|
||||
{
|
||||
var types = Current.TypeLoader.GetTypes<PublishedContentModel>();
|
||||
var factory = new PublishedModelFactory(types);
|
||||
container.RegisterSingleton<IPublishedModelFactory>(_ => factory);
|
||||
}
|
||||
|
||||
private void InstallLiveModels(IServiceContainer container)
|
||||
{
|
||||
container.RegisterSingleton<IPublishedModelFactory, PureLiveModelFactory>();
|
||||
|
||||
// the following would add @using statement in every view so user's don't
|
||||
// have to do it - however, then noone understands where the @using statement
|
||||
// comes from, and it cannot be avoided / removed --- DISABLED
|
||||
//
|
||||
/*
|
||||
// no need for @using in views
|
||||
// note:
|
||||
// we are NOT using the in-code attribute here, config is required
|
||||
// because that would require parsing the code... and what if it changes?
|
||||
// we can AddGlobalImport not sure we can remove one anyways
|
||||
var modelsNamespace = Configuration.Config.ModelsNamespace;
|
||||
if (string.IsNullOrWhiteSpace(modelsNamespace))
|
||||
modelsNamespace = Configuration.Config.DefaultModelsNamespace;
|
||||
System.Web.WebPages.Razor.WebPageRazorHost.AddGlobalImport(modelsNamespace);
|
||||
*/
|
||||
}
|
||||
|
||||
private void InstallServerVars()
|
||||
{
|
||||
// register our url - for the backoffice api
|
||||
ServerVariablesParser.Parsing += (sender, serverVars) =>
|
||||
{
|
||||
if (!serverVars.ContainsKey("umbracoUrls"))
|
||||
throw new Exception("Missing umbracoUrls.");
|
||||
var umbracoUrlsObject = serverVars["umbracoUrls"];
|
||||
if (umbracoUrlsObject == null)
|
||||
throw new Exception("Null umbracoUrls");
|
||||
if (!(umbracoUrlsObject is Dictionary<string, object> umbracoUrls))
|
||||
throw new Exception("Invalid umbracoUrls");
|
||||
|
||||
if (!serverVars.ContainsKey("umbracoPlugins"))
|
||||
throw new Exception("Missing umbracoPlugins.");
|
||||
if (!(serverVars["umbracoPlugins"] is Dictionary<string, object> umbracoPlugins))
|
||||
throw new Exception("Invalid umbracoPlugins");
|
||||
|
||||
if (HttpContext.Current == null) throw new InvalidOperationException("HttpContext is null");
|
||||
var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()));
|
||||
|
||||
umbracoUrls["modelsBuilderBaseUrl"] = urlHelper.GetUmbracoApiServiceBaseUrl<ModelsBuilderBackOfficeController>(controller => controller.BuildModels());
|
||||
umbracoPlugins["modelsBuilder"] = GetModelsBuilderSettings();
|
||||
};
|
||||
}
|
||||
|
||||
private Dictionary<string, object> GetModelsBuilderSettings()
|
||||
{
|
||||
if (_runtimeState.Level != RuntimeLevel.Run)
|
||||
return null;
|
||||
|
||||
var settings = new Dictionary<string, object>
|
||||
{
|
||||
{"enabled", UmbracoConfig.For.ModelsBuilder().Enable}
|
||||
};
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to check if a template is being created based on a document type, in this case we need to
|
||||
/// ensure the template markup is correct based on the model name of the document type
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void FileService_SavingTemplate(IFileService sender, Core.Events.SaveEventArgs<Core.Models.ITemplate> e)
|
||||
{
|
||||
// don't do anything if the factory is not enabled
|
||||
// because, no factory = no models (even if generation is enabled)
|
||||
if (!UmbracoConfig.For.ModelsBuilder().EnableFactory) return;
|
||||
|
||||
// don't do anything if this special key is not found
|
||||
if (!e.AdditionalData.ContainsKey("CreateTemplateForContentType")) return;
|
||||
|
||||
// ensure we have the content type alias
|
||||
if (!e.AdditionalData.ContainsKey("ContentTypeAlias"))
|
||||
throw new InvalidOperationException("The additionalData key: ContentTypeAlias was not found");
|
||||
|
||||
foreach (var template in e.SavedEntities)
|
||||
{
|
||||
// if it is in fact a new entity (not been saved yet) and the "CreateTemplateForContentType" key
|
||||
// is found, then it means a new template is being created based on the creation of a document type
|
||||
if (!template.HasIdentity && template.Content.IsNullOrWhiteSpace())
|
||||
{
|
||||
// ensure is safe and always pascal cased, per razor standard
|
||||
// + this is how we get the default model name in Umbraco.ModelsBuilder.Umbraco.Application
|
||||
var alias = e.AdditionalData["ContentTypeAlias"].ToString();
|
||||
var name = template.Name; // will be the name of the content type since we are creating
|
||||
var className = Application.GetClrName(name, alias);
|
||||
|
||||
var modelNamespace = UmbracoConfig.For.ModelsBuilder().ModelsNamespace;
|
||||
|
||||
// we do not support configuring this at the moment, so just let Umbraco use its default value
|
||||
//var modelNamespaceAlias = ...;
|
||||
|
||||
var markup = ViewHelper.GetDefaultFileContent(
|
||||
modelClassName: className,
|
||||
modelNamespace: modelNamespace/*,
|
||||
modelNamespaceAlias: modelNamespaceAlias*/);
|
||||
|
||||
//set the template content to the new markup
|
||||
template.Content = markup;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ using Umbraco.ModelsBuilder.Building;
|
||||
using Umbraco.ModelsBuilder.Configuration;
|
||||
using Umbraco.ModelsBuilder.Dashboard;
|
||||
using Umbraco.Web.Editors;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Umbraco
|
||||
{
|
||||
@@ -22,8 +23,16 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
/// correct CSRF security is adhered to for angular and it also ensures that this controller is not subseptipal to
|
||||
/// global WebApi formatters being changed since this is always forced to only return Angular JSON Specific formats.
|
||||
/// </remarks>
|
||||
[UmbracoApplicationAuthorize(Core.Constants.Applications.Developer)]
|
||||
public class ModelsBuilderBackOfficeController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly UmbracoServices _umbracoServices;
|
||||
|
||||
public ModelsBuilderBackOfficeController(UmbracoServices umbracoServices)
|
||||
{
|
||||
_umbracoServices = umbracoServices;
|
||||
}
|
||||
|
||||
// invoked by the dashboard
|
||||
// requires that the user is logged into the backoffice and has access to the developer section
|
||||
// beware! the name of the method appears in modelsbuilder.controller.js
|
||||
@@ -93,7 +102,12 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
};
|
||||
}
|
||||
|
||||
internal static void GenerateModels(string modelsDirectory, string bin)
|
||||
private void GenerateModels(string modelsDirectory, string bin)
|
||||
{
|
||||
GenerateModels(_umbracoServices, modelsDirectory, bin);
|
||||
}
|
||||
|
||||
internal static void GenerateModels(UmbracoServices umbracoServices, string modelsDirectory, string bin)
|
||||
{
|
||||
if (!Directory.Exists(modelsDirectory))
|
||||
Directory.CreateDirectory(modelsDirectory);
|
||||
@@ -101,8 +115,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
foreach (var file in Directory.GetFiles(modelsDirectory, "*.generated.cs"))
|
||||
File.Delete(file);
|
||||
|
||||
var umbraco = ModelsBuilderComponent.Umbraco;
|
||||
var typeModels = umbraco.GetAllTypes();
|
||||
var typeModels = umbracoServices.GetAllTypes();
|
||||
|
||||
var ourFiles = Directory.GetFiles(modelsDirectory, "*.cs").ToDictionary(x => x, File.ReadAllText);
|
||||
var parseResult = new CodeParser().ParseWithReferencedAssemblies(ourFiles);
|
||||
@@ -178,4 +191,4 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
public OutOfDateType Status { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
using Umbraco.ModelsBuilder.Api;
|
||||
using Umbraco.ModelsBuilder.Configuration;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PublishedCache.NuCache;
|
||||
@@ -19,59 +20,55 @@ using Umbraco.Web.UI.JavaScript;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Umbraco
|
||||
{
|
||||
// fixme
|
||||
// nucache components wants models so we need to setup models before
|
||||
// however for some reason, this creates a cyclic dependency? => need better debugging info
|
||||
// cos nucache is Core so we need to be Core too
|
||||
// also... should have a generic "modelsbuilder" and "contentcache" components for dependencies!
|
||||
|
||||
[RequiredComponent(typeof(NuCacheComponent))]
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
public class ModelsBuilderComponent : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
{
|
||||
public override void Compose(Composition composition)
|
||||
{
|
||||
base.Compose(composition);
|
||||
composition.Container.Register<Application>(new PerContainerLifetime());
|
||||
|
||||
composition.Container.Register<UmbracoServices>(new PerContainerLifetime());
|
||||
|
||||
var config = UmbracoConfig.For.ModelsBuilder();
|
||||
|
||||
if (config.ModelsMode == ModelsMode.PureLive)
|
||||
InstallLiveModels(composition.Container);
|
||||
ComposeForLiveModels(composition.Container);
|
||||
else if (config.EnableFactory)
|
||||
InstallDefaultModelsFactory(composition.Container);
|
||||
ComposeForDefaultModelsFactory(composition.Container);
|
||||
|
||||
// always setup the dashboard
|
||||
InstallServerVars(composition.Container.GetInstance<IRuntimeState>().Level);
|
||||
composition.Container.Register(typeof(ModelsBuilderBackOfficeController), new PerRequestLifeTime());
|
||||
|
||||
// need to do it here 'cos NuCache wants it during compose?
|
||||
Umbraco = composition.Container.GetInstance<Application>();
|
||||
// setup the API if enabled (and in debug mode)
|
||||
if (config.ApiServer)
|
||||
composition.Container.Register(typeof(ModelsBuilderApiController), new PerRequestLifeTime());
|
||||
}
|
||||
|
||||
public void Initialize(Application application)
|
||||
public void Initialize(UmbracoServices umbracoServices)
|
||||
{
|
||||
Umbraco = application;
|
||||
|
||||
var config = UmbracoConfig.For.ModelsBuilder();
|
||||
|
||||
if (config.Enable)
|
||||
FileService.SavingTemplate += FileService_SavingTemplate;
|
||||
|
||||
// fixme LiveModelsProvider should not be static
|
||||
if (config.ModelsMode.IsLiveNotPure())
|
||||
LiveModelsProvider.Install();
|
||||
LiveModelsProvider.Install(umbracoServices);
|
||||
|
||||
// fixme OutOfDateModelsStatus should not be static
|
||||
if (config.FlagOutOfDateModels)
|
||||
OutOfDateModelsStatus.Install();
|
||||
}
|
||||
|
||||
public static Application Umbraco { get; private set; }
|
||||
|
||||
private void InstallDefaultModelsFactory(IServiceContainer container)
|
||||
private void ComposeForDefaultModelsFactory(IServiceContainer container)
|
||||
{
|
||||
container.RegisterSingleton<IPublishedModelFactory>(factory
|
||||
=> new PublishedModelFactory(factory.GetInstance<TypeLoader>().GetTypes<PublishedContentModel>()));
|
||||
}
|
||||
|
||||
private void InstallLiveModels(IServiceContainer container)
|
||||
private void ComposeForLiveModels(IServiceContainer container)
|
||||
{
|
||||
container.RegisterSingleton<IPublishedModelFactory, PureLiveModelFactory>();
|
||||
|
||||
@@ -102,14 +99,12 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
var umbracoUrlsObject = serverVars["umbracoUrls"];
|
||||
if (umbracoUrlsObject == null)
|
||||
throw new Exception("Null umbracoUrls");
|
||||
var umbracoUrls = umbracoUrlsObject as Dictionary<string, object>;
|
||||
if (umbracoUrls == null)
|
||||
if (!(umbracoUrlsObject is Dictionary<string, object> umbracoUrls))
|
||||
throw new Exception("Invalid umbracoUrls");
|
||||
|
||||
if (!serverVars.ContainsKey("umbracoPlugins"))
|
||||
throw new Exception("Missing umbracoPlugins.");
|
||||
var umbracoPlugins = serverVars["umbracoPlugins"] as Dictionary<string, object>;
|
||||
if (umbracoPlugins == null)
|
||||
if (!(serverVars["umbracoPlugins"] is Dictionary<string, object> umbracoPlugins))
|
||||
throw new Exception("Invalid umbracoPlugins");
|
||||
|
||||
if (HttpContext.Current == null) throw new InvalidOperationException("HttpContext is null");
|
||||
@@ -162,7 +157,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
// + this is how we get the default model name in Umbraco.ModelsBuilder.Umbraco.Application
|
||||
var alias = e.AdditionalData["ContentTypeAlias"].ToString();
|
||||
var name = template.Name; // will be the name of the content type since we are creating
|
||||
var className = Application.GetClrName(name, alias);
|
||||
var className = UmbracoServices.GetClrName(name, alias);
|
||||
|
||||
var modelNamespace = UmbracoConfig.For.ModelsBuilder().ModelsNamespace;
|
||||
|
||||
@@ -180,4 +175,4 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,10 +43,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
File.Delete(path);
|
||||
}
|
||||
|
||||
public static bool IsEnabled
|
||||
{
|
||||
get { return UmbracoConfig.For.ModelsBuilder().FlagOutOfDateModels; }
|
||||
}
|
||||
public static bool IsEnabled => UmbracoConfig.For.ModelsBuilder().FlagOutOfDateModels;
|
||||
|
||||
public static bool IsOutOfDate
|
||||
{
|
||||
|
||||
@@ -36,13 +36,16 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
private int _ver, _skipver;
|
||||
private readonly int _debugLevel;
|
||||
private BuildManager _theBuildManager;
|
||||
private readonly Lazy<UmbracoServices> _umbracoServices;
|
||||
private UmbracoServices UmbracoServices => _umbracoServices.Value;
|
||||
|
||||
private static readonly Regex AssemblyVersionRegex = new Regex("AssemblyVersion\\(\"[0-9]+.[0-9]+.[0-9]+.[0-9]+\"\\)", RegexOptions.Compiled);
|
||||
private const string ProjVirt = "~/App_Data/Models/all.generated.cs";
|
||||
private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" };
|
||||
|
||||
public PureLiveModelFactory(ProfilingLogger logger)
|
||||
public PureLiveModelFactory(Lazy<UmbracoServices> umbracoServices, ProfilingLogger logger)
|
||||
{
|
||||
_umbracoServices = umbracoServices;
|
||||
_logger = logger;
|
||||
_ver = 1; // zero is for when we had no version
|
||||
_skipver = -1; // nothing to skip
|
||||
@@ -161,8 +164,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
|
||||
if (_debugLevel > 0)
|
||||
_logger.Logger.Debug<PureLiveModelFactory>("RazorBuildProvider.CodeGenerationStarted");
|
||||
var provider = sender as RazorBuildProvider;
|
||||
if (provider == null) return;
|
||||
if (!(sender is RazorBuildProvider provider)) return;
|
||||
|
||||
// add the assembly, and add a dependency to a text file that will change on each
|
||||
// compilation as in some environments (could not figure which/why) the BuildManager
|
||||
@@ -309,8 +311,7 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
.ToDictionary(x => x, File.ReadAllText)
|
||||
: new Dictionary<string, string>();
|
||||
|
||||
var umbraco = ModelsBuilderComponent.Umbraco;
|
||||
var typeModels = umbraco.GetAllTypes();
|
||||
var typeModels = UmbracoServices.GetAllTypes();
|
||||
var currentHash = HashHelper.Hash(ourFiles, typeModels);
|
||||
var modelsHashFile = Path.Combine(modelsDirectory, "models.hash");
|
||||
var modelsSrcFile = Path.Combine(modelsDirectory, "models.generated.cs");
|
||||
@@ -598,4 +599,4 @@ namespace Umbraco.ModelsBuilder.Umbraco
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,14 +12,14 @@ using Umbraco.ModelsBuilder.Configuration;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Umbraco
|
||||
{
|
||||
public class Application
|
||||
public class UmbracoServices
|
||||
{
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
private readonly IMediaTypeService _mediaTypeService;
|
||||
private readonly IMemberTypeService _memberTypeService;
|
||||
private readonly IPublishedContentTypeFactory _publishedContentTypeFactory;
|
||||
|
||||
public Application(IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedContentTypeFactory publishedContentTypeFactory)
|
||||
public UmbracoServices(IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedContentTypeFactory publishedContentTypeFactory)
|
||||
{
|
||||
_contentTypeService = contentTypeService;
|
||||
_mediaTypeService = mediaTypeService;
|
||||
@@ -14,9 +14,7 @@
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<TargetFrameworkProfile />
|
||||
<!--
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
-->
|
||||
<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.7.0.0" newVersion="2.7.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.7.0.0" newVersion="2.7.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Diagnostics.Tracing.TraceEvent" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
@@ -275,11 +275,11 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.4.0" newVersion="5.2.4.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.6.0" newVersion="5.2.6.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.4.0" newVersion="5.2.4.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.6.0" newVersion="5.2.6.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Xml.ReaderWriter" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
|
||||
@@ -113,11 +113,11 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.7.0.0" newVersion="2.7.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.7.0.0" newVersion="2.7.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
@@ -157,11 +157,11 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.4.0" newVersion="5.2.4.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.6.0" newVersion="5.2.6.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.4.0" newVersion="5.2.4.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.6.0" newVersion="5.2.6.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
|
||||
|
||||
@@ -528,6 +528,26 @@ namespace Umbraco.Tests.Clr
|
||||
Assert.AreEqual(1, values5D["intValue2"]); // JsonProperty changes property name
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitFieldGetterSetterEmits()
|
||||
{
|
||||
var getter1 = ReflectionUtilities.EmitFieldGetter<Class1, int>("Field1");
|
||||
var getter2 = ReflectionUtilities.EmitFieldGetter<Class1, int>("Field2");
|
||||
var c = new Class1();
|
||||
Assert.AreEqual(33, getter1(c));
|
||||
Assert.AreEqual(66, getter2(c));
|
||||
|
||||
var setter2 = ReflectionUtilities.EmitFieldSetter<Class1, int>("Field2");
|
||||
setter2(c, 99);
|
||||
Assert.AreEqual(99, getter2(c));
|
||||
|
||||
// works on readonly fields!
|
||||
var (getter3, setter3) = ReflectionUtilities.EmitFieldGetterAndSetter<Class1, int>("Field3");
|
||||
Assert.AreEqual(22, getter3(c));
|
||||
setter3(c, 44);
|
||||
Assert.AreEqual(44, getter3(c));
|
||||
}
|
||||
|
||||
// fixme - missing tests specifying 'returned' on method, property
|
||||
|
||||
#region IL Code
|
||||
@@ -550,6 +570,12 @@ namespace Umbraco.Tests.Clr
|
||||
// conv.i4
|
||||
public void SetIntValue2(Class4 object4, object d) => object4.IntValue = (int) (double) d;
|
||||
|
||||
// get field
|
||||
public int GetIntField(Class1 object1) => object1.Field1;
|
||||
|
||||
// set field
|
||||
public void SetIntField(Class1 object1, int i) => object1.Field1 = i;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Test Objects
|
||||
@@ -583,6 +609,10 @@ namespace Umbraco.Tests.Clr
|
||||
public int Value2 { set { } }
|
||||
public int Value3 { get { return 42; } set { } }
|
||||
private int ValueP1 => 42;
|
||||
|
||||
public int Field1 = 33;
|
||||
private int Field2 = 66;
|
||||
public readonly int Field3 = 22;
|
||||
}
|
||||
|
||||
public class Class2 { }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -293,5 +294,24 @@ namespace Umbraco.Tests.Persistence.NPocoTests
|
||||
|
||||
Debug.Print(sql.SQL);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ForUpdate()
|
||||
{
|
||||
var sessionId = Guid.NewGuid();
|
||||
|
||||
var sql = Sql()
|
||||
.SelectAll()
|
||||
.From<UserLoginDto>()
|
||||
.Where<UserLoginDto>(x => x.SessionId == sessionId);
|
||||
|
||||
sql.WriteToConsole();
|
||||
Assert.AreEqual("SELECT * FROM [umbracoUserLogin] WHERE (([umbracoUserLogin].[sessionId] = @0))", sql.SQL.NoCrLf());
|
||||
|
||||
sql = sql.ForUpdate();
|
||||
|
||||
sql.WriteToConsole();
|
||||
Assert.AreEqual("SELECT * FROM [umbracoUserLogin] WITH (UPDLOCK) WHERE (([umbracoUserLogin].[sessionId] = @0))", sql.SQL.NoCrLf());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,6 @@ using System.Runtime.InteropServices;
|
||||
// Umbraco Headless
|
||||
[assembly: InternalsVisibleTo("Umbraco.Headless")]
|
||||
|
||||
// v8
|
||||
[assembly: InternalsVisibleTo("Umbraco.Compat7")]
|
||||
|
||||
// code analysis
|
||||
// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]
|
||||
|
||||
@@ -356,7 +356,7 @@ namespace Umbraco.Web
|
||||
|
||||
logger.Debug<UmbracoModule>(() => $"Response status: Redirect={(pcr.IsRedirect ? (pcr.IsRedirectPermanent ? "permanent" : "redirect") : "none")}, Is404={(pcr.Is404 ? "true" : "false")}, StatusCode={pcr.ResponseStatusCode}");
|
||||
|
||||
if(pcr.Cacheability != default(HttpCacheability))
|
||||
if(pcr.Cacheability != default)
|
||||
response.Cache.SetCacheability(pcr.Cacheability);
|
||||
|
||||
foreach (var cacheExtension in pcr.CacheExtensions)
|
||||
|
||||
Reference in New Issue
Block a user