Compare commits

...

131 Commits

Author SHA1 Message Date
Shannon Deminick a0651f4383 Merge with 4.11.6 2013-03-27 03:09:36 +06:00
Shannon Deminick 9452d5fd09 adds patch for #U4-1754 and updates 2013-03-27 03:08:37 +06:00
Shannon Deminick 1f40d726de adds patch for #U4-1754 2013-03-27 02:59:42 +06:00
Shannon Deminick 2699611ba3 adds patch for #U4-1754 2013-03-27 02:58:59 +06:00
Shannon Deminick 43795f0007 Merge with 4.11.6 2013-03-26 22:03:23 +06:00
Shannon Deminick b1fa06bfe8 Removes unused code. 2013-03-26 22:02:49 +06:00
Shannon Deminick 4dc22b6ce4 Applies patch for #U4-497 for getting exceptions for xslt 2013-03-26 22:02:08 +06:00
Sebastiaan Janssen d4ab60f8af Merge with 4.11.6 2013-03-26 13:29:45 -01:00
Sebastiaan Janssen 883277125a Can't use parameters here as the query gets butchered. 2013-03-26 13:27:46 -01:00
Sebastiaan Janssen 8edfc0ffdd Merge with 4.11.6 2013-03-26 09:53:59 -01:00
Sebastiaan Janssen ff961abaab Actual fix for U4-1987 Error when attempting to save document type 2013-03-26 09:50:48 -01:00
Sebastiaan Janssen b2414c1ab8 Fixes U4-1987 Error when attempting to save document type 2013-03-26 09:33:08 -01:00
Sebastiaan Janssen 9dde86d591 Fixes U4-1999 When copying content with subcontent, the new subcontent data is a
direct reference to the old.
2013-03-26 08:39:50 -01:00
Sebastiaan Janssen b4ce4fbdef Logging warning when package installer can't create a property due to a missing
datatype for that property
2013-03-26 07:55:43 -01:00
Sebastiaan Janssen 4285484c1b Update code comment 2013-03-26 07:19:39 -01:00
Sebastiaan Janssen 2fd299ebfc Change TinyMCE to use the mediaservice to get the original image + some updates
to the new mediaservice method.
2013-03-26 07:15:22 -01:00
Morten Christensen f545f293b1 Adding GetMediaByUrl method to MediaService cause Sebastiaan needs it for less hacky code. 2013-03-26 05:46:20 -01:00
Sebastiaan Janssen b745c0ae90 If the image is not resized, there's probably not going to be an underscore,
just query for the whole image source then.
2013-03-25 18:18:14 -01:00
Sebastiaan Janssen f2efff5411 Temporary fix until we can fix this properly for U4-1812 - Changing Width or
Height in Insert Picture popup results in NaN in other dimension
2013-03-25 18:09:31 -01:00
Sebastiaan Janssen 9ef5890636 Changing sortorder on tabs now also re-orders the tabs in the contenttype editor 2013-03-25 13:33:32 -01:00
Sebastiaan Janssen bc9fd04a36 Related to U4-1847 - Tabs weren't imported with the correct sort order and when
a datatype can't be found we should silently fail and not create the property
that wants that datatype (that's how v4 did it).
2013-03-25 12:49:43 -01:00
Sebastiaan Janssen 185c5d78f1 Query changed due to fix fe02cef72d87 that uses 1/0 instead of True/False 2013-03-25 11:27:54 -01:00
Brian Powell 3ea9963166 Fixes U4-1904 / U4-1905 2013-03-25 10:39:35 -01:00
Sebastiaan Janssen ab40822a98 Fix merge issue by re-applying Stephen Roberts' patch 2013-03-25 10:30:55 -01:00
Sebastiaan Janssen dffce76e29 Merge with 4.11.6 2013-03-25 10:24:36 -01:00
Sebastiaan Janssen d1e02f506c PropertyGroupId can be null 2013-03-25 07:51:44 -01:00
Morten Christensen 5e18d13178 Fixing parsing issue with saving boolean values in the Integer column for Members.
Related to issue U4-1989
2013-03-23 07:22:43 -01:00
Shannon Deminick 1dfca6836d Merge with 4.11.6 2013-03-23 02:34:59 +06:00
Shannon Deminick dbbdd16bb9 Fixes: #U4-497 2013-03-23 02:34:34 +06:00
Shannon Deminick 74362fba23 Merge 2013-03-22 22:11:26 +06:00
Morten Christensen 112502cf18 Fixes U4-547 2013-03-22 15:09:36 -01:00
Shannon Deminick 1db7f808c9 Merge with 4.11.6 2013-03-22 21:59:52 +06:00
Shannon Deminick 762cca145f Fixes: #U4-1931 - allow empty string in dictionary item. 2013-03-22 21:59:21 +06:00
Morten Christensen 65dc5eaeee Corrects incorrect sql query in the ContentTypeBaseRepository and looping through property types in the DataTypeService.
Adds initial test fixture for the DataTypeService.
Fixes U4-1939
2013-03-22 14:54:44 -01:00
Morten Christensen 4f81e06d3d Fixes U4-1894 by ensuring that all overloads of SetValue uses the IOHelper.SafeFileName 2013-03-22 14:18:45 -01:00
Morten Christensen 6b74b75b6f Adding a few checks to ensure that we don't try to bulk save an empty list 2013-03-22 14:08:20 -01:00
Morten Christensen 98e53b3d74 Correcting a few checks for multiple or single item imports in the PackagingService 2013-03-22 13:58:21 -01:00
Morten Christensen a1f01f9d5c re-inverting the check for existing datatypedefinitions in the packaging service 2013-03-22 13:48:51 -01:00
Sebastiaan Janssen f5d8cb0275 Merge 2013-03-22 13:36:26 -01:00
Sebastiaan Janssen 0d8b65caea Merge 2013-03-22 13:36:04 -01:00
Sebastiaan Janssen 70285991bb I think this was an oversight, if a definition is NOT null, then fill it 2013-03-22 13:35:47 -01:00
Sebastiaan Janssen a336eaa4a1 Check all of the elements for null, apparently any kind of installable thing can
be missing from the install xml file
2013-03-22 13:35:19 -01:00
Morten Christensen fdefe993b7 Fixes U4-1990 2013-03-22 12:54:46 -01:00
Morten Christensen ba0e72a1c1 Fixes U4-1937 by calling save when media is updated with new properties. Also uses the incremented folder count instead of the property id. 2013-03-22 12:30:20 -01:00
Morten Christensen c5710277a5 Redoing the fix for U4-1875 2013-03-22 12:13:06 -01:00
Morten Christensen 5cd2d568e3 Fixes U4-1938 by actually calling and checking the Before/AfterDelete events for DataTypeDefinitions.
Backported from 32fb51f603a3
2013-03-22 11:12:32 -01:00
Morten Christensen 9c89a56d8d Fixes U4-1938 by actually calling and checking the Before/AfterDelete events for DataTypeDefinitions. 2013-03-22 10:53:07 -01:00
Morten Christensen 9ba7664f78 Updating repositories to handle sort order upon updating in a consistent manner.
Related to U4-1828
2013-03-22 10:34:05 -01:00
Morten Christensen 4b87a5c2d3 Adding safe alias cast to Templates.
Updating doc type create dialog to verify alias before saving.
Updating ContentTypeRepository to Mandate that the alias is not empty.
Fixes the cause for U4-1976
2013-03-22 09:56:21 -01:00
Morten Christensen f0699afb6e Fixes U4-1974 2013-03-21 18:45:06 -01:00
Morten Christensen b4d5658d45 Fixes U4-1828 by correctly incrementing the sortorder ... doh! 2013-03-21 17:34:08 -01:00
Morten Christensen d485c3da97 Fixes U4-1875 by correcting the Creating events in the ContentService and MediaService, so null is returned if the creation of an object is cancelled.
In the legacy Document and Media classes we check if the created object is null to determine if the event has been cancelled through the new api.
2013-03-21 16:09:45 -01:00
Morten Christensen 1214082997 Fixes U4-1883 by setting the Document/Media UpdateDate property in the Save/SaveAndPublish methods 2013-03-21 14:56:50 -01:00
Morten Christensen 1a56e6693a Removing dictionary from DataTypeDefinition as it wasn't used.
Updating package xml to include DatabaseType for testing.
2013-03-21 14:50:39 -01:00
Morten Christensen c6b7f20dab Fixes U4-1849 by introducing a new attribute for packaged DataTypes, so it stores information about the database type.
Will still default to Ntext, but seeing as the database type has never been used before it always defaulted to Ntext.
2013-03-21 14:40:17 -01:00
Morten Christensen 5cc55ad6e2 Fixing U4-1948 by setting the Published property when using document.Publish so updating the cache won't be skipped. 2013-03-21 13:51:45 -01:00
Morten Christensen a55fedab0a Adding a few checks to ensure package installation doesn't fail when properties are not present in the xml. 2013-03-21 13:40:54 -01:00
Morten Christensen 0e12f14a4a Making the export method internal until its been properly implemented 2013-03-21 13:10:31 -01:00
Morten Christensen 3e25b71d9e Updating test for adding PropertyType outside a group to use the proper method for doing so. 2013-03-21 12:58:55 -01:00
Morten Christensen 63de9e6691 Refactoring package installer to use the new PackagingService.
Refactoring ImportDocumentType dialog to import through the PackagingService.
Making a few corrections to the ProppertyGroup and PropertyType classes to support bulk saving.
2013-03-21 12:34:10 -01:00
Morten Christensen b9ea85d29d Updating Template to have a lazy master template id.
Adding a few new methods to the DataTypeService, which were needed for the import of DataTypes.
Adding bulk saving of templates.
Adding TopologicalSorter for sorting dependencies.
Implementing import of DataTypes and Templates.
Renaming the import test fixture for consistency after having creating the PackagingService.
2013-03-20 20:31:44 -01:00
Morten Christensen d0787e92fe Implementing PackagingService and moving Import Export methods to this service to have it specialized and centralized around packaging operations. 2013-03-20 13:51:46 -01:00
Morten Christensen ffe9953c43 Merge 2013-03-19 20:08:40 -01:00
Morten Christensen 99a9f1ab87 Adding note to mediaService regarding issue U4-1937 2013-03-19 20:06:33 -01:00
Morten Christensen 7def26a489 Implementing import methods in the Content- and ContentType services.
Adding tests to verify import is correct.
2013-03-19 20:05:55 -01:00
Shannon Deminick a76ffe8daf Backported changes from 6.1 to fix how RePublishAll behaves in the content service to ensure its the same as what was done with
Document.RePublishAll
2013-03-20 00:19:36 +06:00
Sebastiaan Janssen 259fbcb8f0 Fixed U4-1934 Error in comments of config files 2013-03-18 08:50:24 -01:00
Shannon Deminick ee9f91b5cf Merge with 4.11.6 2013-03-15 11:31:34 +06:00
Shannon Deminick db3f21429e Fixes infinite loop bug with string trimming. 2013-03-15 11:31:11 +06:00
Shannon Deminick 033692d7ee had some strange issues with unit tests, added error checks. 2013-03-15 08:26:49 +04:00
Shannon Deminick 23146cb12a Merge with 4.11.6 2013-03-15 08:06:26 +04:00
Shannon Deminick 04b9607741 Fixes: #U4-1916 and another issue for vdirs, added unit tests, changed UI web project to always
launch in a VDIR.
2013-03-15 08:03:19 +04:00
Stephen Roberts 0e392b398c Fixed Property order for document types with Master document types. 2013-03-14 11:08:02 +00:00
Sebastiaan Janssen 5914690ad8 Allow leading sign in number field so that negative numbers are supported 2013-03-25 10:09:02 -01:00
Morten Christensen c4aa9095f2 Fixes U4-1858 by ensuring that the text field is reset before setting or removing a value 2013-03-13 20:24:21 -01:00
Morten Christensen 79ce586c8b Fixes U4-1808 by removing the database lookup from an id that was resolved from the media url 2013-03-13 19:26:22 -01:00
Morten Christensen 8fba03c05d Fixes U4-1863 and U4-1908 by ensuring that content and media are loaded in the same manner through the new api 2013-03-13 18:55:25 -01:00
Shannon Deminick 2fdcb9164a Fix merge issues 2013-03-12 00:19:06 +04:00
Shannon Deminick 7404a1f93d Merge with 4.11.6 2013-03-12 00:14:50 +04:00
Shannon Deminick c8b8b28e9b applies patch for #U4-1890 2013-03-12 00:10:59 +04:00
Shannon Deminick 5bd2571395 Merge 2013-03-12 00:01:14 +04:00
Shannon Deminick c0cd157e60 applies patch for #U4-1890 2013-03-12 00:00:55 +04:00
Sebastiaan Janssen ac2f9b172c .transformed files are auto-generated and shouldn't be under source control 2013-03-11 17:15:30 -01:00
Sebastiaan Janssen b8e4a73c3b Revert Casey's mistakenly added files 2013-03-11 15:55:35 -01:00
Shannon Deminick 63192f3a65 Merge 2013-03-11 22:04:06 +06:00
Shannon Deminick 727f62d418 Merge with 4.11.6 2013-03-11 21:49:27 +06:00
Shannon Deminick 68c4255a51 updates proper error handling for razor script macros 2013-03-11 21:49:04 +06:00
Shannon Deminick 187af3e361 Fixed merge issue 2013-03-11 21:23:35 +06:00
Shannon Deminick c6f29a50d6 Merge with 4.11.6 2013-03-11 21:17:57 +06:00
Shannon Deminick d07212c89b Fixed changes with new MacroErrors config and how macros are rendered so it supports all macro types and also fixes up a bit of code
in the umbraco.macro class.
2013-03-11 21:06:02 +06:00
Shannon Deminick 28c55320a1 Updates the pull request for handling macro errors.
Backports fixes for partial view macros from 6.x - U4-1488, U4-1844, U4-1730, U4-1843
2013-03-11 20:11:11 +06:00
Morten Christensen cb0dd70434 Minor change to the SqlSyntaxProvidersResolver in the CoreBootManager as per Shannons review. 2013-03-11 12:44:12 -01:00
Shannon Deminick fd58017e97 imported patches for pull request spudstuff/u4497 2013-03-11 18:49:45 +06:00
Morten Christensen 928d92fce4 Making the Sql Syntax Providers public and changing a few names and bits for consistency.
Adding resolver for the syntax providers and wiring it up in the boot manager.
2013-03-09 10:43:34 -01:00
Casey Neehouse 09408b898e Merge 2013-03-08 19:38:33 +05:00
Morten Christensen d1b05332c5 Manually adds fix for U4-1869 from 6.0.3 branch 2013-03-07 20:28:13 -01:00
Morten Christensen 836b0f39c2 Additional correction of the implementation for U4-1869 2013-03-07 20:19:39 -01:00
Morten Christensen 1b01386673 Changing the initial fix of U4-1869 to use UrlReplacingCharacters 2013-03-07 19:56:59 -01:00
Morten Christensen 2a09f02afb Fixing incorrect sql syntax when the query contains two expressions. 2013-03-07 19:56:10 -01:00
Morten Christensen ee95434cea Implements U4-1869 by adding the 3 characters to the list of reserved characters. 2013-03-07 19:04:25 -01:00
Casey Neehouse caad0afed8 Corrects u4-1870 - Refactor Load Content SQL to check if ID is in published list
versus using a join that can cause duplicate entries.
2013-03-07 21:00:31 +05:00
Morten Christensen fe08e7fc2f Fixes U4-1865 by excluding trashed items from GetByLevel method for both Content and Media 2013-03-07 13:42:14 -01:00
Morten Christensen 4ad96b49e7 Fixes U4-1862 2013-03-07 13:35:17 -01:00
Morten Christensen 9a1bb4a2dd Adding unit test to assert issue with issue with creation of property types outside a property type group.
Fixes U4-1861.
2013-03-07 13:33:22 -01:00
Sebastiaan Janssen c39f902ed5 And one more fix for U4-1845 to make upgrades succeed as well 2013-03-06 14:30:09 -01:00
Sebastiaan Janssen b7dc052cb2 Additional fixes for U4-1845 to maintain compatibility for people using the
wrong connection string
2013-03-06 14:09:01 -01:00
Morten Christensen 0c77114cd5 Fixes U4-1845 by correcting the sql ce connectionstring 2013-03-06 13:36:03 -01:00
Morten Christensen 222a5237b0 Version updated to 6.0.3 2013-03-06 12:03:01 -01:00
Morten Christensen de55cb8392 Correcting fix for U4-1835 2013-03-06 08:32:05 -01:00
Morten Christensen df164ee618 Fixes U4-1835 by checking if the value is null before running the regex validation against the value. 2013-03-06 08:02:09 -01:00
Morten Christensen 21b0687a57 Fixes U4-1837 by syncing tree after saveing DataTypeDefinition 2013-03-06 07:57:00 -01:00
Morten Christensen 9310efa280 Fixes U4-1831 by catching exception if there is no current logged in user. 2013-03-06 07:54:09 -01:00
Morten Christensen a41b55a9e6 Fixes U4-1846 2013-03-06 07:50:20 -01:00
Morten Christensen af2d8a4755 Fix related to U4-1407 but for Media. We already committed this fix for Content. 2013-03-06 07:49:29 -01:00
Shannon Deminick d48e339b81 Fixes: #U4-1844, #U4-1730, #U4-1843 2013-03-06 04:12:28 +06:00
Shannon Deminick 9b6d498cf7 Merge with 4.11.6 2013-03-06 03:17:47 +06:00
Shannon Deminick 62d365573f Back ports fixes for: #U4-1614, #U4-793 - preview working properly in mvc 2013-03-06 03:17:18 +06:00
Shannon Deminick 04bf011fcd Merge with 4.11.6 2013-03-05 23:55:09 +06:00
Shannon Deminick f3b7a8a581 Fixes: #U4-1471 - issue with having NewRelic installed and some sort of conflict with shutting down
our logger.
2013-03-05 23:49:45 +06:00
Shannon Deminick 5d62902684 Fixes up the double event for MakeNew on document (#U4-1737) 2013-03-05 22:34:31 +06:00
Shannon Deminick 82d645a0f7 Merge with 4.11.6 2013-03-05 22:18:53 +06:00
Shannon Deminick a8936de638 Fixes: #U4-1834 2013-03-05 21:52:22 +06:00
Shannon Deminick a765f36d24 Adds unit tests for DynamicNode and DynamicPublishedContent, fixes both when querying for recursive properties.
Fixes: #U4-1839
2013-03-05 21:00:16 +06:00
Shannon Deminick 6b691eb461 Merge with 4.11.6 2013-03-05 08:34:14 +06:00
Shannon Deminick 046da1a8ce Fixes: #U4-1824 - issue with razor dynamic node property access performance enhancements. 2013-03-05 07:06:41 +06:00
Shannon Deminick ca7abd6c78 Merge 2013-03-05 06:08:59 +06:00
Shannon Deminick 452688b2bb Merge with 4.11.6 2013-03-05 05:57:35 +06:00
Shannon Deminick 7cc0f2a514 Fixes: #U4-1819 2013-03-05 05:56:53 +06:00
Sebastiaan Janssen a2251fe062 Created branch 6.0.3 2013-03-04 10:19:22 -01:00
Sebastiaan Janssen 3d0684eac0 Closing branch 6.0.2 2013-03-04 10:18:18 -01:00
Sebastiaan Janssen a8fafaa194 Added tag Release-6.0.2 for changeset b247b35d8211 2013-03-04 10:18:08 -01:00
189 changed files with 10304 additions and 2426 deletions
+1
View File
@@ -44,6 +44,7 @@ src\Umbraco.Web.UI\[Mm]acro[Ss]cripts\*
src\Umbraco.Web.UI\[Xx]slt\*
src\Umbraco.Web.UI\[Ii]mages\*
src\Umbraco.Web.UI\[Ss]cripts\*
src\Umbraco.Web.UI\Web.*.config.transformed
umbraco\presentation\umbraco\plugins\uComponents\uComponentsInstaller.ascx
umbraco\presentation\packages\uComponents\MultiNodePicker\CustomTreeService.asmx
+1
View File
@@ -26,3 +26,4 @@ ff3bb24ea0c915878396a6ae27f1ff164e8ac150 Release-6.0.0-beta
56015ac26f5ab60e3c61b1d09075297b660afa07 Release-6.0.0-RC
1719fbd857f28b376639ac2aa0abada0ef2e7560 Release-6.0.0
e02f5aebb87e3f07d27376647756caa9762931d8 Release-4.11.4
b247b35d821144849f551e02da8ba719f91d5fb0 Release-6.0.2
+1 -1
View File
@@ -1,5 +1,5 @@
@ECHO OFF
SET release=6.0.2
SET release=6.0.3
SET comment=
SET version=%release%
+3 -1
View File
@@ -149,7 +149,9 @@ namespace SqlCE4Umbraco
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory") as string;
if (!string.IsNullOrEmpty(dataDirectory))
{
path = path.Replace("|DataDirectory|", dataDirectory + System.IO.Path.DirectorySeparatorChar);
path = path.Contains(@"|\")
? path.Replace("|DataDirectory|", dataDirectory)
: path.Replace("|DataDirectory|", dataDirectory + System.IO.Path.DirectorySeparatorChar);
}
}
@@ -154,6 +154,9 @@ namespace Umbraco.Core.Configuration
/// This will return the MVC area that we will route all custom routes through like surface controllers, etc...
/// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin
/// we will convert the '/' to '-' and use that as the path. its a bit lame but will work.
///
/// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something
/// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco".
/// </remarks>
internal static string UmbracoMvcArea
{
@@ -163,7 +166,7 @@ namespace Umbraco.Core.Configuration
{
throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified");
}
return Path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim();
return Path.TrimStart(SystemDirectories.Root).TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
}
}
@@ -1216,6 +1216,40 @@ namespace Umbraco.Core.Configuration
}
}
private static MacroErrorBehaviour? _macroErrorBehaviour;
/// <summary>
/// This configuration setting defines how to handle macro errors:
/// - Inline - Show error within macro as text (default and current Umbraco 'normal' behavior)
/// - Silent - Suppress error and hide macro
/// - Throw - Throw an exception and invoke the global error handler (if one is defined, if not you'll get a YSOD)
/// </summary>
/// <value>MacroErrorBehaviour enum defining how to handle macro errors.</value>
public static MacroErrorBehaviour MacroErrorBehaviour
{
get
{
if (_macroErrorBehaviour == null)
{
try
{
var behaviour = MacroErrorBehaviour.Inline;
var value = GetKey("/settings/content/MacroErrors");
if (value != null)
{
Enum<MacroErrorBehaviour>.TryParse(value, true, out behaviour);
}
_macroErrorBehaviour = behaviour;
}
catch (Exception ex)
{
LogHelper.Error<UmbracoSettings>("Could not load /settings/content/MacroErrors from umbracosettings.config", ex);
_macroErrorBehaviour = MacroErrorBehaviour.Inline;
}
}
return _macroErrorBehaviour.Value;
}
}
/// <summary>
/// Configuration regarding webservices
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("6.0.2");
private static readonly Version Version = new Version("6.0.3");
/// <summary>
/// Gets the current version of Umbraco.
+32 -11
View File
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
@@ -10,6 +8,7 @@ using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix;
using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Publishing;
@@ -61,27 +60,36 @@ namespace Umbraco.Core
new PetaPocoUnitOfWorkProvider(dbFactory),
new FileUnitOfWorkProvider(),
new PublishingStrategy());
//create the ApplicationContext
ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext);
//initialize the DatabaseContext
dbContext.Initialize();
CreateApplicationContext(dbContext, serviceContext);
InitializeApplicationEventsResolver();
InitializeResolvers();
//initialize the DatabaseContext
dbContext.Initialize();
//now we need to call the initialize methods
ApplicationEventsResolver.Current.ApplicationEventHandlers
.ForEach(x => x.OnApplicationInitialized(UmbracoApplication, ApplicationContext));
_isInitialized = true;
return this;
}
/// <summary>
/// Creates and assigns the application context singleton
/// </summary>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
protected virtual void CreateApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext)
{
//create the ApplicationContext
ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext);
}
/// <summary>
/// Special method to initialize the ApplicationEventsResolver and any modifications required for it such
/// as adding custom types to the resolver.
@@ -135,8 +143,7 @@ namespace Umbraco.Core
if (_isComplete)
throw new InvalidOperationException("The boot manager has already been completed");
//freeze resolution to not allow Resolvers to be modified
Resolution.Freeze();
FreezeResolution();
//stop the timer and log the output
_timer.Dispose();
@@ -161,6 +168,14 @@ namespace Umbraco.Core
return this;
}
/// <summary>
/// Freeze resolution to not allow Resolvers to be modified
/// </summary>
protected virtual void FreezeResolution()
{
Resolution.Freeze();
}
/// <summary>
/// Create the resolvers
/// </summary>
@@ -169,6 +184,12 @@ namespace Umbraco.Core
RepositoryResolver.Current = new RepositoryResolver(
new RepositoryFactory());
SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver(
new[] { typeof(MySqlSyntaxProvider), typeof(SqlCeSyntaxProvider), typeof(SqlServerSyntaxProvider) })
{
CanResolveBeforeFrozen = true
};
CacheRefreshersResolver.Current = new CacheRefreshersResolver(
() => PluginManager.Current.ResolveCacheRefreshers());
+18 -17
View File
@@ -112,7 +112,7 @@ namespace Umbraco.Core
public void ConfigureEmbeddedDatabaseConnection()
{
const string providerName = "System.Data.SqlServerCe.4.0";
const string connectionString = "Datasource=|DataDirectory|Umbraco.sdf";
const string connectionString = @"Data Source=|DataDirectory|\Umbraco.sdf";
SaveConnectionString(connectionString, providerName);
@@ -337,21 +337,22 @@ namespace Umbraco.Core
internal void Initialize(string providerName)
{
if (providerName.StartsWith("MySql"))
{
SyntaxConfig.SqlSyntaxProvider = MySqlSyntax.Provider;
}
else if (providerName.Contains("SqlServerCe"))
{
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
}
else
{
SyntaxConfig.SqlSyntaxProvider = SqlServerSyntax.Provider;
}
_providerName = providerName;
_configured = true;
try
{
SqlSyntaxContext.SqlSyntaxProvider =
SqlSyntaxProvidersResolver.Current.GetByProviderNameOrDefault(providerName);
_configured = true;
}
catch (Exception e)
{
_configured = false;
LogHelper.Info<DatabaseContext>("Initialization of the DatabaseContext failed with following error: " + e.Message);
LogHelper.Info<DatabaseContext>(e.StackTrace);
}
}
internal DatabaseSchemaResult ValidateDatabaseSchema()
@@ -388,7 +389,7 @@ namespace Umbraco.Core
var message = string.Empty;
var database = new UmbracoDatabase(_connectionString, ProviderName);
var supportsCaseInsensitiveQueries = SyntaxConfig.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
if (supportsCaseInsensitiveQueries == false)
{
message = "<p>&nbsp;</p><p>The database you're trying to use does not support case insensitive queries. <br />We currently do not support these types of databases.</p>" +
@@ -411,7 +412,7 @@ namespace Umbraco.Core
}
else
{
if (SyntaxConfig.SqlSyntaxProvider == MySqlSyntaxProvider.Instance)
if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider))
{
message = "<p>&nbsp;</p><p>Congratulations, the database step ran successfully!</p>" +
"<p>Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.</p>" +
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Umbraco.Core.Events
{
// Provides information on the macro that caused an error
public class MacroErrorEventArgs : System.EventArgs
{
/// <summary>
/// Name of the faulting macro.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Alias of the faulting macro.
/// </summary>
public string Alias { get; set; }
/// <summary>
/// Filename, file path, fully qualified class name, or other key used by the macro engine to do it's processing of the faulting macro.
/// </summary>
public string ItemKey { get; set; }
/// <summary>
/// Exception raised.
/// </summary>
public Exception Exception { get; set; }
/// <summary>
/// Gets or sets the desired behaviour when a matching macro causes an error. See
/// <see cref="MacroErrorBehaviour"/> for definitions. By setting this in your event
/// you can override the default behaviour defined in UmbracoSettings.config.
/// </summary>
/// <value>Macro error behaviour enum.</value>
public MacroErrorBehaviour Behaviour { get; set; }
}
}
+15
View File
@@ -8,6 +8,7 @@ using System.IO;
using System.Configuration;
using System.Web;
using System.Text.RegularExpressions;
using System.Xml;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
@@ -230,6 +231,20 @@ namespace Umbraco.Core.IO
filePath = String.Empty;
}
//Break up the file in name and extension before applying the UrlReplaceCharacters
var fileNamePart = filePath.Substring(0, filePath.LastIndexOf('.'));
var ext = filePath.Substring(filePath.LastIndexOf('.'));
//Because the file usually is downloadable as well we check characters against 'UmbracoSettings.UrlReplaceCharacters'
XmlNode replaceChars = UmbracoSettings.UrlReplaceCharacters;
foreach (XmlNode n in replaceChars.SelectNodes("char"))
{
if (n.Attributes.GetNamedItem("org") != null && n.Attributes.GetNamedItem("org").Value != "")
fileNamePart = fileNamePart.Replace(n.Attributes.GetNamedItem("org").Value, XmlHelper.GetNodeValue(n));
}
filePath = string.Concat(fileNamePart, ext);
// Adapted from: http://stackoverflow.com/a/4827510/5018
// Combined both Reserved Characters and Character Data
// from http://en.wikipedia.org/wiki/Percent-encoding
+14 -4
View File
@@ -183,16 +183,26 @@ namespace Umbraco.Core.IO
}
}
private static string _root;
/// <summary>
/// Gets the root path of the application
/// </summary>
public static string Root
{
get
{
string appPath = HttpRuntime.AppDomainAppVirtualPath ?? string.Empty;
if (appPath == "/")
appPath = string.Empty;
if (_root == null)
{
string appPath = HttpRuntime.AppDomainAppVirtualPath ?? string.Empty;
if (appPath == "/")
appPath = string.Empty;
return appPath;
_root = appPath;
}
return _root;
}
//Only required for unit tests
internal set { _root = value; }
}
}
@@ -64,23 +64,28 @@ namespace Umbraco.Core.Logging
{
_forceStop = true;
var windowsIdentity = WindowsIdentity.GetCurrent();
base.Append(new LoggingEvent(new LoggingEventData
{
Level = Level.Error,
Message =
"Unable to clear out the AsynchronousRollingFileAppender buffer in the allotted time, forcing a shutdown",
TimeStamp = DateTime.UtcNow,
Identity = "",
ExceptionString = "",
UserName = windowsIdentity != null ? windowsIdentity.Name : "",
Domain = AppDomain.CurrentDomain.FriendlyName,
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
LocationInfo =
new LocationInfo(this.GetType().Name, "OnClose", "AsynchronousRollingFileAppender.cs", "59"),
LoggerName = this.GetType().FullName,
Properties = new PropertiesDictionary(),
})
);
var logEvent = new LoggingEvent(new LoggingEventData
{
Level = global::log4net.Core.Level.Error,
Message =
"Unable to clear out the AsynchronousRollingFileAppender buffer in the allotted time, forcing a shutdown",
TimeStamp = DateTime.UtcNow,
Identity = "",
ExceptionString = "",
UserName = windowsIdentity != null ? windowsIdentity.Name : "",
Domain = AppDomain.CurrentDomain.FriendlyName,
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
LocationInfo =
new LocationInfo(this.GetType().Name, "OnClose", "AsynchronousRollingFileAppender.cs", "59"),
LoggerName = this.GetType().FullName,
Properties = new PropertiesDictionary(),
});
if (this.DateTimeStrategy != null)
{
base.Append(logEvent);
}
}
base.OnClose();
+23
View File
@@ -0,0 +1,23 @@
namespace Umbraco.Core
{
public enum MacroErrorBehaviour
{
/// <summary>
/// Default umbraco behavior - show an inline error within the
/// macro but allow the page to continue rendering.
/// </summary>
Inline,
/// <summary>
/// Silently eat the error and do not display the offending macro.
/// </summary>
Silent,
/// <summary>
/// Throw an exception which can be caught by the global error handler
/// defined in Application_OnError. If no such error handler is defined
/// then you'll see the Yellow Screen Of Death (YSOD) error page.
/// </summary>
Throw
}
}
+8 -4
View File
@@ -117,8 +117,10 @@ namespace Umbraco.Core.Models
if (fileName.LastIndexOf(@"\") > 0)
fileName = fileName.Substring(fileName.LastIndexOf(@"\") + 1);
if (string.IsNullOrEmpty(fileName) == false)
SetFileOnContent(content, propertyTypeAlias, fileName, value.InputStream);
var name = IOHelper.SafeFileName(fileName);
if (string.IsNullOrEmpty(name) == false)
SetFileOnContent(content, propertyTypeAlias, name, value.InputStream);
}
/// <summary>
@@ -131,8 +133,10 @@ namespace Umbraco.Core.Models
public static void SetValue(this IContentBase content, string propertyTypeAlias, string fileName,
Stream fileStream)
{
if (string.IsNullOrEmpty(fileName) == false && fileStream != null)
SetFileOnContent(content, propertyTypeAlias, fileName, fileStream);
var name = IOHelper.SafeFileName(fileName);
if (string.IsNullOrEmpty(name) == false && fileStream != null)
SetFileOnContent(content, propertyTypeAlias, name, fileStream);
}
private static void SetFileOnContent(IContentBase content, string propertyTypeAlias, string name, Stream fileStream)
+1 -1
View File
@@ -381,7 +381,7 @@ namespace Umbraco.Core.Models
oldPropertyGroup.PropertyTypes.RemoveItem(propertyTypeAlias);
}
propertyType.PropertyGroupId = default(int);
propertyType.PropertyGroupId = new Lazy<int>(() => default(int));
propertyType.ResetDirtyProperties();
var propertyGroup = PropertyGroups.First(x => x.Name == propertyGroupName);
@@ -140,8 +140,8 @@ namespace Umbraco.Core.Models
if (CompositionPropertyGroups.Any(x => x.Name == groupName))
{
var first = CompositionPropertyGroups.First(x => x.Name == groupName && x.ParentId.HasValue == false);
propertyGroup.ParentId = first.Id;
var firstGroup = CompositionPropertyGroups.First(x => x.Name == groupName && x.ParentId.HasValue == false);
propertyGroup.SetLazyParentId(new Lazy<int?>(() => firstGroup.Id));
}
if (PropertyGroups.Any())
@@ -166,7 +166,7 @@ namespace Umbraco.Core.Models
{
if (PropertyGroups.Contains(propertyGroupName))
{
propertyType.PropertyGroupId = PropertyGroups[propertyGroupName].Id;
propertyType.PropertyGroupId = new Lazy<int>(() => PropertyGroups[propertyGroupName].Id);
PropertyGroups[propertyGroupName].PropertyTypes.Add(propertyType);
}
else
@@ -179,7 +179,8 @@ namespace Umbraco.Core.Models
{
var parentPropertyGroup = CompositionPropertyGroups.First(x => x.Name == propertyGroupName && x.ParentId.HasValue == false);
propertyGroup.SortOrder = parentPropertyGroup.SortOrder;
propertyGroup.ParentId = parentPropertyGroup.Id;
//propertyGroup.ParentId = parentPropertyGroup.Id;
propertyGroup.SetLazyParentId(new Lazy<int?>(() => parentPropertyGroup.Id));
}
PropertyGroups.Add(propertyGroup);
@@ -8,6 +8,17 @@ namespace Umbraco.Core.Models
/// </summary>
public class ContentTypeSort : IValueObject
{
public ContentTypeSort()
{
}
public ContentTypeSort(Lazy<int> id, int sortOrder, string @alias)
{
Id = id;
SortOrder = sortOrder;
Alias = alias;
}
/// <summary>
/// Gets or sets the Id of the ContentType
/// </summary>
@@ -15,12 +15,12 @@ namespace Umbraco.Core.Models
public enum DataTypeDatabaseType
{
[EnumMember]
Integer,
[EnumMember]
Date,
Ntext,
[EnumMember]
Nvarchar,
[EnumMember]
Ntext /*, Object*/
Integer,
[EnumMember]
Date
}
}
@@ -172,7 +172,9 @@ namespace Umbraco.Core.Models
internal override void AddingEntity()
{
base.AddingEntity();
Key = Guid.NewGuid();
if(Key == default(Guid))
Key = Guid.NewGuid();
}
}
}
@@ -66,6 +66,15 @@ namespace Umbraco.Core.Models.EntityBase
[DataMember]
public DateTime UpdateDate { get; set; }
/// <summary>
/// Gets or sets the WasCancelled flag, which is used to track
/// whether some action against an entity was cancelled through some event.
/// This only exists so we have a way to check if an event was cancelled through
/// the new api, which also needs to take effect in the legacy api.
/// </summary>
[IgnoreDataMember]
internal bool WasCancelled { get; set; }
/// <summary>
/// Property changed event
/// </summary>
+17 -3
View File
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Models
public class PropertyGroup : Entity, IEquatable<PropertyGroup>
{
private string _name;
private int? _parentId;
private Lazy<int?> _parentId;
private int _sortOrder;
private PropertyTypeCollection _propertyTypes;
@@ -60,10 +60,15 @@ namespace Umbraco.Core.Models
[DataMember]
public int? ParentId
{
get { return _parentId; }
get
{
if (_parentId == null)
return default(int?);
return _parentId.Value;
}
set
{
_parentId = value;
_parentId = new Lazy<int?>(() => value);
OnPropertyChanged(ParentIdSelector);
}
}
@@ -96,6 +101,15 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Sets the ParentId from the lazy integer id
/// </summary>
/// <param name="id">Id of the Parent</param>
internal void SetLazyParentId(Lazy<int?> id)
{
_parentId = id;
}
public bool Equals(PropertyGroup other)
{
//Check whether the compared object is null.
+5 -5
View File
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Models
private string _alias;
private string _description;
private int _dataTypeDefinitionId;
private int _propertyGroupId;
private Lazy<int> _propertyGroupId;
private Guid _dataTypeId;
private DataTypeDatabaseType _dataTypeDatabaseType;
private bool _mandatory;
@@ -61,7 +61,7 @@ namespace Umbraco.Core.Models
private static readonly PropertyInfo HelpTextSelector = ExpressionHelper.GetPropertyInfo<PropertyType, string>(x => x.HelpText);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<PropertyType, int>(x => x.SortOrder);
private static readonly PropertyInfo ValidationRegExpSelector = ExpressionHelper.GetPropertyInfo<PropertyType, string>(x => x.ValidationRegExp);
private static readonly PropertyInfo PropertyGroupIdSelector = ExpressionHelper.GetPropertyInfo<PropertyType, int>(x => x.PropertyGroupId);
private static readonly PropertyInfo PropertyGroupIdSelector = ExpressionHelper.GetPropertyInfo<PropertyType, Lazy<int>>(x => x.PropertyGroupId);
/// <summary>
/// Gets of Sets the Name of the PropertyType
@@ -153,7 +153,7 @@ namespace Umbraco.Core.Models
/// Gets or Sets the PropertyGroup's Id for which this PropertyType belongs
/// </summary>
[DataMember]
internal int PropertyGroupId
internal Lazy<int> PropertyGroupId
{
get { return _propertyGroupId; }
set
@@ -335,8 +335,8 @@ namespace Umbraco.Core.Models
if (Mandatory && (value == null || string.IsNullOrEmpty(value.ToString())))
return false;
//Check against Regular Expression for Legacy DataTypes
if(!string.IsNullOrEmpty(ValidationRegExp))
//Check against Regular Expression for Legacy DataTypes - Validation exists and value is not null:
if(string.IsNullOrEmpty(ValidationRegExp) == false && (value != null && string.IsNullOrEmpty(value.ToString()) == false))
{
var regexPattern = new Regex(ValidationRegExp);
return regexPattern.IsMatch(value.ToString());
+3 -3
View File
@@ -29,8 +29,8 @@ namespace Umbraco.Core.Models
base.Path = path;
ParentId = -1;
Key = name.EncodeAsGuid();
_name = name;
_alias = alias;
_name = name.Replace("/", ".").Replace("\\", "");
_alias = alias.ToSafeAlias();
CreateDate = DateTime.Now;
UpdateDate = DateTime.Now;
@@ -52,7 +52,7 @@ namespace Umbraco.Core.Models
internal string NodePath { get; set; }
[DataMember]
internal int MasterTemplateId { get; set; }
internal Lazy<int> MasterTemplateId { get; set; }
[DataMember]
internal string MasterTemplateAlias { get; set; }
@@ -8,25 +8,17 @@ namespace Umbraco.Core.Persistence.Factories
{
internal class PropertyFactory : IEntityFactory<IEnumerable<Property>, IEnumerable<PropertyDataDto>>
{
private readonly IContentType _contentType;
private readonly IMediaType _mediaType;
private readonly IContentTypeComposition _contentType;
private readonly Guid _version;
private readonly int _id;
public PropertyFactory(IContentType contentType, Guid version, int id)
public PropertyFactory(IContentTypeComposition contentType, Guid version, int id)
{
_contentType = contentType;
_version = version;
_id = id;
}
public PropertyFactory(IMediaType mediaType, Guid version, int id)
{
_mediaType = mediaType;
_version = version;
_id = id;
}
#region Implementation of IEntityFactory<IContent,PropertyDataDto>
public IEnumerable<Property> BuildEntity(IEnumerable<PropertyDataDto> dtos)
@@ -98,22 +90,5 @@ namespace Umbraco.Core.Persistence.Factories
}
#endregion
public IEnumerable<Property> BuildMediaEntity(IEnumerable<PropertyDataDto> dtos)
{
var properties = new List<Property>();
foreach (var dto in dtos)
{
if (_mediaType.CompositionPropertyTypes.Any(x => x.Id == dto.PropertyTypeId))
{
var propertyType = _mediaType.CompositionPropertyTypes.First(x => x.Id == dto.PropertyTypeId);
var property = propertyType.CreatePropertyFromRawValue(dto.GetValue, dto.VersionId.Value, dto.Id);
property.ResetDirtyProperties();
properties.Add(property);
}
}
return properties;
}
}
}
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
@@ -44,6 +45,7 @@ namespace Umbraco.Core.Persistence.Factories
var typeDtos = groupDto.PropertyTypeDtos.Where(x => x.Id > 0);
foreach (var typeDto in typeDtos)
{
var tempGroupDto = groupDto;
var propertyType = new PropertyType(typeDto.DataTypeDto.ControlId,
typeDto.DataTypeDto.DbType.EnumParse<DataTypeDatabaseType>(true))
{
@@ -56,7 +58,7 @@ namespace Umbraco.Core.Persistence.Factories
Mandatory = typeDto.Mandatory,
SortOrder = typeDto.SortOrder,
ValidationRegExp = typeDto.ValidationRegExp,
PropertyGroupId = groupDto.Id
PropertyGroupId = new Lazy<int>(() => tempGroupDto.Id)
};
propertyType.ResetDirtyProperties();
@@ -28,17 +28,22 @@ namespace Umbraco.Core.Persistence.Factories
public Template BuildEntity(TemplateDto dto)
{
return new Template(string.Empty, dto.NodeDto.Text, dto.Alias)
{
CreateDate = dto.NodeDto.CreateDate,
Id = dto.NodeId,
Key = dto.NodeDto.UniqueId.Value,
CreatorId = dto.NodeDto.UserId.Value,
Level = dto.NodeDto.Level,
ParentId = dto.NodeDto.ParentId,
SortOrder = dto.NodeDto.SortOrder,
NodePath = dto.NodeDto.Path
};
var template = new Template(string.Empty, dto.NodeDto.Text, dto.Alias)
{
CreateDate = dto.NodeDto.CreateDate,
Id = dto.NodeId,
Key = dto.NodeDto.UniqueId.Value,
CreatorId = dto.NodeDto.UserId.Value,
Level = dto.NodeDto.Level,
ParentId = dto.NodeDto.ParentId,
SortOrder = dto.NodeDto.SortOrder,
NodePath = dto.NodeDto.Path
};
if(dto.Master.HasValue)
template.MasterTemplateId = new Lazy<int>(() => dto.Master.Value);
return template;
}
public TemplateDto BuildDto(Template entity)
@@ -50,6 +55,11 @@ namespace Umbraco.Core.Persistence.Factories
NodeDto = BuildNodeDto(entity)
};
if (entity.MasterTemplateId != null && entity.MasterTemplateId.Value != default(int))
{
dto.Master = entity.MasterTemplateId.Value;
}
if (entity.HasIdentity)
{
dto.NodeId = entity.Id;
@@ -30,8 +30,8 @@ namespace Umbraco.Core.Persistence.Mappers
string columnName = columnAttribute.Name;
string columnMap = string.Format("{0}.{1}",
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(columnName));
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName));
return columnMap;
}
}
@@ -102,7 +102,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
}
//Check tables in configured database against tables in schema
var tablesInDatabase = SyntaxConfig.SqlSyntaxProvider.GetTablesInSchema(_database).ToList();
var tablesInDatabase = SqlSyntaxContext.SqlSyntaxProvider.GetTablesInSchema(_database).ToList();
var tablesInSchema = result.TableDefinitions.Select(x => x.Name).ToList();
//Add valid and invalid table differences to the result object
var validTableDifferences = tablesInDatabase.Intersect(tablesInSchema);
@@ -117,7 +117,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
}
//Check columns in configured database against columns in schema
var columnsInDatabase = SyntaxConfig.SqlSyntaxProvider.GetColumnsInSchema(_database);
var columnsInDatabase = SqlSyntaxContext.SqlSyntaxProvider.GetColumnsInSchema(_database);
var columnsPerTableInDatabase = columnsInDatabase.Select(x => string.Concat(x.TableName, ",", x.ColumnName)).ToList();
var columnsPerTableInSchema = result.TableDefinitions.SelectMany(x => x.Columns.Select(y => string.Concat(y.TableName, ",", y.Name))).ToList();
//Add valid and invalid column differences to the result object
@@ -134,11 +134,11 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
//MySql doesn't conform to the "normal" naming of constraints, so there is currently no point in doing these checks.
//NOTE: At a later point we do other checks for MySql, but ideally it should be necessary to do special checks for different providers.
if (SyntaxConfig.SqlSyntaxProvider is MySqlSyntaxProvider)
if (SqlSyntaxContext.SqlSyntaxProvider is MySqlSyntaxProvider)
return result;
//Check constraints in configured database against constraints in schema
var constraintsInDatabase = SyntaxConfig.SqlSyntaxProvider.GetConstraintsPerColumn(_database).DistinctBy(x => x.Item3).ToList();
var constraintsInDatabase = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(_database).DistinctBy(x => x.Item3).ToList();
var foreignKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.StartsWith("FK_")).Select(x => x.Item3).ToList();
var primaryKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.StartsWith("PK_")).Select(x => x.Item3).ToList();
var indexesInDatabase = constraintsInDatabase.Where(x => x.Item3.StartsWith("IX_")).Select(x => x.Item3).ToList();
@@ -111,7 +111,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
sb.AppendLine(" ");
}
if (SyntaxConfig.SqlSyntaxProvider is MySqlSyntaxProvider)
if (SqlSyntaxContext.SqlSyntaxProvider is MySqlSyntaxProvider)
{
sb.AppendLine("Please note that the constraints could not be validated because the current dataprovider is MySql.");
}
@@ -21,9 +21,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions
public override string ToString()
{
return string.Format(SyntaxConfig.SqlSyntaxProvider.AlterColumn,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(TableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(Column.Name));
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.AlterColumn,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(Column.Name));
}
}
}
@@ -22,9 +22,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions
{
//NOTE Should probably investigate if Deleting a Default Constraint is different from deleting a 'regular' constraint
return string.Format(SyntaxConfig.SqlSyntaxProvider.DeleteConstraint,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(TableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedName(ConstraintName));
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(ConstraintName));
}
}
}
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions
{
var constraintType = (Constraint.IsPrimaryKeyConstraint) ? "PRIMARY KEY" : "UNIQUE";
if (Constraint.IsPrimaryKeyConstraint && SyntaxConfig.SqlSyntaxProvider.SupportsClustered())
if (Constraint.IsPrimaryKeyConstraint && SqlSyntaxContext.SqlSyntaxProvider.SupportsClustered())
constraintType += " CLUSTERED";
if (Constraint.IsNonUniqueConstraint)
@@ -27,12 +27,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions
for (int i = 0; i < Constraint.Columns.Count; i++)
{
columns[i] = SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(Constraint.Columns.ElementAt(i));
columns[i] = SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(Constraint.Columns.ElementAt(i));
}
return string.Format(SyntaxConfig.SqlSyntaxProvider.CreateConstraint,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedName(Constraint.ConstraintName),
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.CreateConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(Constraint.ConstraintName),
constraintType,
string.Join(", ", columns));
}
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions
{
var table = new TableDefinition{Name = TableName, SchemaName = SchemaName, Columns = Columns};
return string.Format(SyntaxConfig.SqlSyntaxProvider.Format(table));
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.Format(table));
}
}
}
@@ -31,9 +31,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
foreach (string columnName in ColumnNames)
{
if (ColumnNames.First() != columnName) sb.AppendLine(";");
sb.AppendFormat(SyntaxConfig.SqlSyntaxProvider.DropColumn,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(TableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(columnName));
sb.AppendFormat(SqlSyntaxContext.SqlSyntaxProvider.DropColumn,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName));
}
return sb.ToString();
@@ -14,9 +14,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
public override string ToString()
{
return string.Format(SyntaxConfig.SqlSyntaxProvider.DeleteConstraint,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedName(Constraint.ConstraintName));
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(Constraint.ConstraintName));
}
}
}
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
if (IsAllRows)
{
deleteItems.Add(string.Format(SyntaxConfig.SqlSyntaxProvider.DeleteData, SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(TableName), "1 = 1"));
deleteItems.Add(string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteData, SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName), "1 = 1"));
}
else
{
@@ -42,13 +42,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
foreach (KeyValuePair<string, object> item in row)
{
whereClauses.Add(string.Format("{0} {1} {2}",
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
item.Value == null ? "IS" : "=",
SyntaxConfig.SqlSyntaxProvider.GetQuotedValue(item.Value.ToString())));
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(item.Value.ToString())));
}
deleteItems.Add(string.Format(SyntaxConfig.SqlSyntaxProvider.DeleteData,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(TableName),
deleteItems.Add(string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteData,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
String.Join(" AND ", whereClauses.ToArray())));
}
}
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
if (IsExpressionSupported() == false)
return string.Empty;
return string.Format(SyntaxConfig.SqlSyntaxProvider.DeleteDefaultConstraint,
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteDefaultConstraint,
TableName,
ColumnName);
}
@@ -33,10 +33,10 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
if (string.IsNullOrEmpty(ForeignKey.Name))
ForeignKey.Name = string.Format("{0}_ibfk_1", ForeignKey.ForeignTable.ToLower());
return string.Format(SyntaxConfig.SqlSyntaxProvider.DeleteConstraint,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(ForeignKey.ForeignTable),
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(ForeignKey.ForeignTable),
"FOREIGN KEY ",
SyntaxConfig.SqlSyntaxProvider.GetQuotedName(ForeignKey.Name));
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(ForeignKey.Name));
}
if (string.IsNullOrEmpty(ForeignKey.Name))
@@ -44,9 +44,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
ForeignKey.Name = string.Format("FK_{0}_{1}", ForeignKey.ForeignTable, ForeignKey.PrimaryTable);
}
return string.Format(SyntaxConfig.SqlSyntaxProvider.DeleteConstraint,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(ForeignKey.ForeignTable),
SyntaxConfig.SqlSyntaxProvider.GetQuotedName(ForeignKey.Name));
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(ForeignKey.ForeignTable),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(ForeignKey.Name));
}
}
}
@@ -19,9 +19,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
public override string ToString()
{
return string.Format(SyntaxConfig.SqlSyntaxProvider.DropIndex,
SyntaxConfig.SqlSyntaxProvider.GetQuotedName(Index.Name),
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(Index.TableName));
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DropIndex,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(Index.Name),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Index.TableName));
}
}
}
@@ -17,8 +17,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
public override string ToString()
{
return string.Format(SyntaxConfig.SqlSyntaxProvider.DropTable,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(TableName));
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DropTable,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName));
}
}
}
@@ -28,9 +28,9 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Expressions
if (string.IsNullOrEmpty(Column.TableName))
Column.TableName = TableName;
return string.Format(SyntaxConfig.SqlSyntaxProvider.AddColumn,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(Column.TableName),
SyntaxConfig.SqlSyntaxProvider.Format(Column));
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.AddColumn,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Column.TableName),
SqlSyntaxContext.SqlSyntaxProvider.Format(Column));
}
}
}
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Expressions
if (IsExpressionSupported() == false)
return string.Empty;
return SyntaxConfig.SqlSyntaxProvider.Format(ForeignKey);
return SqlSyntaxContext.SqlSyntaxProvider.Format(ForeignKey);
}
}
}
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Expressions
public override string ToString()
{
return SyntaxConfig.SqlSyntaxProvider.Format(Index);
return SqlSyntaxContext.SqlSyntaxProvider.Format(Index);
}
}
}
@@ -52,7 +52,7 @@ SELECT CONCAT(
if (IsExpressionSupported() == false)
return string.Empty;
return SyntaxConfig.SqlSyntaxProvider.FormatColumnRename(TableName, OldName, NewName);
return SqlSyntaxContext.SqlSyntaxProvider.FormatColumnRename(TableName, OldName, NewName);
}
}
}
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Rename.Expressions
if (IsExpressionSupported() == false)
return string.Empty;
return SyntaxConfig.SqlSyntaxProvider.FormatTableRename(OldName, NewName);
return SqlSyntaxContext.SqlSyntaxProvider.FormatTableRename(OldName, NewName);
}
}
}
@@ -31,8 +31,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Update.Expressions
foreach (var item in Set)
{
updateItems.Add(string.Format("{0} = {1}",
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
SyntaxConfig.SqlSyntaxProvider.GetQuotedValue(item.Value.ToString())));
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(item.Value.ToString())));
}
if (IsAllRows)
@@ -44,13 +44,13 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Update.Expressions
foreach (var item in Where)
{
whereClauses.Add(string.Format("{0} {1} {2}",
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(item.Key),
item.Value == null ? "IS" : "=",
SyntaxConfig.SqlSyntaxProvider.GetQuotedValue(item.Value.ToString())));
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(item.Value.ToString())));
}
}
return string.Format(SyntaxConfig.SqlSyntaxProvider.UpdateData,
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(TableName),
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.UpdateData,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName),
string.Join(", ", updateItems.ToArray()),
string.Join(" AND ", whereClauses.ToArray()));
}
@@ -33,10 +33,10 @@ namespace Umbraco.Core.Persistence
var tableDefinition = DefinitionFactory.GetTableDefinition(modelType);
var tableName = tableDefinition.Name;
string createSql = SyntaxConfig.SqlSyntaxProvider.Format(tableDefinition);
string createPrimaryKeySql = SyntaxConfig.SqlSyntaxProvider.FormatPrimaryKey(tableDefinition);
var foreignSql = SyntaxConfig.SqlSyntaxProvider.Format(tableDefinition.ForeignKeys);
var indexSql = SyntaxConfig.SqlSyntaxProvider.Format(tableDefinition.Indexes);
string createSql = SqlSyntaxContext.SqlSyntaxProvider.Format(tableDefinition);
string createPrimaryKeySql = SqlSyntaxContext.SqlSyntaxProvider.FormatPrimaryKey(tableDefinition);
var foreignSql = SqlSyntaxContext.SqlSyntaxProvider.Format(tableDefinition.ForeignKeys);
var indexSql = SqlSyntaxContext.SqlSyntaxProvider.Format(tableDefinition.Indexes);
var tableExist = db.TableExist(tableName);
if (overwrite && tableExist)
@@ -65,18 +65,18 @@ namespace Umbraco.Core.Persistence
var e = new TableCreationEventArgs();
//Turn on identity insert if db provider is not mysql
if (SyntaxConfig.SqlSyntaxProvider.SupportsIdentityInsert() && tableDefinition.Columns.Any(x => x.IsIdentity))
db.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName))));
if (SqlSyntaxContext.SqlSyntaxProvider.SupportsIdentityInsert() && tableDefinition.Columns.Any(x => x.IsIdentity))
db.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName))));
//Call the NewTable-event to trigger the insert of base/default data
NewTable(tableName, db, e);
//Turn off identity insert if db provider is not mysql
if (SyntaxConfig.SqlSyntaxProvider.SupportsIdentityInsert() && tableDefinition.Columns.Any(x => x.IsIdentity))
db.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName))));
if (SqlSyntaxContext.SqlSyntaxProvider.SupportsIdentityInsert() && tableDefinition.Columns.Any(x => x.IsIdentity))
db.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName))));
//Special case for MySql
if (SyntaxConfig.SqlSyntaxProvider is MySqlSyntaxProvider && tableName.Equals("umbracoUser"))
if (SqlSyntaxContext.SqlSyntaxProvider is MySqlSyntaxProvider && tableName.Equals("umbracoUser"))
{
db.Update<UserDto>("SET id = @IdAfter WHERE id = @IdBefore AND userLogin = @Login", new { IdAfter = 0, IdBefore = 1, Login = "admin" });
}
@@ -120,18 +120,28 @@ namespace Umbraco.Core.Persistence
public static void DropTable(this Database db, string tableName)
{
var sql = new Sql(string.Format("DROP TABLE {0}", SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName)));
var sql = new Sql(string.Format(
SqlSyntaxContext.SqlSyntaxProvider.DropTable,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)));
db.Execute(sql);
}
public static void TruncateTable(this Database db, string tableName)
{
var sql = new Sql(string.Format(
SqlSyntaxContext.SqlSyntaxProvider.TruncateTable,
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)));
db.Execute(sql);
}
public static bool TableExist(this Database db, string tableName)
{
return SyntaxConfig.SqlSyntaxProvider.DoesTableExist(db, tableName);
return SqlSyntaxContext.SqlSyntaxProvider.DoesTableExist(db, tableName);
}
public static bool TableExist(this UmbracoDatabase db, string tableName)
{
return SyntaxConfig.SqlSyntaxProvider.DoesTableExist(db, tableName);
return SqlSyntaxContext.SqlSyntaxProvider.DoesTableExist(db, tableName);
}
public static void CreateDatabaseSchema(this Database db)
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
return sql.From(SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName));
return sql.From(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName));
}
public static Sql Where<T>(this Sql sql, Expression<Func<T, bool>> predicate)
@@ -38,8 +38,8 @@ namespace Umbraco.Core.Persistence
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
var syntax = string.Format("{0}.{1}",
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(columnName));
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName));
return sql.OrderBy(syntax);
}
@@ -54,8 +54,8 @@ namespace Umbraco.Core.Persistence
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
var syntax = string.Format("{0}.{1} DESC",
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(columnName));
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName));
return sql.OrderBy(syntax);
}
@@ -65,7 +65,7 @@ namespace Umbraco.Core.Persistence
var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo;
var columnName = column.FirstAttribute<ColumnAttribute>().Name;
return sql.GroupBy(SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(columnName));
return sql.GroupBy(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName));
}
public static Sql.SqlJoinClause InnerJoin<T>(this Sql sql)
@@ -74,7 +74,7 @@ namespace Umbraco.Core.Persistence
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
return sql.InnerJoin(SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName));
return sql.InnerJoin(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName));
}
public static Sql.SqlJoinClause LeftJoin<T>(this Sql sql)
@@ -83,7 +83,7 @@ namespace Umbraco.Core.Persistence
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
return sql.LeftJoin(SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName));
return sql.LeftJoin(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName));
}
public static Sql.SqlJoinClause LeftOuterJoin<T>(this Sql sql)
@@ -92,7 +92,7 @@ namespace Umbraco.Core.Persistence
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
return sql.LeftOuterJoin(SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName));
return sql.LeftOuterJoin(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName));
}
public static Sql.SqlJoinClause RightJoin<T>(this Sql sql)
@@ -101,7 +101,7 @@ namespace Umbraco.Core.Persistence
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
string tableName = tableNameAttribute == null ? string.Empty : tableNameAttribute.Value;
return sql.RightJoin(SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(tableName));
return sql.RightJoin(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName));
}
public static Sql On<TLeft, TRight>(this Sql.SqlJoinClause sql, Expression<Func<TLeft, object>> leftMember,
@@ -118,10 +118,10 @@ namespace Umbraco.Core.Persistence
var rightColumnName = right.FirstAttribute<ColumnAttribute>().Name;
string onClause = string.Format("{0}.{1} = {2}.{3}",
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(leftTableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(leftColumnName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(rightTableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(rightColumnName));
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(leftTableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(leftColumnName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(rightTableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(rightColumnName));
return sql.On(onClause);
}
}
@@ -523,7 +523,8 @@ namespace Umbraco.Core.Persistence.Querying
protected bool IsFieldName(string quotedExp)
{
return true;
//Not entirely sure this is reliable, but its better then simply returning true
return quotedExp.LastIndexOf("'", StringComparison.InvariantCultureIgnoreCase) + 1 != quotedExp.Length;
}
}
}
@@ -468,6 +468,9 @@ namespace Umbraco.Core.Persistence.Querying
if(fieldType == typeof(DateTime))
return "'" + EscapeParam(((DateTime)value).ToString(CultureInfo.InvariantCulture)) + "'";
if (fieldType == typeof(bool))
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
return ShouldQuoteValue(fieldType)
? "'" + EscapeParam(value) + "'"
: value.ToString();
@@ -487,8 +490,8 @@ namespace Umbraco.Core.Persistence.Querying
{
var column = pocoData.Columns.FirstOrDefault(x => x.Value.PropertyInfo.Name == name);
return string.Format("{0}.{1}",
SyntaxConfig.SqlSyntaxProvider.GetQuotedTableName(pocoData.TableInfo.TableName),
SyntaxConfig.SqlSyntaxProvider.GetQuotedColumnName(column.Value.ColumnName));
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(pocoData.TableInfo.TableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(column.Value.ColumnName));
}
protected string RemoveQuote(string exp)
@@ -266,8 +266,11 @@ namespace Umbraco.Core.Persistence.Repositories
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
entity.Path = string.Concat(parent.Path, ",", entity.Id);
entity.Level = parent.Level + 1;
var maxSortOrder = Database.ExecuteScalar<int>("SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId", new { ParentId = entity.ParentId });
entity.SortOrder = maxSortOrder;
var maxSortOrder =
Database.ExecuteScalar<int>(
"SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType",
new {ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId});
entity.SortOrder = maxSortOrder + 1;
}
var factory = new ContentFactory(NodeObjectTypeId, entity.Id);
@@ -41,11 +41,11 @@ namespace Umbraco.Core.Persistence.Repositories
.RightJoin<PropertyTypeDto>()
.On<PropertyTypeGroupDto, PropertyTypeDto>(left => left.Id, right => right.PropertyTypeGroupId)
.InnerJoin<DataTypeDto>()
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
.OrderBy<PropertyTypeDto>(x => x.PropertyTypeGroupId);
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.DataTypeId);
var translator = new SqlTranslator<PropertyType>(sqlClause, query);
var sql = translator.Translate();
var sql = translator.Translate()
.OrderBy<PropertyTypeDto>(x => x.PropertyTypeGroupId);
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
@@ -108,7 +108,12 @@ namespace Umbraco.Core.Persistence.Repositories
//Insert collection of allowed content types
foreach (var allowedContentType in entity.AllowedContentTypes)
{
Database.Insert(new ContentTypeAllowedContentTypeDto { Id = entity.Id, AllowedId = allowedContentType.Id.Value, SortOrder = allowedContentType.SortOrder });
Database.Insert(new ContentTypeAllowedContentTypeDto
{
Id = entity.Id,
AllowedId = allowedContentType.Id.Value,
SortOrder = allowedContentType.SortOrder
});
}
var propertyFactory = new PropertyGroupFactory(nodeDto.NodeId);
@@ -119,22 +124,31 @@ namespace Umbraco.Core.Persistence.Repositories
var tabDto = propertyFactory.BuildGroupDto(propertyGroup);
var primaryKey = Convert.ToInt32(Database.Insert(tabDto));
propertyGroup.Id = primaryKey;//Set Id on PropertyGroup
//Ensure that the PropertyGroup's Id is set on the PropertyTypes within a group
//unless the PropertyGroupId has already been changed.
foreach (var propertyType in propertyGroup.PropertyTypes)
{
if (propertyType.IsPropertyDirty("PropertyGroupId") == false)
{
var tempGroup = propertyGroup;
propertyType.PropertyGroupId = new Lazy<int>(() => tempGroup.Id);
}
}
}
//Insert PropertyTypes
foreach (var propertyGroup in entity.PropertyGroups)
foreach (var propertyType in entity.PropertyTypes)
{
foreach (var propertyType in propertyGroup.PropertyTypes)
{
var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(propertyGroup.Id, propertyType);
var primaryKey = Convert.ToInt32(Database.Insert(propertyTypeDto));
propertyType.Id = primaryKey;//Set Id on PropertyType
var tabId = propertyType.PropertyGroupId != null ? propertyType.PropertyGroupId.Value : default(int);
var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(tabId, propertyType);
int typePrimaryKey = Convert.ToInt32(Database.Insert(propertyTypeDto));
propertyType.Id = typePrimaryKey; //Set Id on new PropertyType
//Update the current PropertyType with correct ControlId and DatabaseType
var dataTypeDto = Database.FirstOrDefault<DataTypeDto>("WHERE nodeId = @Id", new { Id = propertyTypeDto.DataTypeId });
propertyType.DataTypeId = dataTypeDto.ControlId;
propertyType.DataTypeDatabaseType = dataTypeDto.DbType.EnumParse<DataTypeDatabaseType>(true);
}
//Update the current PropertyType with correct ControlId and DatabaseType
var dataTypeDto = Database.FirstOrDefault<DataTypeDto>("WHERE nodeId = @Id", new { Id = propertyTypeDto.DataTypeId });
propertyType.DataTypeId = dataTypeDto.ControlId;
propertyType.DataTypeDatabaseType = dataTypeDto.DbType.EnumParse<DataTypeDatabaseType>(true);
}
}
@@ -267,15 +281,18 @@ namespace Umbraco.Core.Persistence.Repositories
foreach (var propertyType in propertyGroup.PropertyTypes)
{
if (propertyType.IsPropertyDirty("PropertyGroupId") == false)
propertyType.PropertyGroupId = propertyGroup.Id;
{
var tempGroup = propertyGroup;
propertyType.PropertyGroupId = new Lazy<int>(() => tempGroup.Id);
}
}
}
//Run through all PropertyTypes to insert or update entries
foreach (var propertyType in entity.PropertyTypes)
{
var propertyTypeDto = propertyGroupFactory.BuildPropertyTypeDto(propertyType.PropertyGroupId,
propertyType);
var tabId = propertyType.PropertyGroupId != null ? propertyType.PropertyGroupId.Value : default(int);
var propertyTypeDto = propertyGroupFactory.BuildPropertyTypeDto(tabId, propertyType);
int typePrimaryKey = propertyType.HasIdentity
? Database.Update(propertyTypeDto)
: Convert.ToInt32(Database.Insert(propertyTypeDto));
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
@@ -167,6 +168,19 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PersistNewItem(IContentType entity)
{
Mandate.That<Exception>(string.IsNullOrEmpty(entity.Alias) == false,
() =>
{
var message =
string.Format(
"ContentType '{0}' cannot have an empty Alias. This is most likely due to invalid characters stripped from the Alias.",
entity.Name);
var exception = new Exception(message);
LogHelper.Error<ContentTypeRepository>(message, exception);
throw exception;
});
((ContentType)entity).AddingEntity();
var factory = new ContentTypeFactory(NodeObjectTypeId);
@@ -192,6 +206,19 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PersistUpdatedItem(IContentType entity)
{
Mandate.That<Exception>(string.IsNullOrEmpty(entity.Alias) == false,
() =>
{
var message =
string.Format(
"ContentType '{0}' cannot have an empty Alias. This is most likely due to invalid characters stripped from the Alias.",
entity.Name);
var exception = new Exception(message);
LogHelper.Error<ContentTypeRepository>(message, exception);
throw exception;
});
//Updates Modified date
((ContentType)entity).UpdatingEntity();
@@ -200,6 +227,12 @@ namespace Umbraco.Core.Persistence.Repositories
{
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
entity.Path = string.Concat(parent.Path, ",", entity.Id);
entity.Level = parent.Level + 1;
var maxSortOrder =
Database.ExecuteScalar<int>(
"SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType",
new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId });
entity.SortOrder = maxSortOrder + 1;
}
var factory = new ContentTypeFactory(NodeObjectTypeId);
@@ -159,6 +159,12 @@ namespace Umbraco.Core.Persistence.Repositories
{
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
entity.Path = string.Concat(parent.Path, ",", entity.Id);
entity.Level = parent.Level + 1;
var maxSortOrder =
Database.ExecuteScalar<int>(
"SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType",
new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId });
entity.SortOrder = maxSortOrder + 1;
}
var factory = new DataTypeDefinitionFactory(NodeObjectTypeId);
@@ -246,8 +246,11 @@ namespace Umbraco.Core.Persistence.Repositories
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
entity.Path = string.Concat(parent.Path, ",", entity.Id);
entity.Level = parent.Level + 1;
var maxSortOrder = Database.ExecuteScalar<int>("SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId", new { ParentId = entity.ParentId });
entity.SortOrder = maxSortOrder;
var maxSortOrder =
Database.ExecuteScalar<int>(
"SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType",
new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId });
entity.SortOrder = maxSortOrder + 1;
}
var factory = new MediaFactory(NodeObjectTypeId, entity.Id);
@@ -347,7 +350,18 @@ namespace Umbraco.Core.Persistence.Repositories
var propertyDataDtos = Database.Fetch<PropertyDataDto, PropertyTypeDto>(sql);
var propertyFactory = new PropertyFactory(contentType, versionId, id);
var properties = propertyFactory.BuildMediaEntity(propertyDataDtos);
var properties = propertyFactory.BuildEntity(propertyDataDtos);
var newProperties = properties.Where(x => x.HasIdentity == false);
foreach (var property in newProperties)
{
var propertyDataDto = new PropertyDataDto { NodeId = id, PropertyTypeId = property.PropertyTypeId, VersionId = versionId };
int primaryKey = Convert.ToInt32(Database.Insert(propertyDataDto));
property.Version = versionId;
property.Id = primaryKey;
}
return new PropertyCollection(properties);
}
}
@@ -168,6 +168,12 @@ namespace Umbraco.Core.Persistence.Repositories
{
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = entity.ParentId });
entity.Path = string.Concat(parent.Path, ",", entity.Id);
entity.Level = parent.Level + 1;
var maxSortOrder =
Database.ExecuteScalar<int>(
"SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType",
new { ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId });
entity.SortOrder = maxSortOrder + 1;
}
var factory = new MediaTypeFactory(NodeObjectTypeId);
@@ -71,7 +71,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
var masterTemplate = Get(dto.Master.Value);
template.MasterTemplateAlias = masterTemplate.Alias;
template.MasterTemplateId = dto.Master.Value;
template.MasterTemplateId = new Lazy<int>(() => dto.Master.Value);
}
if (_viewsFileSystem.FileExists(csViewName))
@@ -172,14 +172,18 @@ namespace Umbraco.Core.Persistence.Repositories
{
if (entity.GetTypeOfRenderingEngine() == RenderingEngine.Mvc)
{
_viewsFileSystem.AddFile(entity.Name, stream, true);
string viewName = string.Concat(entity.Alias, ".cshtml");
_viewsFileSystem.AddFile(viewName, stream, true);
}
else
{
_masterpagesFileSystem.AddFile(entity.Name, stream, true);
string masterpageName = string.Concat(entity.Alias, ".master");
_masterpagesFileSystem.AddFile(masterpageName, stream, true);
}
}
//TODO Possibly ensure unique alias here (as is done in the legacy Template class)?
//Save to db
var template = entity as Template;
var factory = new TemplateFactory(NodeObjectTypeId);
@@ -223,11 +227,13 @@ namespace Umbraco.Core.Persistence.Repositories
{
if (entity.GetTypeOfRenderingEngine() == RenderingEngine.Mvc)
{
_viewsFileSystem.AddFile(entity.Name, stream, true);
string viewName = string.Concat(entity.Alias, ".cshtml");
_viewsFileSystem.AddFile(viewName, stream, true);
}
else
{
_masterpagesFileSystem.AddFile(entity.Name, stream, true);
string masterpageName = string.Concat(entity.Alias, ".master");
_masterpagesFileSystem.AddFile(masterpageName, stream, true);
}
}
@@ -236,6 +242,12 @@ namespace Umbraco.Core.Persistence.Repositories
{
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = ((Template)entity).ParentId });
entity.Path = string.Concat(parent.Path, ",", entity.Id);
((Template)entity).Level = parent.Level + 1;
var maxSortOrder =
Database.ExecuteScalar<int>(
"SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType",
new { ParentId = ((Template)entity).ParentId, NodeObjectType = NodeObjectTypeId });
((Template)entity).SortOrder = maxSortOrder + 1;
}
//Get TemplateDto from db to get the Primary key of the entity
@@ -328,8 +340,8 @@ namespace Umbraco.Core.Persistence.Repositories
public ITemplate Get(string alias)
{
var sql = GetBaseQuery(false);
sql.Where("cmsTemplate.alias = @Alias", new { Alias = alias });
var sql = GetBaseQuery(false)
.Where<TemplateDto>(x => x.Alias == alias);
var dto = Database.Fetch<TemplateDto, NodeDto>(sql).FirstOrDefault();
@@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
@@ -4,7 +4,7 @@ using System.Data;
namespace Umbraco.Core.Persistence.SqlSyntax
{
internal class DbTypes<TSyntax>
public class DbTypes<TSyntax>
where TSyntax : ISqlSyntaxProvider
{
public DbType DbType;
@@ -31,6 +31,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
string InsertData { get; }
string UpdateData { get; }
string DeleteData { get; }
string TruncateTable { get; }
string CreateConstraint { get; }
string DeleteConstraint { get; }
string CreateForeignKeyConstraint { get; }
@@ -7,21 +7,20 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Static class that provides simple access to the MySql SqlSyntax Providers singleton
/// Static class that provides simple access to the MySql SqlSyntax Provider
/// </summary>
internal static class MySqlSyntax
{
public static ISqlSyntaxProvider Provider { get { return MySqlSyntaxProvider.Instance; } }
public static ISqlSyntaxProvider Provider { get { return new MySqlSyntaxProvider(); } }
}
/// <summary>
/// Represents an SqlSyntaxProvider for MySql
/// </summary>
internal class MySqlSyntaxProvider : SqlSyntaxProviderBase<MySqlSyntaxProvider>
[SqlSyntaxProviderAttribute("MySql.Data.MySqlClient")]
public class MySqlSyntaxProvider : SqlSyntaxProviderBase<MySqlSyntaxProvider>
{
public static MySqlSyntaxProvider Instance = new MySqlSyntaxProvider();
private MySqlSyntaxProvider()
public MySqlSyntaxProvider()
{
DefaultStringLength = 255;
StringLengthColumnDefinitionFormat = StringLengthUnicodeColumnDefinitionFormat;
@@ -1,28 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Static class that provides simple access to the Sql CE SqlSyntax Providers singleton
/// Static class that provides simple access to the Sql CE SqlSyntax Provider
/// </summary>
internal static class SqlCeSyntax
{
public static ISqlSyntaxProvider Provider { get { return SqlCeSyntaxProvider.Instance; } }
public static ISqlSyntaxProvider Provider { get { return new SqlCeSyntaxProvider(); } }
}
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Ce
/// </summary>
internal class SqlCeSyntaxProvider : SqlSyntaxProviderBase<SqlCeSyntaxProvider>
[SqlSyntaxProviderAttribute("System.Data.SqlServerCe.4.0")]
public class SqlCeSyntaxProvider : SqlSyntaxProviderBase<SqlCeSyntaxProvider>
{
public static SqlCeSyntaxProvider Instance = new SqlCeSyntaxProvider();
private SqlCeSyntaxProvider()
public SqlCeSyntaxProvider()
{
StringLengthColumnDefinitionFormat = StringLengthUnicodeColumnDefinitionFormat;
StringColumnDefinition = string.Format(StringLengthColumnDefinitionFormat, DefaultStringLength);
@@ -44,6 +42,14 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return false;
}
/// <summary>
/// SqlCe doesn't support the Truncate Table syntax, so we just have to do a DELETE FROM which is slower but we have no choice.
/// </summary>
public override string TruncateTable
{
get { return "DELETE FROM {0}"; }
}
public override string GetIndexType(IndexTypes indexTypes)
{
string indexType;
@@ -6,21 +6,20 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Static class that provides simple access to the Sql Server SqlSyntax Providers singleton
/// Static class that provides simple access to the Sql Server SqlSyntax Provider
/// </summary>
internal static class SqlServerSyntax
{
public static ISqlSyntaxProvider Provider { get { return SqlServerSyntaxProvider.Instance; } }
public static ISqlSyntaxProvider Provider { get { return new SqlServerSyntaxProvider(); } }
}
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Server
/// </summary>
internal class SqlServerSyntaxProvider : SqlSyntaxProviderBase<SqlServerSyntaxProvider>
[SqlSyntaxProviderAttribute("System.Data.SqlClient")]
public class SqlServerSyntaxProvider : SqlSyntaxProviderBase<SqlServerSyntaxProvider>
{
public static SqlServerSyntaxProvider Instance = new SqlServerSyntaxProvider();
private SqlServerSyntaxProvider()
public SqlServerSyntaxProvider()
{
StringLengthColumnDefinitionFormat = StringLengthUnicodeColumnDefinitionFormat;
StringColumnDefinition = string.Format(StringLengthColumnDefinitionFormat, DefaultStringLength);
@@ -3,9 +3,9 @@
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Singleton to handle the configuration of an SqlSyntaxProvider
/// Singleton to handle the configuration of a SqlSyntaxProvider
/// </summary>
internal static class SyntaxConfig
public static class SqlSyntaxContext
{
private static ISqlSyntaxProvider _sqlSyntaxProvider;
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
if(_sqlSyntaxProvider == null)
{
throw new ArgumentNullException("SqlSyntaxProvider",
"You must set the singleton 'Umbraco.Core.Persistence.SqlSyntax.SyntaxConfig' to use an sql syntax provider");
"You must set the singleton 'Umbraco.Core.Persistence.SqlSyntax.SqlSyntaxContext' to use an sql syntax provider");
}
return _sqlSyntaxProvider;
}
@@ -0,0 +1,21 @@
using System;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Attribute for implementations of an ISqlSyntaxProvider
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class SqlSyntaxProviderAttribute : Attribute
{
public SqlSyntaxProviderAttribute(string providerName)
{
ProviderName = providerName;
}
/// <summary>
/// Gets or sets the ProviderName that corresponds to the sql syntax in a provider.
/// </summary>
public string ProviderName { get; set; }
}
}
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
/// All Sql Syntax provider implementations should derive from this abstract class.
/// </remarks>
/// <typeparam name="TSyntax"></typeparam>
internal abstract class SqlSyntaxProviderBase<TSyntax> : ISqlSyntaxProvider
public abstract class SqlSyntaxProviderBase<TSyntax> : ISqlSyntaxProvider
where TSyntax : ISqlSyntaxProvider
{
protected SqlSyntaxProviderBase()
@@ -436,6 +436,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public virtual string InsertData { get { return "INSERT INTO {0} ({1}) VALUES ({2})"; } }
public virtual string UpdateData { get { return "UPDATE {0} SET {1} WHERE {2}"; } }
public virtual string DeleteData { get { return "DELETE FROM {0} WHERE {1}"; } }
public virtual string TruncateTable { get { return "TRUNCATE TABLE {0}"; } }
public virtual string CreateConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} {2} ({3})"; } }
public virtual string DeleteConstraint { get { return "ALTER TABLE {0} DROP CONSTRAINT {1}"; } }
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// A resolver to return all ISqlSyntaxProvider objects
/// </summary>
internal sealed class SqlSyntaxProvidersResolver : ManyObjectsResolverBase<SqlSyntaxProvidersResolver, ISqlSyntaxProvider>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="syntaxProviders"></param>
internal SqlSyntaxProvidersResolver(IEnumerable<Type> syntaxProviders)
: base(syntaxProviders)
{
}
/// <summary>
/// Gets the <see cref="ISqlSyntaxProvider"/> implementations.
/// </summary>
public IEnumerable<ISqlSyntaxProvider> SqlSyntaxProviders
{
get
{
return Values;
}
}
/// <summary>
/// Gets a <see cref="ISqlSyntaxProvider"/> by its attributed provider.
/// </summary>
/// <param name="providerName">ProviderName from the ConnectionString settings</param>
/// <returns><see cref="ISqlSyntaxProvider"/> that corresponds to the attributed provider or the default Sql Server Syntax Provider.</returns>
public ISqlSyntaxProvider GetByProviderNameOrDefault(string providerName)
{
var provider =
Values.FirstOrDefault(
x =>
x.GetType()
.FirstAttribute<SqlSyntaxProviderAttribute>()
.ProviderName.ToLowerInvariant()
.Equals(providerName.ToLowerInvariant()));
if (provider != null)
return provider;
return Values.First(x => x.GetType() == typeof (SqlServerSyntaxProvider));
}
}
}
+10
View File
@@ -12,6 +12,7 @@ using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.PropertyEditors;
using umbraco.interfaces;
using File = System.IO.File;
@@ -477,6 +478,15 @@ namespace Umbraco.Core
return ResolveTypes<IMigration>();
}
/// <summary>
/// Returns all SqlSyntaxProviders with the SqlSyntaxProviderAttribute
/// </summary>
/// <returns></returns>
internal IEnumerable<Type> ResolveSqlSyntaxProviders()
{
return ResolveTypesWithAttribute<ISqlSyntaxProvider, SqlSyntaxProviderAttribute>();
}
/// <summary>
/// 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.
File diff suppressed because it is too large Load Diff
+71 -55
View File
@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Threading;
using Umbraco.Core.Auditing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
@@ -22,6 +25,9 @@ namespace Umbraco.Core.Services
private readonly IContentService _contentService;
private readonly IMediaService _mediaService;
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
//Support recursive locks because some of the methods that require locking call other methods that require locking.
//for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
public ContentTypeService(IContentService contentService, IMediaService mediaService)
: this(new PetaPocoUnitOfWorkProvider(), new RepositoryFactory(), contentService, mediaService)
@@ -173,19 +179,22 @@ namespace Umbraco.Core.Services
{
if (DeletingContentType.IsRaisedEventCancelled(new DeleteEventArgs<IContentType>(contentType), this))
return;
_contentService.DeleteContentOfType(contentType.Id);
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
{
repository.Delete(contentType);
uow.Commit();
using (new WriteLock(Locker))
{
_contentService.DeleteContentOfType(contentType.Id);
DeletedContentType.RaiseEvent(new DeleteEventArgs<IContentType>(contentType, false), this);
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
{
repository.Delete(contentType);
uow.Commit();
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentType performed by user"), userId, contentType.Id);
DeletedContentType.RaiseEvent(new DeleteEventArgs<IContentType>(contentType, false), this);
}
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentType performed by user"), userId, contentType.Id);
}
}
/// <summary>
@@ -200,27 +209,30 @@ namespace Umbraco.Core.Services
{
if (DeletingContentType.IsRaisedEventCancelled(new DeleteEventArgs<IContentType>(contentTypes), this))
return;
var contentTypeList = contentTypes.ToList();
foreach (var contentType in contentTypeList)
{
_contentService.DeleteContentOfType(contentType.Id);
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
{
foreach (var contentType in contentTypeList)
{
repository.Delete(contentType);
}
using (new WriteLock(Locker))
{
var contentTypeList = contentTypes.ToList();
foreach (var contentType in contentTypeList)
{
_contentService.DeleteContentOfType(contentType.Id);
}
uow.Commit();
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
{
foreach (var contentType in contentTypeList)
{
repository.Delete(contentType);
}
DeletedContentType.RaiseEvent(new DeleteEventArgs<IContentType>(contentTypes, false), this);
}
uow.Commit();
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1);
DeletedContentType.RaiseEvent(new DeleteEventArgs<IContentType>(contentTypes, false), this);
}
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1);
}
}
/// <summary>
@@ -357,20 +369,22 @@ namespace Umbraco.Core.Services
{
if (DeletingMediaType.IsRaisedEventCancelled(new DeleteEventArgs<IMediaType>(mediaType), this))
return;
_mediaService.DeleteMediaOfType(mediaType.Id, userId);
using (new WriteLock(Locker))
{
_mediaService.DeleteMediaOfType(mediaType.Id, userId);
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
repository.Delete(mediaType);
uow.Commit();
repository.Delete(mediaType);
uow.Commit();
DeletedMediaType.RaiseEvent(new DeleteEventArgs<IMediaType>(mediaType, false), this);
}
DeletedMediaType.RaiseEvent(new DeleteEventArgs<IMediaType>(mediaType, false), this);
}
Audit.Add(AuditTypes.Delete, string.Format("Delete MediaType performed by user"), userId, mediaType.Id);
Audit.Add(AuditTypes.Delete, string.Format("Delete MediaType performed by user"), userId, mediaType.Id);
}
}
/// <summary>
@@ -383,26 +397,28 @@ namespace Umbraco.Core.Services
{
if (DeletingMediaType.IsRaisedEventCancelled(new DeleteEventArgs<IMediaType>(mediaTypes), this))
return;
var mediaTypeList = mediaTypes.ToList();
foreach (var mediaType in mediaTypeList)
{
_mediaService.DeleteMediaOfType(mediaType.Id);
}
using (new WriteLock(Locker))
{
var mediaTypeList = mediaTypes.ToList();
foreach (var mediaType in mediaTypeList)
{
_mediaService.DeleteMediaOfType(mediaType.Id);
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
foreach (var mediaType in mediaTypeList)
{
repository.Delete(mediaType);
}
uow.Commit();
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
foreach (var mediaType in mediaTypeList)
{
repository.Delete(mediaType);
}
uow.Commit();
DeletedMediaType.RaiseEvent(new DeleteEventArgs<IMediaType>(mediaTypes, false), this);
}
DeletedMediaType.RaiseEvent(new DeleteEventArgs<IMediaType>(mediaTypes, false), this);
}
Audit.Add(AuditTypes.Delete, string.Format("Delete MediaTypes performed by user"), userId, -1);
Audit.Add(AuditTypes.Delete, string.Format("Delete MediaTypes performed by user"), userId, -1);
}
}
/// <summary>
@@ -459,7 +475,7 @@ namespace Umbraco.Core.Services
}
return dtd.ToString();
}
#region Event Handlers
/// <summary>
+99 -16
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Umbraco.Core.Auditing;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
@@ -19,6 +20,7 @@ namespace Umbraco.Core.Services
{
private readonly RepositoryFactory _repositoryFactory;
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
public DataTypeService()
: this(new RepositoryFactory())
@@ -105,11 +107,26 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of string values</returns>
public IEnumerable<string> GetPreValuesByDataTypeId(int id)
{
var uow = _uowProvider.GetUnitOfWork();
var dtos = uow.Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new {Id = id});
var list = dtos.Select(x => x.Value).ToList();
uow.Dispose();
return list;
using (var uow = _uowProvider.GetUnitOfWork())
{
var dtos = uow.Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new {Id = id});
var list = dtos.Select(x => x.Value).ToList();
return list;
}
}
/// <summary>
/// Gets a specific PreValue by its Id
/// </summary>
/// <param name="id">Id of the PreValue to retrieve the value from</param>
/// <returns>PreValue as a string</returns>
public string GetPreValueAsString(int id)
{
using (var uow = _uowProvider.GetUnitOfWork())
{
var dto = uow.Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @Id", new { Id = id });
return dto != null ? dto.Value : string.Empty;
}
}
/// <summary>
@@ -121,18 +138,84 @@ namespace Umbraco.Core.Services
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition), this))
return;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
{
dataTypeDefinition.CreatorId = userId;
repository.AddOrUpdate(dataTypeDefinition);
uow.Commit();
Saved.RaiseEvent(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition, false), this);
}
using (new WriteLock(Locker))
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
{
dataTypeDefinition.CreatorId = userId;
repository.AddOrUpdate(dataTypeDefinition);
uow.Commit();
Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
Saved.RaiseEvent(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition, false), this);
}
}
Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
}
/// <summary>
/// Saves a collection of <see cref="IDataTypeDefinition"/>
/// </summary>
/// <param name="dataTypeDefinitions"><see cref="IDataTypeDefinition"/> to save</param>
/// <param name="userId">Id of the user issueing the save</param>
public void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId = 0)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions), this))
return;
using (new WriteLock(Locker))
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
{
foreach (var dataTypeDefinition in dataTypeDefinitions)
{
dataTypeDefinition.CreatorId = userId;
repository.AddOrUpdate(dataTypeDefinition);
}
uow.Commit();
Saved.RaiseEvent(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions, false), this);
}
}
Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, -1);
}
/// <summary>
/// Saves a list of PreValues for a given DataTypeDefinition
/// </summary>
/// <param name="id">Id of the DataTypeDefinition to save PreValues for</param>
/// <param name="values">List of string values to save</param>
public void SavePreValues(int id, IEnumerable<string> values)
{
using (new WriteLock(Locker))
{
using (var uow = _uowProvider.GetUnitOfWork())
{
var sortOrderObj =
uow.Database.ExecuteScalar<object>(
"SELECT max(sortorder) FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = id });
int sortOrder;
if (sortOrderObj == null || int.TryParse(sortOrderObj.ToString(), out sortOrder) == false)
{
sortOrder = 1;
}
using (var transaction = uow.Database.GetTransaction())
{
foreach (var value in values)
{
var dto = new DataTypePreValueDto { DataTypeNodeId = id, Value = value, SortOrder = sortOrder };
uow.Database.Insert(dto);
sortOrder++;
}
transaction.Complete();
}
}
}
}
/// <summary>
@@ -163,7 +246,7 @@ namespace Umbraco.Core.Services
foreach (var group in contentType.PropertyGroups)
{
var types = @group.PropertyTypes.Where(x => x.DataTypeDefinitionId == dataTypeDefinition.Id);
var types = @group.PropertyTypes.Where(x => x.DataTypeDefinitionId == dataTypeDefinition.Id).ToList();
foreach (var propertyType in types)
{
@group.PropertyTypes.Remove(propertyType);
+25
View File
@@ -255,6 +255,31 @@ namespace Umbraco.Core.Services
Audit.Add(AuditTypes.Save, string.Format("Save Template performed by user"), userId, template.Id);
}
/// <summary>
/// Saves a collection of <see cref="Template"/> objects
/// </summary>
/// <param name="templates">List of <see cref="Template"/> to save</param>
/// <param name="userId">Optional id of the user</param>
public void SaveTemplate(IEnumerable<ITemplate> templates, int userId = 0)
{
if (SavingTemplate.IsRaisedEventCancelled(new SaveEventArgs<ITemplate>(templates), this))
return;
var uow = _dataUowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateTemplateRepository(uow))
{
foreach (var template in templates)
{
repository.AddOrUpdate(template);
}
uow.Commit();
SavedTemplate.RaiseEvent(new SaveEventArgs<ITemplate>(templates, false), this);
}
Audit.Add(AuditTypes.Save, string.Format("Save Template performed by user"), userId, -1);
}
/// <summary>
/// Deletes a template by its alias
/// </summary>
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Xml.Linq;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
@@ -38,6 +38,13 @@ namespace Umbraco.Core.Services
/// <param name="userId">Id of the user issueing the save</param>
void Save(IDataTypeDefinition dataTypeDefinition, int userId = 0);
/// <summary>
/// Saves a collection of <see cref="IDataTypeDefinition"/>
/// </summary>
/// <param name="dataTypeDefinitions"><see cref="IDataTypeDefinition"/> to save</param>
/// <param name="userId">Id of the user issueing the save</param>
void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId = 0);
/// <summary>
/// Deletes an <see cref="IDataTypeDefinition"/>
/// </summary>
@@ -75,5 +82,19 @@ namespace Umbraco.Core.Services
/// <param name="id">Id of the <see cref="IDataTypeDefinition"/> to retrieve prevalues from</param>
/// <returns>An enumerable list of string values</returns>
IEnumerable<string> GetPreValuesByDataTypeId(int id);
/// <summary>
/// Saves a list of PreValues for a given DataTypeDefinition
/// </summary>
/// <param name="id">Id of the DataTypeDefinition to save PreValues for</param>
/// <param name="values">List of string values to save</param>
void SavePreValues(int id, IEnumerable<string> values);
/// <summary>
/// Gets a specific PreValue by its Id
/// </summary>
/// <param name="id">Id of the PreValue to retrieve the value from</param>
/// <returns>PreValue as a string</returns>
string GetPreValueAsString(int id);
}
}
@@ -116,5 +116,12 @@ namespace Umbraco.Core.Services
/// <param name="template"><see cref="ITemplate"/> to validate</param>
/// <returns>True if Script is valid, otherwise false</returns>
bool ValidateTemplate(ITemplate template);
/// <summary>
/// Saves a collection of <see cref="Template"/> objects
/// </summary>
/// <param name="templates">List of <see cref="Template"/> to save</param>
/// <param name="userId">Optional id of the user</param>
void SaveTemplate(IEnumerable<ITemplate> templates, int userId = 0);
}
}
@@ -177,5 +177,12 @@ namespace Umbraco.Core.Services
/// <param name="deletePriorVersions">Boolean indicating whether to delete versions prior to the versionId</param>
/// <param name="userId">Optional Id of the User deleting versions of a Content object</param>
void DeleteVersion(int id, Guid versionId, bool deletePriorVersions, int userId = 0);
/// <summary>
/// Gets an <see cref="IMedia"/> object from the path stored in the 'umbracoFile' property.
/// </summary>
/// <param name="mediaPath">Path of the media item to retreive (for example: /media/1024/koala_403x328.jpg)</param>
/// <returns><see cref="IMedia"/></returns>
IMedia GetMediaByPath(string mediaPath);
}
}
+124 -63
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Xml.Linq;
using Umbraco.Core.Auditing;
using Umbraco.Core.Events;
@@ -19,6 +20,9 @@ namespace Umbraco.Core.Services
{
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly RepositoryFactory _repositoryFactory;
//Support recursive locks because some of the methods that require locking call other methods that require locking.
//for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
public MediaService(RepositoryFactory repositoryFactory)
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
@@ -42,7 +46,8 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMedia"/></returns>
public IMedia CreateMedia(string name, int parentId, string mediaTypeAlias, int userId = 0)
{
IMediaType mediaType = null;
IMediaType mediaType;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
@@ -62,8 +67,11 @@ namespace Umbraco.Core.Services
var media = new Models.Media(name, parentId, mediaType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId), this))
return media;
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId), this))
{
media.WasCancelled = true;
return media;
}
media.CreatorId = userId;
@@ -85,7 +93,8 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMedia"/></returns>
public IMedia CreateMedia(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
{
IMediaType mediaType = null;
IMediaType mediaType;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
@@ -104,9 +113,11 @@ namespace Umbraco.Core.Services
}
var media = new Models.Media(name, parent, mediaType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parent), this))
{
media.WasCancelled = true;
return media;
}
media.CreatorId = userId;
@@ -155,7 +166,7 @@ namespace Umbraco.Core.Services
{
using (var repository = _repositoryFactory.CreateMediaRepository(_uowProvider.GetUnitOfWork()))
{
var query = Query<IMedia>.Builder.Where(x => x.Level == level);
var query = Query<IMedia>.Builder.Where(x => x.Level == level && !x.Path.StartsWith("-21"));
var contents = repository.GetByQuery(query);
return contents;
@@ -283,6 +294,40 @@ namespace Umbraco.Core.Services
}
}
/// <summary>
/// Gets an <see cref="IMedia"/> object from the path stored in the 'umbracoFile' property.
/// </summary>
/// <param name="mediaPath">Path of the media item to retreive (for example: /media/1024/koala_403x328.jpg)</param>
/// <returns><see cref="IMedia"/></returns>
public IMedia GetMediaByPath(string mediaPath)
{
var umbracoFileValue = mediaPath;
var isResized = mediaPath.Contains("_") && mediaPath.Contains("x");
// If the image has been resized we strip the "_403x328" of the original "/media/1024/koala_403x328.jpg" url.
if (isResized)
{
var underscoreIndex = mediaPath.LastIndexOf('_');
var dotIndex = mediaPath.LastIndexOf('.');
umbracoFileValue = string.Concat(mediaPath.Substring(0, underscoreIndex), mediaPath.Substring(dotIndex));
}
var sql = new Sql()
.Select("*")
.From<PropertyDataDto>()
.InnerJoin<PropertyTypeDto>()
.On<PropertyDataDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.Where<PropertyTypeDto>(x => x.Alias == "umbracoFile")
.Where<PropertyDataDto>(x => x.VarChar == umbracoFileValue);
using (var uow = _uowProvider.GetUnitOfWork())
{
var propertyDataDto = uow.Database.Fetch<PropertyDataDto, PropertyTypeDto>(sql).FirstOrDefault();
return propertyDataDto == null ? null : GetById(propertyDataDto.NodeId);
}
}
/// <summary>
/// Checks whether an <see cref="IMedia"/> item has any children
/// </summary>
@@ -306,32 +351,35 @@ namespace Umbraco.Core.Services
/// <param name="userId">Id of the User moving the Media</param>
public void Move(IMedia media, int parentId, int userId = 0)
{
//This ensures that the correct method is called if this method is used to Move to recycle bin.
if (parentId == -21)
{
MoveToRecycleBin(media, userId);
return;
}
using (new WriteLock(Locker))
{
//This ensures that the correct method is called if this method is used to Move to recycle bin.
if (parentId == -21)
{
MoveToRecycleBin(media, userId);
return;
}
if (Moving.IsRaisedEventCancelled(new MoveEventArgs<IMedia>(media, parentId), this))
return;
if (Moving.IsRaisedEventCancelled(new MoveEventArgs<IMedia>(media, parentId), this))
return;
media.ParentId = parentId;
Save(media, userId);
media.ParentId = parentId;
Save(media, userId);
//Ensure that Path and Level is updated on children
var children = GetChildren(media.Id);
if (children.Any())
{
var parentPath = media.Path;
var parentLevel = media.Level;
var updatedDescendents = UpdatePathAndLevelOnChildren(children, parentPath, parentLevel);
Save(updatedDescendents, userId);
}
//Ensure that Path and Level is updated on children
var children = GetChildren(media.Id);
if (children.Any())
{
var parentPath = media.Path;
var parentLevel = media.Level;
var updatedDescendents = UpdatePathAndLevelOnChildren(children, parentPath, parentLevel);
Save(updatedDescendents, userId);
}
Moved.RaiseEvent(new MoveEventArgs<IMedia>(media, false, parentId), this);
Moved.RaiseEvent(new MoveEventArgs<IMedia>(media, false, parentId), this);
Audit.Add(AuditTypes.Move, "Move Media performed by user", userId, media.Id);
Audit.Add(AuditTypes.Move, "Move Media performed by user", userId, media.Id);
}
}
/// <summary>
@@ -403,32 +451,42 @@ namespace Umbraco.Core.Services
/// <param name="mediaTypeId">Id of the <see cref="IMediaType"/></param>
/// <param name="userId">Optional id of the user deleting the media</param>
public void DeleteMediaOfType(int mediaTypeId, int userId = 0)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
{
using (new WriteLock(Locker))
{
//NOTE What about media that has the contenttype as part of its composition?
//The ContentType has to be removed from the composition somehow as it would otherwise break
//Dbl.check+test that the ContentType's Id is removed from the ContentType2ContentType table
var query = Query<IMedia>.Builder.Where(x => x.ContentTypeId == mediaTypeId);
var contents = repository.GetByQuery(query);
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
{
//NOTE What about media that has the contenttype as part of its composition?
//The ContentType has to be removed from the composition somehow as it would otherwise break
//Dbl.check+test that the ContentType's Id is removed from the ContentType2ContentType table
var query = Query<IMedia>.Builder.Where(x => x.ContentTypeId == mediaTypeId);
var contents = repository.GetByQuery(query);
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMedia>(contents), this))
return;
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMedia>(contents), this))
return;
foreach (var content in contents)
{
((Core.Models.Media)content).ChangeTrashedState(true);
repository.AddOrUpdate(content);
}
foreach (var content in contents.OrderByDescending(x => x.ParentId))
{
//Look for children of current content and move that to trash before the current content is deleted
var c = content;
var childQuery = Query<IMedia>.Builder.Where(x => x.Path.StartsWith(c.Path));
var children = repository.GetByQuery(childQuery);
uow.Commit();
foreach (var child in children)
{
if (child.ContentType.Id != mediaTypeId)
MoveToRecycleBin(child, userId);
}
Deleted.RaiseEvent(new DeleteEventArgs<IMedia>(contents, false), this);
}
//Permantly delete the content
Delete(content, userId);
}
}
Audit.Add(AuditTypes.Delete, "Delete Media items by Type performed by user", userId, -1);
}
Audit.Add(AuditTypes.Delete, "Delete Media items by Type performed by user", userId, -1);
}
}
/// <summary>
/// Permanently deletes an <see cref="IMedia"/> object
@@ -523,25 +581,28 @@ namespace Umbraco.Core.Services
return;
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
{
media.CreatorId = userId;
repository.AddOrUpdate(media);
uow.Commit();
using (new WriteLock(Locker))
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
{
media.CreatorId = userId;
repository.AddOrUpdate(media);
uow.Commit();
var xml = media.ToXml();
var poco = new ContentXmlDto { NodeId = media.Id, Xml = xml.ToString(SaveOptions.None) };
var exists = uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = media.Id }) != null;
int result = exists
? uow.Database.Update(poco)
: Convert.ToInt32(uow.Database.Insert(poco));
}
var xml = media.ToXml();
var poco = new ContentXmlDto {NodeId = media.Id, Xml = xml.ToString(SaveOptions.None)};
var exists = uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new {Id = media.Id}) != null;
int result = exists
? uow.Database.Update(poco)
: Convert.ToInt32(uow.Database.Insert(poco));
}
if(raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
if (raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
Audit.Add(AuditTypes.Save, "Save Media performed by user", media.CreatorId, media.Id);
Audit.Add(AuditTypes.Save, "Save Media performed by user", media.CreatorId, media.Id);
}
}
/// <summary>
@@ -0,0 +1,642 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Xml.Linq;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
{
/// <summary>
/// Represents the Packaging Service, which provides import/export functionality for the Core models of the API
/// using xml representation. This is primarily used by the Package functionality.
/// </summary>
public class PackagingService : IService
{
private readonly IContentService _contentService;
private readonly IContentTypeService _contentTypeService;
private readonly IMediaService _mediaService;
private readonly IDataTypeService _dataTypeService;
private readonly IFileService _fileService;
private readonly RepositoryFactory _repositoryFactory;
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private Dictionary<string, IContentType> _importedContentTypes;
//Support recursive locks because some of the methods that require locking call other methods that require locking.
//for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
public PackagingService(IContentService contentService, IContentTypeService contentTypeService, IMediaService mediaService, IDataTypeService dataTypeService, IFileService fileService, RepositoryFactory repositoryFactory, IDatabaseUnitOfWorkProvider uowProvider)
{
_contentService = contentService;
_contentTypeService = contentTypeService;
_mediaService = mediaService;
_dataTypeService = dataTypeService;
_fileService = fileService;
_repositoryFactory = repositoryFactory;
_uowProvider = uowProvider;
_importedContentTypes = new Dictionary<string, IContentType>();
}
#region Content
/// <summary>
/// Imports and saves package xml as <see cref="IContent"/>
/// </summary>
/// <param name="element">Xml to import</param>
/// <param name="parentId">Optional parent Id for the content being imported</param>
/// <param name="userId">Optional Id of the user performing the import</param>
/// <returns>An enumrable list of generated content</returns>
public IEnumerable<IContent> ImportContent(XElement element, int parentId = -1, int userId = 0)
{
var name = element.Name.LocalName;
if (name.Equals("DocumentSet"))
{
//This is a regular deep-structured import
var roots = from doc in element.Elements()
where (string)doc.Attribute("isDoc") == ""
select doc;
var contents = ParseDocumentRootXml(roots, parentId);
if(contents.Any())
_contentService.Save(contents, userId);
return contents;
}
var attribute = element.Attribute("isDoc");
if (attribute != null)
{
//This is a single doc import
var elements = new List<XElement> { element };
var contents = ParseDocumentRootXml(elements, parentId);
if (contents.Any())
_contentService.Save(contents, userId);
return contents;
}
throw new ArgumentException(
"The passed in XElement is not valid! It does not contain a root element called " +
"'DocumentSet' (for structured imports) nor is the first element a Document (for single document import).");
}
private IEnumerable<IContent> ParseDocumentRootXml(IEnumerable<XElement> roots, int parentId)
{
var contents = new List<IContent>();
foreach (var root in roots)
{
bool isLegacySchema = root.Name.LocalName.ToLowerInvariant().Equals("node");
string contentTypeAlias = isLegacySchema
? root.Attribute("nodeTypeAlias").Value
: root.Name.LocalName;
if (_importedContentTypes.ContainsKey(contentTypeAlias) == false)
{
var contentType = FindContentTypeByAlias(contentTypeAlias);
_importedContentTypes.Add(contentTypeAlias, contentType);
}
var content = CreateContentFromXml(root, _importedContentTypes[contentTypeAlias], null, parentId, isLegacySchema);
contents.Add(content);
var children = from child in root.Elements()
where (string)child.Attribute("isDoc") == ""
select child;
if (children.Any())
contents.AddRange(CreateContentFromXml(children, content, isLegacySchema));
}
return contents;
}
private IEnumerable<IContent> CreateContentFromXml(IEnumerable<XElement> children, IContent parent, bool isLegacySchema)
{
var list = new List<IContent>();
foreach (var child in children)
{
string contentTypeAlias = isLegacySchema
? child.Attribute("nodeTypeAlias").Value
: child.Name.LocalName;
if (_importedContentTypes.ContainsKey(contentTypeAlias) == false)
{
var contentType = FindContentTypeByAlias(contentTypeAlias);
_importedContentTypes.Add(contentTypeAlias, contentType);
}
//Create and add the child to the list
var content = CreateContentFromXml(child, _importedContentTypes[contentTypeAlias], parent, default(int), isLegacySchema);
list.Add(content);
//Recursive call
XElement child1 = child;
var grandChildren = from grand in child1.Elements()
where (string)grand.Attribute("isDoc") == ""
select grand;
if (grandChildren.Any())
list.AddRange(CreateContentFromXml(grandChildren, content, isLegacySchema));
}
return list;
}
private IContent CreateContentFromXml(XElement element, IContentType contentType, IContent parent, int parentId, bool isLegacySchema)
{
var id = element.Attribute("id").Value;
var level = element.Attribute("level").Value;
var sortOrder = element.Attribute("sortOrder").Value;
var nodeName = element.Attribute("nodeName").Value;
var path = element.Attribute("path").Value;
var template = element.Attribute("template").Value;
var properties = from property in element.Elements()
where property.Attribute("isDoc") == null
select property;
IContent content = parent == null
? new Content(nodeName, parentId, contentType)
{
Level = int.Parse(level),
SortOrder = int.Parse(sortOrder)
}
: new Content(nodeName, parent, contentType)
{
Level = int.Parse(level),
SortOrder = int.Parse(sortOrder)
};
foreach (var property in properties)
{
string propertyTypeAlias = isLegacySchema ? property.Attribute("alias").Value : property.Name.LocalName;
if (content.HasProperty(propertyTypeAlias))
content.SetValue(propertyTypeAlias, property.Value);
}
return content;
}
internal XElement Export(IContent content, bool deep = false)
{
throw new NotImplementedException();
}
#endregion
#region ContentTypes
/// <summary>
/// Imports and saves package xml as <see cref="IContentType"/>
/// </summary>
/// <param name="element">Xml to import</param>
/// <param name="userId"></param>
/// <returns>An enumrable list of generated ContentTypes</returns>
public IEnumerable<IContentType> ImportContentTypes(XElement element, int userId = 0)
{
var name = element.Name.LocalName;
if (name.Equals("DocumentTypes") == false && name.Equals("DocumentType") == false)
{
throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'DocumentTypes' for multiple imports or 'DocumentType' for a single import.");
}
_importedContentTypes = new Dictionary<string, IContentType>();
var documentTypes = name.Equals("DocumentTypes")
? (from doc in element.Elements("DocumentType") select doc).ToList()
: new List<XElement> {element.Element("DocumentType")};
//NOTE it might be an idea to sort the doctype XElements based on dependencies
//before creating the doc types - should also allow for a better structure/inheritance support.
foreach (var documentType in documentTypes)
{
var alias = documentType.Element("Info").Element("Alias").Value;
if (_importedContentTypes.ContainsKey(alias) == false)
{
var contentType = _contentTypeService.GetContentType(alias);
_importedContentTypes.Add(alias, contentType == null
? CreateContentTypeFromXml(documentType)
: UpdateContentTypeFromXml(documentType, contentType));
}
}
var list = _importedContentTypes.Select(x => x.Value).ToList();
_contentTypeService.Save(list, userId);
var updatedContentTypes = new List<IContentType>();
//Update the structure here - we can't do it untill all DocTypes have been created
foreach (var documentType in documentTypes)
{
var alias = documentType.Element("Info").Element("Alias").Value;
var structureElement = documentType.Element("Structure");
//Ensure that we only update ContentTypes which has actual structure-elements
if (structureElement == null || structureElement.Elements("DocumentType").Any() == false) continue;
var updated = UpdateContentTypesStructure(_importedContentTypes[alias], structureElement);
updatedContentTypes.Add(updated);
}
//Update ContentTypes with a newly added structure/list of allowed children
if(updatedContentTypes.Any())
_contentTypeService.Save(updatedContentTypes, userId);
return list;
}
private IContentType CreateContentTypeFromXml(XElement documentType)
{
var infoElement = documentType.Element("Info");
//Name of the master corresponds to the parent
var masterElement = infoElement.Element("Master");
IContentType parent = null;
if (masterElement != null)
{
var masterAlias = masterElement.Value;
parent = _importedContentTypes.ContainsKey(masterAlias)
? _importedContentTypes[masterAlias]
: _contentTypeService.GetContentType(masterAlias);
}
var contentType = parent == null
? new ContentType(-1)
{
Alias = infoElement.Element("Alias").Value
}
: new ContentType(parent)
{
Alias = infoElement.Element("Alias").Value
};
if (parent != null)
contentType.AddContentType(parent);
return UpdateContentTypeFromXml(documentType, contentType);
}
private IContentType UpdateContentTypeFromXml(XElement documentType, IContentType contentType)
{
var infoElement = documentType.Element("Info");
var defaultTemplateElement = infoElement.Element("DefaultTemplate");
contentType.Name = infoElement.Element("Name").Value;
contentType.Icon = infoElement.Element("Icon").Value;
contentType.Thumbnail = infoElement.Element("Thumbnail").Value;
contentType.Description = infoElement.Element("Description").Value;
//NOTE AllowAtRoot is a new property in the package xml so we need to verify it exists before using it.
if (infoElement.Element("AllowAtRoot") != null)
contentType.AllowedAsRoot = infoElement.Element("AllowAtRoot").Value.ToLowerInvariant().Equals("true");
UpdateContentTypesAllowedTemplates(contentType, infoElement.Element("AllowedTemplates"), defaultTemplateElement);
UpdateContentTypesTabs(contentType, documentType.Element("Tabs"));
UpdateContentTypesProperties(contentType, documentType.Element("GenericProperties"));
return contentType;
}
private void UpdateContentTypesAllowedTemplates(IContentType contentType,
XElement allowedTemplatesElement, XElement defaultTemplateElement)
{
if (allowedTemplatesElement != null && allowedTemplatesElement.Elements("Template").Any())
{
var allowedTemplates = contentType.AllowedTemplates.ToList();
foreach (var templateElement in allowedTemplatesElement.Elements("Template"))
{
var alias = templateElement.Value;
var template = _fileService.GetTemplate(alias);
if (template != null)
{
allowedTemplates.Add(template);
}
else
{
LogHelper.Warn<PackagingService>(
string.Format(
"Packager: Error handling allowed templates. Template with alias '{0}' could not be found.",
alias));
}
}
contentType.AllowedTemplates = allowedTemplates;
}
if (string.IsNullOrEmpty(defaultTemplateElement.Value) == false)
{
var defaultTemplate = _fileService.GetTemplate(defaultTemplateElement.Value);
if (defaultTemplate != null)
{
contentType.SetDefaultTemplate(defaultTemplate);
}
else
{
LogHelper.Warn<PackagingService>(
string.Format(
"Packager: Error handling default template. Default template with alias '{0}' could not be found.",
defaultTemplateElement.Value));
}
}
}
private void UpdateContentTypesTabs(IContentType contentType, XElement tabElement)
{
if(tabElement == null)
return;
var tabs = tabElement.Elements("Tab");
foreach (var tab in tabs)
{
var id = tab.Element("Id").Value;//Do we need to use this for tracking?
var caption = tab.Element("Caption").Value;
if (contentType.PropertyGroups.Contains(caption) == false)
{
contentType.AddPropertyGroup(caption);
}
}
}
private void UpdateContentTypesProperties(IContentType contentType, XElement genericPropertiesElement)
{
var properties = genericPropertiesElement.Elements("GenericProperty");
foreach (var property in properties)
{
var dataTypeId = new Guid(property.Element("Type").Value);//The DataType's Control Id
var dataTypeDefinitionId = new Guid(property.Element("Definition").Value);//Unique Id for a DataTypeDefinition
var dataTypeDefinition = _dataTypeService.GetDataTypeDefinitionById(dataTypeDefinitionId);
//If no DataTypeDefinition with the guid from the xml wasn't found OR the ControlId on the DataTypeDefinition didn't match the DataType Id
//We look up a DataTypeDefinition that matches
if (dataTypeDefinition == null || dataTypeDefinition.ControlId != dataTypeId)
{
var dataTypeDefinitions = _dataTypeService.GetDataTypeDefinitionByControlId(dataTypeId);
if (dataTypeDefinitions != null && dataTypeDefinitions.Any())
{
dataTypeDefinition = dataTypeDefinitions.First();
}
}
// For backwards compatibility, if no datatype with that ID can be found, we're letting this fail silently.
// This means that the property will not be created.
if(dataTypeDefinition == null)
{
LogHelper.Warn<PackagingService>(string.Format("Packager: Error handling creation of PropertyType '{0}'. Could not find DataTypeDefintion with unique id '{1}' nor one referencing the DataType with control id '{2}'. Did the package creator forget to package up custom datatypes?",
property.Element("Name").Value, dataTypeDefinitionId, dataTypeId));
continue;
}
var propertyType = new PropertyType(dataTypeDefinition)
{
Alias = property.Element("Alias").Value,
Name = property.Element("Name").Value,
Description = property.Element("Description").Value,
Mandatory = property.Element("Mandatory").Value.ToLowerInvariant().Equals("true"),
ValidationRegExp = property.Element("Validation").Value
};
var helpTextElement = property.Element("HelpText");
if (helpTextElement != null)
{
propertyType.HelpText = helpTextElement.Value;
}
var tab = property.Element("Tab").Value;
if (string.IsNullOrEmpty(tab))
{
contentType.AddPropertyType(propertyType);
}
else
{
contentType.AddPropertyType(propertyType, tab);
}
}
}
private IContentType UpdateContentTypesStructure(IContentType contentType, XElement structureElement)
{
var allowedChildren = contentType.AllowedContentTypes.ToList();
int sortOrder = allowedChildren.Any() ? allowedChildren.Last().SortOrder : 0;
foreach (var element in structureElement.Elements("DocumentType"))
{
var alias = element.Value;
if (_importedContentTypes.ContainsKey(alias))
{
var allowedChild = _importedContentTypes[alias];
allowedChildren.Add(new ContentTypeSort(new Lazy<int>(() => allowedChild.Id), sortOrder, allowedChild.Alias));
sortOrder++;
}
else
{
LogHelper.Warn<PackagingService>(
string.Format(
"Packager: Error handling DocumentType structure. DocumentType with alias '{0}' could not be found and was not added to the structure for '{1}'.",
alias, contentType.Alias));
}
}
contentType.AllowedContentTypes = allowedChildren;
return contentType;
}
private IContentType FindContentTypeByAlias(string contentTypeAlias)
{
using (var repository = _repositoryFactory.CreateContentTypeRepository(_uowProvider.GetUnitOfWork()))
{
var query = Query<IContentType>.Builder.Where(x => x.Alias == contentTypeAlias);
var types = repository.GetByQuery(query);
if (!types.Any())
throw new Exception(
string.Format("No ContentType matching the passed in Alias: '{0}' was found",
contentTypeAlias));
var contentType = types.First();
if (contentType == null)
throw new Exception(string.Format("ContentType matching the passed in Alias: '{0}' was null",
contentTypeAlias));
return contentType;
}
}
#endregion
#region DataTypes
/// <summary>
/// Imports and saves package xml as <see cref="IDataTypeDefinition"/>
/// </summary>
/// <param name="element">Xml to import</param>
/// <param name="userId"></param>
/// <returns>An enumrable list of generated DataTypeDefinitions</returns>
public IEnumerable<IDataTypeDefinition> ImportDataTypeDefinitions(XElement element, int userId = 0)
{
var name = element.Name.LocalName;
if (name.Equals("DataTypes") == false && name.Equals("DataType") == false)
{
throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'DataTypes' for multiple imports or 'DataType' for a single import.");
}
var dataTypes = new Dictionary<string, IDataTypeDefinition>();
var dataTypeElements = name.Equals("DataTypes")
? (from doc in element.Elements("DataType") select doc).ToList()
: new List<XElement> {element.Element("DataType")};
foreach (var dataTypeElement in dataTypeElements)
{
var dataTypeDefinitionName = dataTypeElement.Attribute("Name").Value;
var dataTypeId = new Guid(dataTypeElement.Attribute("Id").Value);
var dataTypeDefinitionId = new Guid(dataTypeElement.Attribute("Definition").Value);
var databaseTypeAttribute = dataTypeElement.Attribute("DatabaseType");
var definition = _dataTypeService.GetDataTypeDefinitionById(dataTypeDefinitionId);
//If the datatypedefinition doesn't already exist we create a new new according to the one in the package xml
if (definition == null)
{
var databaseType = databaseTypeAttribute != null
? databaseTypeAttribute.Value.EnumParse<DataTypeDatabaseType>(true)
: DataTypeDatabaseType.Ntext;
var dataTypeDefinition = new DataTypeDefinition(-1, dataTypeId)
{
Key = dataTypeDefinitionId,
Name = dataTypeDefinitionName,
DatabaseType = databaseType
};
dataTypes.Add(dataTypeDefinitionName, dataTypeDefinition);
}
}
var list = dataTypes.Select(x => x.Value).ToList();
if (list.Any())
{
_dataTypeService.Save(list, userId);
SavePrevaluesFromXml(list, dataTypeElements);
}
return list;
}
private void SavePrevaluesFromXml(List<IDataTypeDefinition> dataTypes, IEnumerable<XElement> dataTypeElements)
{
foreach (var dataTypeElement in dataTypeElements)
{
var prevaluesElement = dataTypeElement.Element("PreValues");
if (prevaluesElement == null) continue;
var dataTypeDefinitionName = dataTypeElement.Attribute("Name").Value;
var dataTypeDefinition = dataTypes.First(x => x.Name == dataTypeDefinitionName);
var values = prevaluesElement.Elements("PreValue").Select(prevalue => prevalue.Attribute("Value").Value).ToList();
_dataTypeService.SavePreValues(dataTypeDefinition.Id, values);
}
}
#endregion
#region Dictionary Items
#endregion
#region Files
#endregion
#region Languages
#endregion
#region Macros
#endregion
#region Media
#endregion
#region MediaTypes
#endregion
#region Package Manifest
#endregion
#region Templates
/// <summary>
/// Imports and saves package xml as <see cref="ITemplate"/>
/// </summary>
/// <param name="element">Xml to import</param>
/// <param name="userId">Optional user id</param>
/// <returns>An enumrable list of generated Templates</returns>
public IEnumerable<ITemplate> ImportTemplates(XElement element, int userId = 0)
{
var name = element.Name.LocalName;
if (name.Equals("Templates") == false && name.Equals("Template") == false)
{
throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'Templates' for multiple imports or 'Template' for a single import.");
}
var templates = new List<ITemplate>();
var templateElements = name.Equals("Templates")
? (from doc in element.Elements("Template") select doc).ToList()
: new List<XElement> { element.Element("Template") };
var fields = new List<TopologicalSorter.DependencyField<XElement>>();
foreach (XElement tempElement in templateElements)
{
var dependencies = new List<string>();
if(tempElement.Element("Master") != null && string.IsNullOrEmpty(tempElement.Element("Master").Value) == false)
dependencies.Add(tempElement.Element("Master").Value);
var field = new TopologicalSorter.DependencyField<XElement>
{
Alias = tempElement.Element("Alias").Value,
Item = new Lazy<XElement>(() => tempElement),
DependsOn = dependencies.ToArray()
};
fields.Add(field);
}
//Sort templates by dependencies to a potential master template
var sortedElements = TopologicalSorter.GetSortedItems(fields);
foreach (var templateElement in sortedElements)
{
var templateName = templateElement.Element("Name").Value;
var alias = templateElement.Element("Alias").Value;
var design = templateElement.Element("Design").Value;
var masterElement = templateElement.Element("Master");
var isMasterPage = IsMasterPageSyntax(design);
var path = isMasterPage ? MasterpagePath(alias) : ViewPath(alias);
var template = new Template(path, templateName, alias) { Content = design };
if (masterElement != null && string.IsNullOrEmpty(masterElement.Value) == false)
{
template.MasterTemplateAlias = masterElement.Value;
var masterTemplate = templates.FirstOrDefault(x => x.Alias == masterElement.Value);
if(masterTemplate != null)
template.MasterTemplateId = new Lazy<int>(() => masterTemplate.Id);
}
templates.Add(template);
}
if(templates.Any())
_fileService.SaveTemplate(templates, userId);
return templates;
}
private bool IsMasterPageSyntax(string code)
{
return Regex.IsMatch(code, @"<%@\s*Master", RegexOptions.IgnoreCase) ||
code.InvariantContains("<umbraco:Item") || code.InvariantContains("<asp:") || code.InvariantContains("<umbraco:Macro");
}
private string ViewPath(string alias)
{
return SystemDirectories.MvcViews + "/" + alias.Replace(" ", "") + ".cshtml";
}
private string MasterpagePath(string alias)
{
return IOHelper.MapPath(SystemDirectories.Masterpages + "/" + alias.Replace(" ", "") + ".master");
}
#endregion
}
}
@@ -20,6 +20,7 @@ namespace Umbraco.Core.Services
private Lazy<DataTypeService> _dataTypeService;
private Lazy<FileService> _fileService;
private Lazy<LocalizationService> _localizationService;
private Lazy<PackagingService> _packagingService;
/// <summary>
/// Constructor
@@ -70,6 +71,9 @@ namespace Umbraco.Core.Services
if(_localizationService == null)
_localizationService = new Lazy<LocalizationService>(() => new LocalizationService(provider, repositoryFactory.Value));
if(_packagingService == null)
_packagingService = new Lazy<PackagingService>(() => new PackagingService(_contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value, _fileService.Value, repositoryFactory.Value, provider));
}
/// <summary>
@@ -120,6 +124,14 @@ namespace Umbraco.Core.Services
get { return _mediaService.Value; }
}
/// <summary>
/// Gets the <see cref="PackagingService"/>
/// </summary>
public PackagingService PackagingService
{
get { return _packagingService.Value; }
}
/// <summary>
/// Gets the <see cref="IMacroService"/>
/// </summary>
+4
View File
@@ -179,6 +179,8 @@ namespace Umbraco.Core
public static string TrimEnd(this string value, string forRemoving)
{
if (string.IsNullOrEmpty(value)) return value;
if (string.IsNullOrEmpty(forRemoving)) return value;
while (value.EndsWith(forRemoving, StringComparison.InvariantCultureIgnoreCase))
{
value = value.Remove(value.LastIndexOf(forRemoving, StringComparison.InvariantCultureIgnoreCase));
@@ -189,6 +191,8 @@ namespace Umbraco.Core
public static string TrimStart(this string value, string forRemoving)
{
if (string.IsNullOrEmpty(value)) return value;
if (string.IsNullOrEmpty(forRemoving)) return value;
while (value.StartsWith(forRemoving, StringComparison.InvariantCultureIgnoreCase))
{
value = value.Substring(forRemoving.Length);
+173
View File
@@ -0,0 +1,173 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core
{
internal class TopologicalSorter
{
private readonly int[] _vertices; // list of vertices
private readonly int[,] _matrix; // adjacency matrix
private int _numVerts; // current number of vertices
private readonly int[] _sortedArray;
public TopologicalSorter(int size)
{
_vertices = new int[size];
_matrix = new int[size, size];
_numVerts = 0;
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
_matrix[i, j] = 0;
_sortedArray = new int[size]; // sorted vert labels
}
#region Public Methods
public int AddVertex(int vertex)
{
_vertices[_numVerts++] = vertex;
return _numVerts - 1;
}
public void AddEdge(int start, int end)
{
_matrix[start, end] = 1;
}
public int[] Sort() // toplogical sort
{
while (_numVerts > 0) // while vertices remain,
{
// get a vertex with no successors, or -1
int currentVertex = NoSuccessors();
if (currentVertex == -1) // must be a cycle
throw new Exception("Graph has cycles");
// insert vertex label in sorted array (start at end)
_sortedArray[_numVerts - 1] = _vertices[currentVertex];
DeleteVertex(currentVertex); // delete vertex
}
// vertices all gone; return sortedArray
return _sortedArray;
}
#endregion
#region Private Helper Methods
// returns vert with no successors (or -1 if no such verts)
private int NoSuccessors()
{
for (int row = 0; row < _numVerts; row++)
{
bool isEdge = false; // edge from row to column in adjMat
for (int col = 0; col < _numVerts; col++)
{
if (_matrix[row, col] > 0) // if edge to another,
{
isEdge = true;
break; // this vertex has a successor try another
}
}
if (!isEdge) // if no edges, has no successors
return row;
}
return -1; // no
}
private void DeleteVertex(int delVert)
{
// if not last vertex, delete from vertexList
if (delVert != _numVerts - 1)
{
for (int j = delVert; j < _numVerts - 1; j++)
_vertices[j] = _vertices[j + 1];
for (int row = delVert; row < _numVerts - 1; row++)
MoveRowUp(row, _numVerts);
for (int col = delVert; col < _numVerts - 1; col++)
MoveColLeft(col, _numVerts - 1);
}
_numVerts--; // one less vertex
}
private void MoveRowUp(int row, int length)
{
for (int col = 0; col < length; col++)
_matrix[row, col] = _matrix[row + 1, col];
}
private void MoveColLeft(int col, int length)
{
for (int row = 0; row < length; row++)
_matrix[row, col] = _matrix[row, col + 1];
}
#endregion
#region Internal Staic methods
internal static IEnumerable<T> GetSortedItems<T>(List<DependencyField<T>> fields) where T : class
{
int[] sortOrder = GetTopologicalSortOrder(fields);
var list = new List<T>();
for (int i = 0; i < sortOrder.Length; i++)
{
var field = fields[sortOrder[i]];
list.Add(field.Item.Value);
}
list.Reverse();
return list;
}
internal static int[] GetTopologicalSortOrder<T>(List<DependencyField<T>> fields) where T : class
{
var g = new TopologicalSorter(fields.Count());
var indexes = new Dictionary<string, int>();
//add vertices
for (int i = 0; i < fields.Count(); i++)
{
indexes[fields[i].Alias.ToLower()] = g.AddVertex(i);
}
//add edges
for (int i = 0; i < fields.Count; i++)
{
if (fields[i].DependsOn != null)
{
for (int j = 0; j < fields[i].DependsOn.Length; j++)
{
g.AddEdge(i,
indexes[fields[i].DependsOn[j].ToLower()]);
}
}
}
int[] result = g.Sort();
return result;
}
#endregion
internal class DependencyField<T> where T : class
{
public DependencyField()
{
}
public DependencyField(string @alias, string[] dependsOn, Lazy<T> item)
{
Alias = alias;
DependsOn = dependsOn;
Item = item;
}
public string Alias { get; set; }
public string[] DependsOn { get; set; }
public Lazy<T> Item { get; set; }
}
}
}
-1
View File
@@ -232,7 +232,6 @@ namespace Umbraco.Core
"NuGet.",
"RouteDebugger,",
"SqlCE4Umbraco,",
"Umbraco.Core,",
"umbraco.datalayer,",
"umbraco.interfaces,",
"umbraco.providers,",
+7 -2
View File
@@ -143,8 +143,10 @@
<Compile Include="Models\ContentBase.cs" />
<Compile Include="Models\ContentExtensions.cs" />
<Compile Include="Enum.cs" />
<Compile Include="Events\MacroErrorEventArgs.cs" />
<Compile Include="HashCodeCombiner.cs" />
<Compile Include="IO\FileSystemWrapper.cs" />
<Compile Include="MacroErrorBehaviour.cs" />
<Compile Include="Media\IImageUrlProvider.cs" />
<Compile Include="Models\ContentTypeBase.cs" />
<Compile Include="Models\ContentTypeCompositionBase.cs" />
@@ -451,8 +453,10 @@
<Compile Include="Persistence\SqlSyntax\MySqlSyntaxProvider.cs" />
<Compile Include="Persistence\SqlSyntax\SqlCeSyntaxProvider.cs" />
<Compile Include="Persistence\SqlSyntax\SqlServerSyntaxProvider.cs" />
<Compile Include="Persistence\SqlSyntax\SqlSyntaxProviderAttribute.cs" />
<Compile Include="Persistence\SqlSyntax\SqlSyntaxProviderBase.cs" />
<Compile Include="Persistence\SqlSyntax\SyntaxConfig.cs" />
<Compile Include="Persistence\SqlSyntax\SqlSyntaxContext.cs" />
<Compile Include="Persistence\SqlSyntax\SqlSyntaxProvidersResolver.cs" />
<Compile Include="Persistence\TransactionType.cs" />
<Compile Include="Persistence\UmbracoDatabase.cs" />
<Compile Include="Persistence\UnitOfWork\FileUnitOfWork.cs" />
@@ -650,8 +654,10 @@
<Compile Include="Services\LocalizationService.cs" />
<Compile Include="Services\MacroService.cs" />
<Compile Include="Services\MediaService.cs" />
<Compile Include="Services\PackagingService.cs" />
<Compile Include="Services\ServiceContext.cs" />
<Compile Include="Services\UserService.cs" />
<Compile Include="TopologicalSorter.cs" />
<Compile Include="TypeExtensions.cs" />
<Compile Include="ReadLock.cs" />
<Compile Include="TypeFinder.cs" />
@@ -701,7 +707,6 @@
<Name>umbraco.interfaces</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -6,6 +6,7 @@ using System.Web;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Persistence.SqlSyntax;
using umbraco.interfaces;
namespace Umbraco.Tests.BootManagers
@@ -27,6 +28,7 @@ namespace Umbraco.Tests.BootManagers
{
_testApp = null;
ApplicationEventsResolver.Reset();
SqlSyntaxProvidersResolver.Reset();
Resolution.IsFrozen = false;
}
@@ -67,6 +69,12 @@ namespace Umbraco.Tests.BootManagers
protected override void InitializeResolvers()
{
//Do nothing as we don't want to initialize all resolvers in this test
//We only include this resolver to not cause trouble for the database context
SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver(
PluginManager.Current.ResolveSqlSyntaxProviders())
{
CanResolveBeforeFrozen = true
};
}
}
@@ -10,6 +10,77 @@ namespace Umbraco.Tests
[TestFixture]
public class EnumerableExtensionsTests
{
[Test]
public void Flatten_List()
{
var hierarchy = new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem(),
new TestItem()
}
}
}
}
}
},
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
}
}
},
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
}
}
}
}
},
}
};
var flattened = hierarchy.Children.FlattenList(x => x.Children);
Assert.AreEqual(10, flattened.Count());
}
private class TestItem
{
public TestItem()
{
Children = Enumerable.Empty<TestItem>();
}
public IEnumerable<TestItem> Children { get; set; }
}
[Test]
public void InGroupsOf_ReturnsAllElements()
{
+17 -1
View File
@@ -2,6 +2,7 @@ using System.Configuration;
using System.Web.Routing;
using NUnit.Framework;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Tests.TestHelpers;
using System.Web.Mvc;
@@ -23,6 +24,9 @@ namespace Umbraco.Tests
public override void TearDown()
{
//ensure this is reset
SystemDirectories.Root = null;
SettingsForTests.UmbracoPath = "~/umbraco";
//reset the app config
base.TearDown();
@@ -35,7 +39,19 @@ namespace Umbraco.Tests
Assert.That(UmbracoVersion.Current.ToString(3), Is.EqualTo("6.0.0"));
}
[TestCase("/umbraco/umbraco.aspx")]
[TestCase("~/umbraco", "/", "umbraco")]
[TestCase("~/umbraco", "/MyVirtualDir", "umbraco")]
[TestCase("~/customPath", "/MyVirtualDir/", "custompath")]
[TestCase("~/some-wacky/nestedPath", "/MyVirtualDir", "some-wacky-nestedpath")]
[TestCase("~/some-wacky/nestedPath", "/MyVirtualDir/NestedVDir/", "some-wacky-nestedpath")]
public void Umbraco_Mvc_Area(string path, string rootPath, string outcome)
{
SettingsForTests.UmbracoPath = path;
SystemDirectories.Root = rootPath;
Assert.AreEqual(outcome, Umbraco.Core.Configuration.GlobalSettings.UmbracoMvcArea);
}
[TestCase("/umbraco/umbraco.aspx")]
[TestCase("/umbraco/editContent.aspx")]
[TestCase("/install/default.aspx")]
[TestCase("/install/")]
@@ -14,7 +14,7 @@ namespace Umbraco.Tests.Migrations
[SetUp]
public void SetUp()
{
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
}
[Test]
@@ -32,7 +32,7 @@ namespace Umbraco.Tests.Migrations
Resolution.Freeze();
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
}
[Test]
@@ -39,7 +39,7 @@ namespace Umbraco.Tests.Migrations
Resolution.Freeze();
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
}
[Test]
@@ -49,7 +49,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
DatabaseSpecificSetUp();
SyntaxConfig.SqlSyntaxProvider = GetSyntaxProvider();
SqlSyntaxContext.SqlSyntaxProvider = GetSyntaxProvider();
}
[Test]
@@ -91,7 +91,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
public virtual void TearDown()
{
PluginManager.Current = null;
SyntaxConfig.SqlSyntaxProvider = null;
SqlSyntaxContext.SqlSyntaxProvider = null;
MigrationResolver.Reset();
Resolution.IsFrozen = false;
@@ -72,13 +72,13 @@ namespace Umbraco.Tests.Migrations.Upgrades
var engine = new SqlCeEngine(settings.ConnectionString);
engine.CreateDatabase();
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
}
[TearDown]
public virtual void TearDown()
{
SyntaxConfig.SqlSyntaxProvider = null;
SqlSyntaxContext.SqlSyntaxProvider = null;
Resolution.IsFrozen = false;
TestHelper.CleanContentDirectories();
@@ -75,7 +75,7 @@ namespace Umbraco.Tests.Persistence
var engine = new SqlCeEngine(settings.ConnectionString);
engine.CreateDatabase();
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntaxProvider.Instance;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
//Create the umbraco database
_dbContext.Database.CreateDatabaseSchema(false);
@@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Id_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = ContentMapper.Instance.Map("Id");
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Trashed_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = ContentMapper.Instance.Map("Trashed");
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Published_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = ContentMapper.Instance.Map("Published");
@@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Version_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = ContentMapper.Instance.Map("Version");
@@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Id_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = ContentTypeMapper.Instance.Map("Id");
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Name_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = ContentTypeMapper.Instance.Map("Name");
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Thumbnail_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = ContentTypeMapper.Instance.Map("Thumbnail");
@@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Description_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = ContentTypeMapper.Instance.Map("Description");
@@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Id_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DataTypeDefinitionMapper.Instance.Map("Id");
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Key_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DataTypeDefinitionMapper.Instance.Map("Key");
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_DatabaseType_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DataTypeDefinitionMapper.Instance.Map("DatabaseType");
@@ -50,7 +50,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_ControlId_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DataTypeDefinitionMapper.Instance.Map("ControlId");
@@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Id_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DictionaryMapper.Instance.Map("Id");
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Key_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DictionaryMapper.Instance.Map("Key");
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_ItemKey_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DictionaryMapper.Instance.Map("ItemKey");
@@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Key_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DictionaryTranslationMapper.Instance.Map("Key");
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Language_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DictionaryTranslationMapper.Instance.Map("Language");
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Value_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = DictionaryTranslationMapper.Instance.Map("Value");
@@ -11,7 +11,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_Id_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = LanguageMapper.Instance.Map("Id");
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_IsoCode_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = LanguageMapper.Instance.Map("IsoCode");
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers
public void Can_Map_CultureName_Property()
{
// Arrange
SyntaxConfig.SqlSyntaxProvider = SqlCeSyntax.Provider;
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
// Act
string column = LanguageMapper.Instance.Map("CultureName");

Some files were not shown because too many files have changed in this diff Show More