Compare commits

...

884 Commits

Author SHA1 Message Date
Sebastiaan Janssen 10ab3c71fd Bump version 2014-10-08 09:44:59 +02:00
Shannon 1eab26c0f6 reverts IQuery 2014-10-08 17:26:55 +11:00
Shannon 0543c620eb bumps version 2014-10-08 17:25:06 +11:00
Shannon 646e5f173d Fixes descendant queries to ensure that the comma is suffixed to the path, otherwise strange things could happen when there are longer ids! 2014-10-08 17:23:14 +11:00
Shannon b5594517bd Fixes: U4-5583 Can no longer link to Media Items from RTE in 6.2.3 - Due to a cherry pick/merge issue since the newer 7.x EntityRepository deals with NVarchar and NText values whereas the 6.x one did not. Have backported the mapping poco classes to now also support NVarchar and NText for the EntityRepository. Have also fixed the basic query to ensure that there are no left joins before inner joins which can also cause problems. Fixed up the duplicate where clause. Adds more tests to entity service. 2014-10-08 17:13:28 +11:00
Sebastiaan Janssen 246dfba8ac Bump version 2014-10-02 18:06:15 +02:00
Shannon 7d189a6fb8 Backports the @ symbol escaping fixes 2014-10-03 00:28:49 +10:00
Shannon 71242430da Fixes a query that would cause the new petapoco changes to have issues since it was asking for the wrong type 2014-10-01 16:37:42 +10:00
Shannon 4ee4f296fc updates version 2014-09-29 17:31:24 +10:00
Shannon b9e4950e36 fixes up entity repo merges to support old db schema 2014-09-29 17:30:09 +10:00
Shannon ba52f9235e Backports fixes to SQL parameterization and PetaPoco mem updates 2014-09-29 17:11:58 +10:00
Sebastiaan Janssen 33ccf490ab Update nuspec to ask for a valid nuget pkg 2014-08-25 15:53:45 +02:00
Sebastiaan Janssen 03ba8c9e14 Update to 6.2.2, removes airinstallbadge 2014-08-25 13:46:21 +02:00
Shannon 13b57c7638 adds some logging 2014-08-25 16:40:45 +10:00
Shannon a8b297903d Ensures we don't get any ysods when changing doc type properties and the content re-creation since it's running on an async thread (U4-5388 , U4-5387 ) 2014-08-25 16:16:42 +10:00
Shannon 89b5774106 Fixes: U4-5380 Booting.aspx security issue 2014-08-21 14:39:06 -06:00
Shannon 774f201514 Adds a simple cache mechanism to hold reflected property info when cloning - reduces perf to 10% of what it used to be 2014-08-20 20:09:05 -06:00
Sebastiaan Janssen 12e2aa679b Merge pull request #455 from leekelleher/U4-4249
U4-4249 - PetaPocoExtensions CreateTable doesn't recreate the table
2014-08-20 10:45:56 +02:00
leekelleher 1978930fa2 Amends CreateTable, so if 'overwrite' is enabled, the table is dropped, then recreated. 2014-08-19 18:56:15 +01:00
Stephan c4e4f9579b U4-4931 - fix tests 2014-08-15 09:54:04 +02:00
Stephan 9782f66507 U4-5084 - fix commit 2014-08-14 22:24:12 +02:00
Stephan e9938afc83 Merge pull request #418 from zpqrtbnk/6.2-4931
U4-4931 - lock contention & potential application lockdown
2014-08-14 20:52:13 +02:00
Stephan fcda9821d0 Merge branch '6.2.2' into 6.2-4931 2014-08-14 20:50:37 +02:00
Stephan bdc234b18a U4-5084 - DynamicPublishedContentList ext methods confusion 2014-08-14 20:49:49 +02:00
Sebastiaan Janssen 908afbd264 #U4-2238 Fixed
Issue when saving/publishing special characters - '' hexadecimal value 0x03, is an invalid character
2014-08-14 10:26:38 +02:00
Sebastiaan Janssen c548ad6a98 Update failing unit test now that MaxInvalidPasswordAttempts is 20 by default 2014-08-14 10:16:02 +02:00
Sebastiaan Janssen 99b2a2da38 #U4-5337 fixed Due in version: 7.1.5,6.2.2
Too easy to lock yourself out of the backoffice
2014-08-12 11:06:24 +02:00
Sebastiaan Janssen 15ed458ad3 #U4-5258 Fixed
RelationService AreRelated should accepts two entity IDs and a relationTypeAlias
2014-08-12 10:25:33 +02:00
Shannon 6ce303a918 Completes: U4-5264 Add Count methods to IContentService, IMediaService, etc... 2014-08-05 12:37:20 -06:00
Shannon 62d3dc78fa Ensures all caching is disabled for editing templates (master pages and views) 2014-08-05 10:59:54 -06:00
Shannon 3374f9e023 Ensures that the batched distributed calls doesn't cache refresh the server executing the distributed calls since tht will already be done locally. 2014-08-05 10:32:07 -06:00
Stephan 2675992d82 Merge branch '6.2.2' into 6.2-4931 2014-08-05 18:20:04 +02:00
Stephan ce29f54663 U4-4837 - bugfix Umbraco.Core.EnumerableExtensions.InGroupsOf 2014-08-05 17:52:43 +02:00
Shannon 7261162d8a Fixes some of U4-2633 Bundle all cache refresher transmissions into a single call per request for much better performance. See last note on issue. 2014-08-04 17:50:19 -06:00
Shannon b5f900e789 added a couple of tests for member names 2014-07-28 19:37:44 -07:00
Shannon fdab6d5de5 Merge branch '6.2.2' of https://github.com/umbraco/Umbraco-CMS into 6.2.2 2014-07-24 09:39:12 -07:00
Shannon ff94eba3a7 Fixes: U4-5273 6.2: Umbraco.Field no longer rendering macro container 2014-07-24 09:39:05 -07:00
Sebastiaan Janssen e200e2fc48 Removes obsolete cachebrowser 2014-07-24 16:17:40 +02:00
Shannon 22dde5a421 U4-4738 Backoffice search should support node ID search 2014-07-23 14:07:21 -07:00
Shannon 7f510c107a updates proj's with correct specific version attributes 2014-07-23 12:31:38 -07:00
Shannon 2ebfd8f3d4 updates nuspec to have latest versions for all dependencies 2014-07-23 12:31:16 -07:00
Shannon fd7930256b Uninstalls package CodeSharp.Package.AspNetWebPage and removes refs to Nuget.Core and Webpages.Administration - neither of which are used anywhere... but we've been shipping Umbraco with them for some reason. 2014-07-23 10:53:30 -07:00
Shannon c24775adb0 re-installs mvc, webapi and ensures running the latest 2.0.x versions of webpages and razor, now all proj's are consistent with correct versions referenced and copy local set correctly. 2014-07-23 10:03:26 -07:00
Shannon 217f591db0 updates proj references to have SpecificVersion set to false for libs 2014-07-22 16:13:26 -07:00
Shannon d453aedd0d Microsoft.Net.Http required a reinstall command for the UI project as noted by it's persisted 'requiresReinstall' attribute in the packages.config - also ensures that ALL of the WebApi DLLs are copied local 2014-07-22 15:51:13 -07:00
Shannon 4693fb23c8 removes unneeded lock on master controller factory - must have been left over from some v5 stuff for some reason :( this will speed things up a bit! 2014-07-18 16:28:54 +10:00
Shannon 7848a3095d Fixes: U4-5207 User Type with a space in the name breaks User Content 2014-07-16 14:12:04 +10:00
Shannon 388eea95e5 fixes a single vs first check with render route handler when there might be duplicate routes assigned to a controller, fixes short/int parse 2014-07-16 13:46:15 +10:00
Shannon 6167d1584a Fixes an xss vulnerability 2014-07-15 11:37:31 +10:00
Stephan bfd0c5e309 U4-4931 - also for ObjectCacheRuntime provider 2014-07-10 10:25:51 +02:00
Stephan 43669e62b4 Merge branch '6.2.2' into 6.2-4931 2014-07-10 10:25:12 +02:00
Shannon 6b128ea7d4 Fixes: U4-5208 RenderActionInvoker needs to be able to run async so needs to inherit from AsyncControllerActionInvoker 2014-07-10 17:29:34 +10:00
Shannon d5993a4783 Backports fix from 7 for GetDimensions call to ensure the file exists 2014-07-10 12:09:26 +10:00
Shannon 86c2a6e8a9 updates physical file system, now that files are being disposed of properly we don't need to delete first 2014-07-10 11:51:48 +10:00
Shannon 874f464a2b Fixes: U4-5190 Overwrite Media File in 6.2.1 - process cannot access along with a bunch of other undisposed disposables :/ 2014-07-10 11:45:57 +10:00
Shannon b3c41e051f Fixes: U4-5199 Appending certain query strings to URLs cause InvalidOperationException (The UmbracoContext.Current is null) 2014-07-10 11:10:49 +10:00
Shannon a88637910f updates content xml bits so if it's called outside a web req it still executes.
Conflicts:
	src/Umbraco.Web/umbraco.presentation/content.cs
2014-07-10 10:45:26 +10:00
Shannon 431e93000e Fixes: U4-5157 Membership.GetUser() causes 13 SQL queries, including duplicates 2014-07-08 19:04:38 +10:00
Shannon 1a821b4073 super quick performance win in the case where people don't pass in distinct values 2014-07-01 17:41:22 +10:00
Shannon a89b9e9da6 ignores log4net tests 2014-07-01 11:16:57 +10:00
Shannon 8917701fa3 ignores failing test - need stephane to look 2014-07-01 11:03:47 +10:00
Shannon 68b17bff08 Ensures no membership user writing when checking public access 2014-07-01 10:52:29 +10:00
Shannon 7a12060c37 Potentially fixes U4-5069 Deadlock occurring in MemberService.GetByUsername
Conflicts:
	src/Umbraco.Web/Security/MembershipHelper.cs
2014-07-01 10:46:52 +10:00
Shannon 525280d466 fixed some tests 2014-06-30 14:09:36 +10:00
Shannon 496beca8f2 This Can_Find_Targetted_Migrations test needed a valid database to pass. This update ensures that the database is created with the old version 4.8 db schema. 2014-06-30 14:02:43 +10:00
Stephan 637a22293d U4-4931 - fixing & refactoring 2014-06-28 18:33:31 +02:00
Stephan 3c8517edcb Merge branch '6.2.2' into 6.2-4931 2014-06-28 16:26:44 +02:00
Stephan 45e6127d00 U4-4866 - fix the build 2014-06-28 16:26:27 +02:00
Stephan 6eb5d3f7ef Merge branch '6.2.2' into 6.2-4931 2014-06-28 16:06:30 +02:00
Stephan e6986432df U4-4931 - fixing & refactoring 2014-06-28 12:24:02 +02:00
Shannon 80103e6155 Fixes: U4-4866 Select content root when creating a package 2014-06-26 16:55:44 +10:00
Shannon 392634eb76 bumps nuspec versions 2014-06-26 11:44:28 +10:00
Shannon 259bc863f0 Removes Examine.dll deploy from nuspec 2014-06-26 11:32:43 +10:00
Shannon 582bafdefd Updates version 2014-06-26 10:02:09 +10:00
Shannon 9924ef2381 Merge branch '6.2.1' into 6.2.2 2014-06-26 09:57:16 +10:00
Shannon 859fbaaa05 Fixes: U4-5121 umbraco.content launches threadpool threads to reload the xml cache which causes lots of other issues
Conflicts:
	src/Umbraco.Web/umbraco.presentation/content.cs
2014-06-25 19:02:49 +10:00
Shannon 72991334c4 little bit of code cleanup 2014-06-25 15:55:52 +10:00
Shannon c659d5b85e fixes dll ref 2014-06-25 14:35:14 +10:00
Shannon a4bf4b0977 Fixes: U4-5118 Examine not storing XML fragments - updates to latest examine 2014-06-25 14:19:31 +10:00
Shannon bef6ce66f1 Updated core nuspec to include Examine 2014-06-25 14:19:06 +10:00
Shannon a18a2198a8 removes comment 2014-06-25 12:25:27 +10:00
Shannon 7cf7ac687c last issue with state/keep alive timer 2014-06-25 12:03:31 +10:00
Shannon 7ce0272169 updates state param with timers to use singleton 2014-06-25 11:56:36 +10:00
Shannon acb934e3f1 ensures timer's are not GCd 2014-06-25 11:52:48 +10:00
Shannon 3aa486a463 another log 2014-06-25 11:36:58 +10:00
Shannon 5aa0621c90 adds some notes 2014-06-25 11:36:14 +10:00
Shannon 625b8f7e65 Ensures the 'Index' portion of the path is used for scheduled publishing 2014-06-25 11:26:08 +10:00
Shannon e27163f3a7 adds logging to scheduled bits 2014-06-25 11:00:11 +10:00
Shannon 65ea6f94d3 adds authorization to the scheduled publishing , this new attribute can be used to secure scheduled tasks as well. 2014-06-23 15:02:23 +10:00
Shannon 9158ea1ace fixes url returned in GetCurrentServerUmbracoBaseUrl 2014-06-20 14:45:45 +10:00
Shannon e8f7f77bb6 Fixes: U4-581 Automatic publishing not working in load balanced setup - added some more convention and configuration to distributed calls so that servers are aware of the master and how to call into themselves for scheduled tasks, ping and scheduled publishing. Will need to update the docs on LB regarding this too. Cleaned up the code that does the scheduling and separates it into proper segments. Obsoletes the old presentation classes that were doing it. 2014-06-20 14:34:21 +10:00
Stephan 75e003185a U4-4931 - do not cache exceptions 2014-06-17 19:34:24 +02:00
Stephan 9d12e1c7df Merge branch '6.2.2' into 6.2-4931 2014-06-17 19:19:17 +02:00
Shannon b8575ef158 Started writing test implementation to mimic what developers might test in their controllers to expose the pitfalls of umbraco testing so we can make this simpler - identifying what needs to be public and how to re-strcuture some objects constructors, etc... to simplify and make this possible. 2014-06-17 18:53:23 +10:00
Shannon d3bb750f98 Updated to latest Examine with lock fixes 2014-06-17 16:07:08 +10:00
Morten Christensen 02eff33d29 Fixes U4-2640 LocalizationService throws exception when getting dictionary items and adds tests for the LocalizationService 2014-06-08 13:16:32 +02:00
Shannon b43f39a0cb disables dist call 2014-06-08 12:50:45 +02:00
Shannon d0cb27d1c1 Completes: U4-2633 Bundle all cache refresher transmissions into a single call per request for much better performance 2014-06-08 12:49:20 +02:00
Stephan 16a1720bf7 Merge remote-tracking branch 'origin/6.2.1' into 6.2.1 2014-05-28 17:11:56 +02:00
Sebastiaan Janssen ea32776174 Bump version 2014-05-28 17:07:51 +02:00
Stephan 320b53ae3c U4-4773 - bring back IPublishedContentProperty Alias and Version (compat) 2014-05-28 11:36:31 +02:00
Shannon d987dfb5a2 Fixes: U4-4141 7.0.2 "Save and send for approval" fails for a writer user on a newly created unsaved content page 2014-05-28 12:40:43 +10:00
Stephan 74806984b3 U4-4931 - fixing & refactoring 2014-05-27 12:17:48 +02:00
Stephan c8c278c7bc Merge remote-tracking branch 'origin/6.2.1' into 6.2.1 2014-05-27 12:17:43 +02:00
Sebastiaan Janssen 13e8e972eb U4-4956 UserService.SavePassword method always throws a not supported exception 2014-05-27 11:43:50 +02:00
Stephan a8e4c3eb9a Merge remote-tracking branch 'origin/6.2.1' into 6.2.1 2014-05-26 18:07:45 +02:00
Stephan d631039c0d U4-4928 - issue with missing media content properties 2014-05-26 18:07:20 +02:00
Stephan 113b866485 U4-4931 - fixing & refactoring 2014-05-26 15:56:29 +02:00
Stephan 6c6ef8d144 Merge remote-tracking branch 'origin/6.2.1' into 6.2.1 2014-05-26 15:03:38 +02:00
Stephan 95b9a46b88 U4-4928 - issue with missing media content properties 2014-05-26 15:02:05 +02:00
Stephan 99250cefbb U4-4931 - fixing & refactoring 2014-05-23 10:46:41 +02:00
Stephan dc651a1c42 Merge remote-tracking branch 'origin/6.2.1' into 6.2.1 2014-05-23 10:46:13 +02:00
Sebastiaan Janssen 8fb446960c U4-4927 Image Cropper Crop URL is wrong in 6.2.0
Reverts part of 067268a96e which was refactored wrong
2014-05-22 19:39:25 +02:00
Stephan 4e9fd5a223 U4-4931 - fixing & refactoring 2014-05-22 13:43:55 +02:00
Stephan e2c36d7212 Merge remote-tracking branch 'origin/6.2.1' into HEAD 2014-05-22 13:40:58 +02:00
Shannon 62887607ff fixes csrf with mediauploader.ashx 2014-05-22 12:44:04 +10:00
Stephan 695cc07912 Merge remote-tracking branch 'origin/6.2.1' into 6.2.1 2014-05-20 09:32:54 +02:00
Stephan f325794523 U4-4949 - fix issue with domains 2014-05-20 09:32:26 +02:00
Sebastiaan Janssen 3ec6d2b82f U4-4861 6.2.0 Nuget package copies wrong files 2014-05-19 10:08:26 +02:00
Stephan 46f57a3115 U4-4931 - lock contention & potential application lockdown 2014-05-18 19:13:22 +02:00
Sebastiaan Janssen d697c590e7 U4-4930 NuGet update fails to copy new Umbraco binaries 2014-05-16 18:54:49 +02:00
Sebastiaan Janssen a55cd67fd6 U4-4650 Pluralization of document type aliases doesn't always work 2014-05-16 14:33:25 +02:00
Sebastiaan Janssen afa81be102 Fixes U4-4650 Pluralization of document type aliases doesn't always work 2014-05-16 14:23:40 +02:00
Stephan ddd0e8abb5 Bugfix media cache property alias case sensitivity 2014-05-16 10:10:55 +02:00
Stephan e07f573683 Fix the build 2014-05-16 09:57:21 +02:00
Shannon 1f88960b3f Fixes: U4-4926 Pre-values need to be cloned in/out of the cache
Conflicts:
	src/Umbraco.Core/Models/PreValue.cs
	src/Umbraco.Core/Models/PreValueCollection.cs
2014-05-16 12:09:47 +10:00
Shannon d8edf67b82 Fixes: U4-4842 Unable to edit "name" and "alias" to MediaType property 2014-05-16 12:09:08 +10:00
Shannon 365a8e85e9 Fixes: U4-2356 2014-05-15 16:13:54 +10:00
Shannon 5f9dddafd8 fixed an upgrade script when upgrading from old 4.x versions 2014-05-15 14:11:43 +10:00
Shannon 836297df58 Fixes error message on publishing when it fails due to any of these statuses: FailedHasExpired, FailedAwaitingRelease, FailedIsTrashed 2014-05-15 13:35:52 +10:00
Shannon 78613823ae Fixes: U4-4853 Richtext Editor doesn't render macros after upgrade to Umbraco 6.2.0 2014-05-13 15:22:16 +10:00
Shannon 937e840104 Fixes: U4-4873 RuntimeCacheRefresher does not remove items when media or content requires cache refreshing & U4-4871 Synced media indexes between load balanced servers do not sync all properties 2014-05-13 10:40:56 +10:00
Shannon 313d77eb91 Fixes: U4-4789 PluginCache doesn't update with code defined PropertyEditors in package and publicizes a couple things 2014-05-12 17:19:17 +10:00
Stephan 4e5019d5af U4-4851 - Umbraco.Field legacy names 2014-05-11 21:33:56 +02:00
Shannon da0b935604 Fixes merge 2014-05-09 16:08:05 +10:00
Shannon b91a06ab98 Fixes: U4-4849 Cannot change a users language/sections in the back office 2014-05-09 16:00:30 +10:00
Shannon d61fb5d94d Fixes user cloning issues with allowed sections 2014-05-09 15:59:30 +10:00
Shannon 3b424274ee ensure properties reset on deep clone of ContentType (this is just a fail safe check) 2014-05-09 15:57:17 +10:00
Shannon b763c2ab2f Fixes deep clone of User object 2014-05-09 15:56:45 +10:00
Sebastiaan Janssen 16d98488e4 Losen up the requirement for json.net dependency 2014-05-01 14:06:28 +02:00
Morten Christensen 5a862f5c64 Fixes import of nested dictionary items #U4-4663 2014-05-01 13:51:33 +02:00
Sebastiaan Janssen caf41b74b8 Add failing test - dictionary items don't get properly nested 2014-05-01 12:26:18 +02:00
Sebastiaan Janssen e858f4ff1e U4-4775 creating new member group shows error message in dialog... 2014-05-01 11:45:14 +02:00
Sebastiaan Janssen 851961ef2b U4-4775 creating new member group shows error message in dialog... 2014-05-01 10:48:27 +02:00
Sebastiaan Janssen c139c5d93e U4-3925 Cancel Document_BeforePublish event gives YSOD 2014-05-01 09:55:14 +02:00
Shannon c4603ee5cd Fixes: U4-4798 When new property types are added, the internal Examine index isn't notified and will ignore them 2014-05-01 12:43:40 +10:00
Shannon 1e9d1007b6 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-05-01 11:36:33 +10:00
Shannon f23af85253 Fixes: U4-4624 Media cache hits the DB on every empty property, U4-4338 Umbraco fails to enumerate TypedMedia 2014-05-01 11:36:17 +10:00
Sebastiaan Janssen b0c5d16ba7 U4-4127 Turkish culture prevents Macros embedded 2014-04-30 19:29:32 +02:00
Stephan cd5581bef6 Back to IPublishedContentProperty (for 6 only) 2014-04-30 16:53:14 +02:00
Stephan 7d8da56dcb Revert "Reintroduce IPublishedContentProperty"
This reverts commit d33cc29f98.
2014-04-30 16:39:51 +02:00
Stephan 0501b181ce Refactor template aliases to strict aliases 2014-04-30 15:46:26 +02:00
Sebastiaan Janssen 3134668cec Bump version number 2014-04-30 12:00:19 +02:00
Shannon a8cc8fa688 Fixes case sensitivity with MySQL 2014-04-30 19:58:59 +10:00
Shannon cf2217cfe1 Fixes MySQL upgrades from < 6.0 2014-04-30 19:41:40 +10:00
Shannon e88e809e29 Use new YouTube oembed https end-point (old http one redirects) and make sure videos are embedded over https to allow for https Umbraco sites. 2014-04-30 17:39:13 +10:00
Shannon c5559d7721 Specifying assembly for membership/user provider
Addresses http://issues.umbraco.org/issue/U4-4781
2014-04-30 11:27:47 +10:00
Shannon 771e216813 U4-2635 Skip past replaced word when checking
Avoids infinite loop if search and replacement are equal
2014-04-30 11:21:12 +10:00
Stephan d33cc29f98 Reintroduce IPublishedContentProperty 2014-04-29 09:47:30 +02:00
Shannon b98fbbc75d Fixes: U4-4770 Preview XML is not generated for many operations in the ContentService, also moves some more CRUD logic in the content service to the content repo. 2014-04-29 11:11:48 +10:00
Shannon aba1862811 Fixes: U4-4754 Member and Media repositories need to generate preview xml when EnableGlobalPreviewStorage is true 2014-04-29 09:58:38 +10:00
Shannon 2f53698bc5 Fixes: U4-4766 UmbracoMembershipProvider.ChangePassword() is seal, what might be a breaking change? 2014-04-28 19:19:48 +10:00
Shannon e0e12d5773 Moves content xml crud logic for member service to member repo 2014-04-28 19:04:53 +10:00
Shannon 2e96de5449 Moves the CRUD logic from the media service to the media repo for dealing with content xml items and ensures it's done in the same transaction, streamlines how this process is done between the content, media, member services, adds test for it. 2014-04-28 18:53:21 +10:00
Shannon c5bce3b8cc completes: U4-4769 Remove the circular references from services for calls like ToXml which then calls into the PackagingService 2014-04-28 17:46:05 +10:00
Shannon b4286a7d4e works on U4-4769 - removing circular refs from media service 2014-04-28 17:38:24 +10:00
Shannon 31e018c045 Moves XML serialization for content/media/members to a resusable class: EntityXmlSerializer to remove the circular references we have by using the ToXml extension methods from directly in the services. This has been completed for the ContentService, next is Media and Member services. Updates the ContentService to not perform CUD operations for preview or published xml, this is now done at the repository level and now done in a single transaction for the saving and publishing events. Still need to do that for the member and media services too and the remaining methods in the content service 2014-04-28 17:28:40 +10:00
Shannon 50b71faff9 Adds .woff mime type 2014-04-28 12:45:12 +10:00
Shannon 033fd1b7ff Fixes: U4-4765 backoffice user section does not save password changes in v6.2 2014-04-28 12:24:39 +10:00
Shannon 2621b25fd3 Ensures that member saving events don't get raised for normal member operations like validating and getting a user and flagging them as online. This fixes: U4-3451 Cache on Partial View refreshed, after member execute login 2014-04-24 16:28:37 +10:00
Shannon 61055380c5 Ensures that member saving events don't get raised for normal member operations like validating and getting a user and flagging them as online. This fixes: U4-3451 Cache on Partial View refreshed, after member execute login 2014-04-24 16:26:21 +10:00
Shannon adf09d925f adds a comment 2014-04-24 14:51:41 +10:00
Shannon 12170fd787 fixes ysod overlay for ajax errors 2014-04-24 14:23:17 +10:00
Shannon c32cae16db Fixes: U4-4696 Macro personalized cache with custom membership provider not working - for any membership provider regardless of provider user key type 2014-04-24 12:14:06 +10:00
Shannon 437d1b759b fix for: U4-4696. Macro personalized cache with custom membership provider not working 2014-04-24 12:13:50 +10:00
Stephan f46811ff67 U4-3027 - fix content & property types alias casing 2014-04-24 00:18:24 +02:00
Stephan 6d50b46bd8 U4-4747,3027... - bugfix content type editor / aliases 2014-04-23 19:28:04 +02:00
Shannon a51bf232ec Fixes issue with data type pre-values and using PreValueAsArray when they are dictionary formatted. 2014-04-23 22:24:16 +10:00
Shannon fd19411e65 Fixes: U4-4743 Add IMemberService and IUserService to ServiceContext ctor 2014-04-23 20:41:03 +10:00
Shannon 7ac7bb9714 Fixes: U4-4746 Examine does not index updated paths/levels for moved/trashed media, U4-4744 Examine events do not listen for recycle bin emptying 2014-04-23 20:28:09 +10:00
Shannon 021cac9ca5 Fixes: U4-4746 Examine does not index updated paths/levels for moved/trashed media, U4-4744 Examine events do not listen for recycle bin emptying 2014-04-23 20:19:36 +10:00
Shannon 949447c25f Fixes examine lookup for children to ignore recycled media 2014-04-23 13:40:11 +10:00
Shannon 99d7bf91b7 Fixes null check in recycle bin repo
Conflicts:
	src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs
2014-04-23 13:39:34 +10:00
Shannon a92c232178 Fixes: U4-4653 MembershipHelper RegisterMember does not set password and ignores logMemberIn, adds a new flag to the model as to whether or not to have the cookie set as a persistent cookie (default is true) 2014-04-22 19:03:43 +10:00
Shannon 30901446e1 Fixes: U4-1853 Tinymce with the format dropdown added as soon as you interact with it the content tree stops working [Uncaught TypeError: Cannot set property 'href' of undefined (anonymous function) DependencyHandler.axd:57] Chrome Only.. 2014-04-22 18:17:28 +10:00
Shannon d772336c0f Fixes: U4-4695 Copy document type to new parent seems to lose some data, U4-4535 Create Copy method on the content type Service 2014-04-22 17:48:08 +10:00
Shannon f673cb024a Adds unit test for ensuring reset identities on cloning a content type 2014-04-22 14:00:03 +10:00
Shannon c4046ecb32 Fixes 'Clone' methods to ensure a Deep clone is used 2014-04-22 13:48:51 +10:00
Shannon 7823609500 Fixes: U4-4682 Get EditorTemplates and DisplayTemplates working with RenderViewEngine 2014-04-22 13:03:47 +10:00
Shannon a88cb3f724 Fixes: U4-3425 App_Code XSLT Extensions aren't recognized 2014-04-22 11:59:21 +10:00
Stephan 536b8ee921 U4-3425 - TypeHelper referenced assemblies issue 2014-04-19 17:44:52 +02:00
Stephan 3bf1041041 U4-3787 - Ensure we republish published descendants when republishing 2014-04-19 14:31:36 +02:00
Shannon fee23fac0a updates deep clone to have the false flag for resetting properties (we don't want to remember them when cloning)
Conflicts:
	src/Umbraco.Core/Models/Member.cs
2014-04-17 18:54:55 +10:00
Shannon cf6775ec31 moves an internal class 2014-04-17 18:05:12 +10:00
Shannon 1a13366cc9 Working on U4-4701 Fixup DataTypeService and repository with cache - the deletion logic all now happens in the transaction before it was done quite poorly for updating content types :( 2014-04-17 18:03:34 +10:00
Shannon 595b039ebe Working on U4-4701 Fixup DataTypeService and repository with cache, pre-values are now persisted properly using units of work with it's own mini internal repo. 2014-04-17 17:41:08 +10:00
Shannon e6406e9757 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-04-17 14:23:52 +10:00
Shannon bf65bf5bab Got pre-values caching properly and data types using the runtime cache provider correctly + unit tests. 2014-04-17 14:23:37 +10:00
Stephan 306d83cbd6 Bugfix published content extension .Next() 2014-04-16 19:04:49 +02:00
Stephan 1da901be96 U4-4575 - refactor prop. conversion logic 2014-04-16 18:25:41 +02:00
Shannon d953966248 Completes: U4-4670 Add .ContainsAny string extension to Umbraco.Core.StringExtensions 2014-04-16 17:01:26 +10:00
Shannon 2f679a52f4 fix build 2014-04-16 16:52:45 +10:00
Shannon ad8ab9f46e Fixes media uploader issue to ensure non-approved file types are not saved 2014-04-16 16:48:52 +10:00
Shannon 9b344a5a69 Added tests for member groups and member cloning. Added tests to verify that all entities can be serialized without issue. 2014-04-16 16:44:08 +10:00
Shannon 0a28bdafc2 Merge remote-tracking branch 'origin/6.2.0' into 6.2-cachefixing 2014-04-16 15:54:37 +10:00
Shannon 7aa1f480c9 Fixes up some cloning with value types and collections 2014-04-16 15:33:21 +10:00
Shannon 998f031877 Merge branch '6.2.0' into 6.2-cachefixing 2014-04-16 14:01:38 +10:00
Shannon ac7cb8febe Fixes cache providers to ensure it stores and resolves clones 2014-04-16 14:01:26 +10:00
Shannon 6e166bdba7 publicizes DeepCloneHelper 2014-04-16 13:40:20 +10:00
Shannon 1f2e46a195 Simplifies much of the deep cloning with the DeepCloneHelper and adds tests 2014-04-16 13:39:42 +10:00
Shannon bb22f5a283 More code and tests written for deep cloning. 2014-04-16 11:23:00 +10:00
Shannon dcac5d4709 More code and tests written for deep cloning. 2014-04-15 20:31:32 +10:00
Shannon 0e4e12d0ba More code and tests written for deep cloning. 2014-04-15 19:12:42 +10:00
Shannon 9118701669 More test written for deep cloning. 2014-04-15 14:53:19 +10:00
Shannon 58758e7a41 More work on deep cloning, have test passing for IContent 2014-04-15 13:52:49 +10:00
Sebastiaan Janssen 4a516f7da9 Manually applying PR #347 2014-04-07 13:01:43 +02:00
Sebastiaan Janssen bf8add4f8d Manually picked up PR #343 2014-04-03 11:10:43 +02:00
Stephan 9940b78a57 U4-4575 - fix 8371105 2014-04-02 17:00:24 +02:00
Stephan 8371105c10 U4-4575 - property converters use wrong source value 2014-04-02 16:00:46 +02:00
Sebastiaan Janssen 53c0bd6938 Fixes: Password is not saved when using the Register snippet 2014-04-02 11:59:16 +02:00
Sebastiaan Janssen a768fe5bb3 Ports behaviour from membershiphelper from v7 to 6 to make them the same 2014-04-02 11:42:48 +02:00
Sebastiaan Janssen d9c66cd4b3 Adds AddRelation and missing events in RelationService from v7 into v6 2014-04-02 11:41:59 +02:00
Sebastiaan Janssen 5b693f9310 Adds ability to add/remove a single role to/from a single member, which is much nicer than having to instantiate arrays 2014-04-01 16:43:11 +02:00
Sebastiaan Janssen 40ebc1295c Fixes error thrown when saving password and actually using the Umbraco membership provider 2014-04-01 15:30:42 +02:00
Sebastiaan Janssen 51660d918c Assembly redirect seems to help a lot installing NuGet pkg, should finally be able to close U4-4510 nuget targets file creates an invalid path in the property group 2014-04-01 14:22:13 +02:00
Sebastiaan Janssen 15aa6fc4b8 Fixed U4-4576 7.0.4 : InternalMemberSearcher config incorrectly uses 'enableLeadingWildcards', should be 'enableLeadingWildcard' 2014-04-01 11:53:56 +02:00
Shannon b9088c9ac0 fixes build 2014-03-28 08:51:25 +11:00
Shannon 49cf0f98ce U4-1752 - Add GetPreValueAsString(id) method to the @Umbraco helper 2014-03-28 08:31:21 +11:00
Shannon d8a3e00440 Fixes: U4-2843 Copying Document Type when Selecting Master Doesn't Work (Master ignored), U4-3552 Copy nested document type is failing 2014-03-27 17:26:55 +11:00
Shannon c309e18f13 Fixes: U4-459 Public Access permissions not set on distributed servers 2014-03-27 16:11:34 +11:00
Shannon cde3c42cec Fixes: U4-4455 Javascript error with single quotes in literals
Conflicts:
	src/Umbraco.Web.UI/umbraco_client/Editors/EditScript.js
2014-03-26 13:34:26 +11:00
Sebastiaan Janssen f13ddddc16 U4-4510 nuget targets file creates an invalid path in the property group
That should fix this one properly now
2014-03-25 20:39:46 +01:00
Sebastiaan Janssen 89235f707c Sync the en and en_us translations 2014-03-24 17:25:31 +01:00
Sebastiaan Janssen a569796adb Removes stray semicolons from the nuget targets files 2014-03-24 14:00:12 +01:00
Shannon 81600f0f3c Merge branch 'patch-2' of https://github.com/designagencytom/Umbraco-CMS into designagencytom-patch-2
Conflicts:
	src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs
2014-03-24 11:18:11 +11:00
Shannon 74ccd79408 Merge branch 'patch-1' of https://github.com/designagencytom/Umbraco-CMS into designagencytom-patch-1 2014-03-24 11:13:07 +11:00
Sebastiaan Janssen 424ff02734 Forgot a few includes, fixed! 2014-03-20 17:29:16 +01:00
Sebastiaan Janssen 80bd8d962b Make sure the App_Plugins folder is there 2014-03-20 16:58:35 +01:00
Sebastiaan Janssen 956364decd v7 NuGet changes also apply to v6 2014-03-20 16:02:24 +01:00
designagencytom 6133e8f8c2 Update loadMemberGroups.cs
Sort the roles alphabetically to make it easier to manage the list when it becomes very large.
2014-03-20 13:02:25 +00:00
Shannon bcb7561e74 fixes unit test 2014-03-20 17:44:13 +11:00
Shannon 83f4c0262e Fixes: U4-4475 Creating new member doesn't put it in examine. Fixes up some cache refreshers to ensure they are calling the base method so that events fire consistently.
Conflicts:
	src/Umbraco.Web/Cache/UserPermissionsCacheRefresher.cs
2014-03-20 12:38:19 +11:00
Shannon 15222e176e Fixes: U4-4474 YSOD when expanding Members tree 2014-03-20 10:37:54 +11:00
Shannon 84dd7dc61a Fixes: U4-4466 6.2-beta - Creating Member Type without Alias results in no viewable Member Types in back office 2014-03-20 09:52:31 +11:00
Shannon ff5dadde53 Fixes unit test and another potential migration problem using an old alias for foreign key 2014-03-19 18:43:10 +11:00
Shannon ded82611a7 Finalizes: U4-4472 Image cropper should use IFileSystem - currently uses standard IO 2014-03-19 15:09:50 +11:00
Shandem 6a8cb5e123 Merge pull request #270 from stefana99/6.2.0-imagecropper
Changes to imageCropper, supports new mediafilesystem
2014-03-19 14:48:38 +11:00
Shandem 09428d703c Merge pull request #298 from KevinJump/6.2.0--PackageServiceFixes
6.2.0  package service fixes
2014-03-19 14:43:19 +11:00
Shannon a0541b000e Fixes: U4-4463 Upgrade 6.2.0 > 7.1.0 fails - due to incorrect formatting of foreign keys for sql servers
Conflicts:
	src/Umbraco.Tests/Migrations/AlterMigrationTests.cs
	src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs
2014-03-19 10:33:37 +11:00
Shannon 668935548d Fixes: U4-4394 7.0.4: Inconsistency in member tree listings
Conflicts:
	src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs
	src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs
	src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
	src/Umbraco.Web/Trees/MemberTreeController.cs
2014-03-19 09:28:13 +11:00
Shannon 14141fcaa5 Fixes the dictionary query syntax properly for all db's 2014-03-19 09:24:57 +11:00
Sebastiaan Janssen 7c5942b05f Updating minimum required versions of dependencies to be the same as v7. 2014-03-18 18:40:20 +01:00
Sebastiaan Janssen 8b4d4e3189 Update readme and remove non-functioning backups from install.ps1 2014-03-18 18:38:16 +01:00
Sebastiaan Janssen 4f008f5848 Bump version to RC 2014-03-18 18:37:42 +01:00
Sebastiaan Janssen 1a40ccc838 Updating nuget targets files, like on v7. Also updates nuget author name. 2014-03-18 17:51:33 +01:00
Stephan e80963093d Fix MySql dictionary issue
Conflicts:
	src/umbraco.cms/businesslogic/language/Item.cs
2014-03-18 12:44:32 +01:00
Shannon 0749124f45 fixes bug with col name 2014-03-18 20:11:22 +11:00
Shannon bef970437a doh, fix for new ctor 2014-03-18 19:39:17 +11:00
Shannon dda36f0147 added additional ctor for member to create an empty one 2014-03-18 19:30:54 +11:00
Shannon caad775399 Removes the User membership provider name constant - it is not a constant, this value is configurable! 2014-03-18 18:52:17 +11:00
Shannon 7a7720c460 Gets #U4-4454 Can't log in a new member created through memberservice completed 2014-03-18 18:41:18 +11:00
Shannon b2aeb835d5 Implements the SavePassword method of the MemberService 2014-03-18 17:45:11 +11:00
Shannon 8dd950bd52 Ensures all access to the users membership provider is done with our extension method 2014-03-18 17:22:25 +11:00
Shannon e2881e07d1 Ensures that all calls to the members membership provider are done so explicitly with the membership provider alias - this decouples the need to have the umbraco membership provider declared as the default, we were doing both before. 2014-03-18 17:08:21 +11:00
Shannon 71de4dc7de Fixes: U4-3675 [NonAction] attribute should be ignored by Umbraco RenderActionInvoker 2014-03-18 14:28:05 +11:00
Shannon e22476f54a fixes some test logic 2014-03-18 14:19:26 +11:00
Shannon 20ae16b2d7 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-18 14:18:50 +11:00
Shannon 9e466971af fixes some test logic 2014-03-18 14:18:34 +11:00
Stephan 3c6029c969 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-03-17 15:27:25 +01:00
Stephan a4a0de3503 U4-4373, U4-4374 - finalize fixes 2014-03-17 15:25:25 +01:00
Shannon 217267bf94 Supercharges integration tests - now running at a great speed. 2014-03-17 22:22:44 +11:00
Shannon 4748366766 Fixes up some more test attributes 2014-03-17 20:59:31 +11:00
Shannon ab00782d84 Fixes potential issue with why test were failing 2014-03-17 20:33:30 +11:00
Shannon d19d1b3a18 Changes database behavior in integration tests to be opt-in, removes the db behavior to have a new schema per fixture, now we only deal in new files + schema per fixture/tests as it was taking longer to uninstall the db tables than just delete the file. 2014-03-17 19:38:29 +11:00
Shannon 30cfa4c0ae moves MemberCountType to correct namespace 2014-03-17 14:18:38 +11:00
Shannon d028ee2c3e Completes: U4-4457 Upgrade to latest CDF 2014-03-17 14:08:07 +11:00
Shannon a60e2318ad Fix Null Prevalue Values on Export of DataTypes
Exporting a DataType that has a Numeric pre-value that has no value
causes an Exception - added null checking to pre value.value
2014-03-17 13:23:26 +11:00
Shannon f642a7fd63 Fixes: U4-4368 Cannot insert the value NULL into column 'name' when creating new relation type from API 2014-03-17 13:21:17 +11:00
Shannon d1d54d8e84 Fixes: U4-4427 Exception with selecting content start node in Multi-node tree picker 6.2.0 2014-03-17 13:12:08 +11:00
Shannon bbeedb6c1b Fixes: U4-4373 @Library.NodeById(-1).Id returns "0" instead of "-1"(6.2.0 beta) & U4-4374 @Model.NodeById(-1).DescendantsOrSelf().First().Id results in Excecption (6.2.0 beta) 2014-03-17 12:27:37 +11:00
Shannon 4745995f92 Fixes: U4-4373 @Library.NodeById(-1).Id returns "0" instead of "-1"(6.2.0 beta) 2014-03-17 11:45:42 +11:00
Shannon c66aca2d41 Adds migration to rename the index umbracoUserLogins_Index to IX_umbracoUserLogins_Index so that it follows standards, fixes unit test 2014-03-17 11:24:01 +11:00
Shannon af148a4544 reverts the notion of shema migration - we will run migrations normally as we've been doing, this fixes a couple of unit tests too. 2014-03-17 10:48:56 +11:00
Shannon d7ea8e02d6 fixes unit test 2014-03-17 09:40:28 +11:00
Shannon 58814d4ac2 updates the migration order 2014-03-15 20:11:42 +11:00
Shannon bd1dc4f88d Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-15 18:53:25 +11:00
Shannon 67c1cc44c5 oops, fixes some logic with a closing bracket in the wrong place 2014-03-15 18:53:03 +11:00
Morten Christensen b680f87c12 Adding a note about the usage of the PackageInstallation class in the PackagingService 2014-03-14 12:14:43 +01:00
Morten Christensen 8db6633c91 Initial implementation of a new package installation approach based on PR-297. Everything is left internal as we don't know when something like this can be introduced.
Idea is to be able to install a complete package using the PackagingService, so that we eventually can obsolete the old Packager/Installer-code.
2014-03-14 12:11:38 +01:00
Shannon 3e5128147c fixes typo 2014-03-14 19:34:09 +11:00
Shannon b5329ace3b Backports fixes for legacy encoding checks and to not do any db lookups for the new membership providers and also ensures the legacy membership provider doesn't do any db lookups on init. 2014-03-14 18:38:57 +11:00
Shannon e1a134f587 Fixes: U4-4430 MySql primary key issues 2014-03-14 17:11:21 +11:00
Shannon bbe6194b06 Exception is thrown if trying to run mysql in med trust. Migrations arranged to execute schema migrations first and then data migrations. If a schema migration fails it will attempt to run the downgrade scripts of the migrations if running mysql since schema changes aren't supported in transactions. Updated all sql syntax providers to try to return only the column indexes, not key indexes. Updates the db version checker to include errors for all missing columns, indexes and constraints in the db and vice versa in the schema. 2014-03-14 13:04:20 +11:00
Shannon d76fd7d25e updates schema result to have case ignored. 2014-03-13 20:45:07 +11:00
Shannon e020989577 Give some love to mysql with regards to schema validation and the syntax provider - need ignore case comparisons. 2014-03-13 20:42:57 +11:00
Shannon 7258964bb7 Ensures version specific db providers are not referenced in the web.config 2014-03-13 20:14:11 +11:00
Shannon bcc2424577 fixes issue with getting 'other' 'members 2014-03-13 18:43:16 +11:00
Shannon 221bfa5f3d Fixes up issues with editing the member profile and registering a member with our snippets including specifying a custom member type. 2014-03-13 14:10:05 +11:00
Shannon 85a74e4fa7 Fixes: U4-4419 TempData is not being cleared on RedirectToCurrentUmbracoPage - it actually shouldn't be cleared but we need to handle how we add it properly as tempdata only clears when it is read 2014-03-13 12:21:31 +11:00
Shannon a8858ecfdd fixes unit tests 2014-03-13 11:10:29 +11:00
Shannon 0dc00a62e2 Adds ability to have proxy migrations so there is no duplication of declaring migrations and no duplication of executing already executed migrations. Would have been a bit nicer to have 2014-03-12 20:36:40 +11:00
Shannon 3b26834484 updates migration to make it a little faster 2014-03-12 18:40:39 +11:00
Shannon aee10348e5 Ensures not to add new indexes if they already exist 2014-03-12 18:37:22 +11:00
Shannon d0fc3ddba5 ensures applicationeventsresolver is disposed of in the correct place. 2014-03-12 18:11:05 +11:00
Shannon 3aadca167f oops, updated the reset to resetcollections for clearing collections for resolvers. 2014-03-12 18:00:00 +11:00
Shannon 3a92c26a7f Adds ability to extract index details from databases using sql syntax provider. 2014-03-12 17:17:52 +11:00
Shannon ff21379547 Makes ApplicationEventsResolver IDisposable so we can clear resources after startup. 2014-03-12 14:16:52 +11:00
Shannon aed4c1faed minor code cleanup and a null check. 2014-03-11 17:26:14 +11:00
Shannon 48bbf1ecb2 Fixes unit tests 2014-03-11 15:02:23 +11:00
Shannon c500d29029 adds some exceptions 2014-03-11 14:44:18 +11:00
Shannon 2c8fe5a130 fixes a few issues 2014-03-11 14:35:49 +11:00
Shannon d737afa327 Working on 2014-03-11 14:23:51 +11:00
Shannon ec6cb4520c Fixes: U4-3835 U7(nightly214) - Umbraco.Field not working 2014-03-10 17:44:40 +11:00
Shannon 3626d5b79d fixes unit tests 2014-03-10 17:27:22 +11:00
Shannon 980e8e84a6 Fixes: U4-4353 You are able to create duplicate content/media/member type's with the same alias 2014-03-10 17:26:04 +11:00
Shannon fb764641c5 Fixes: U4-4335 It's Possible to Create Duplicate Data Types 2014-03-10 15:16:17 +11:00
Shannon b94cee68e7 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-10 11:23:06 +11:00
Shannon b67fbbcbd8 Fixes: U4-4015 Usercontrol Browse Properties error 2014-03-10 11:22:49 +11:00
Sebastiaan Janssen 4d3eef1124 Update version 2014-03-07 15:25:10 +01:00
Shannon 3e6e6faf03 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-07 20:08:22 +11:00
Shannon b3f18bc677 fixed an issue with setting password with legacy api 2014-03-07 20:08:10 +11:00
Sebastiaan Janssen a48fe40675 Also clean up v6 snippets 2014-03-07 09:46:45 +01:00
Shannon 1511ad58b2 oops, put back the defaults for umbracoSettings 2014-03-06 20:16:55 +11:00
Shannon 2e9b751174 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-06 20:12:21 +11:00
Shannon d61ab97be3 Fixes: U4-4217 Ensure that the cmsTask data is cleared for any entity that uses umbracoNode table 2014-03-06 20:12:05 +11:00
Stephan dd40d73b71 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-03-06 10:06:50 +01:00
Shannon 068bca84b7 Fixes: U4-156 Drag / drop support 2014-03-06 20:05:13 +11:00
Shannon 0fda528b94 Fixes: U4-1550 Publish notifications on a load balanced environment 2014-03-06 19:47:23 +11:00
Shannon 3552f63d87 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-06 19:29:35 +11:00
Shannon 01d04fde37 Fixes: U4-4060 Rollback feature does not show differences 2014-03-06 19:29:09 +11:00
Stephan 7f8c526136 Fix TryConvertTo handling of number decimal separator 2014-03-06 09:14:05 +01:00
Stephan ea4be14f0c Fix 026d040 - keep Standalone stuff internal 2014-03-06 09:10:14 +01:00
Stephan 20df48e2f0 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-03-06 08:49:38 +01:00
Stephan 2c0f6f975c Bugfix UmbracoEntity ctor test 2014-03-06 08:42:41 +01:00
Shannon fa7f91b39d Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-06 18:26:10 +11:00
Shannon 72c5853fb1 Completes: U4-3937 Ensure media is indexed across all servers in LB environment with Distributed Cache calls
for members
2014-03-06 18:25:38 +11:00
Stephan f03b1a22f9 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-03-06 08:12:51 +01:00
Shannon e7fb6e5beb Streamlines member and user services CreateMemberWithIdentity to be similar to media/content and not have a raise events flag. Also implements the CreateWithIdentity explicitly 2014-03-06 18:07:02 +11:00
Shannon d0cc93d6a2 Fixes: U4-3937 Ensure media is indexed across all servers in LB environment with Distributed Cache calls
This fix is for media indexes to be distributed properly and for unpublished content to be distributed properly, now to get members to do the same.
2014-03-06 17:50:08 +11:00
Shannon 4adc2562b1 Fixes issue with ugolive dashboard trying to load in knockout from a bundle which causes the examine mgr to fail 2014-03-06 17:49:09 +11:00
Shannon ba6878666c Fixes pretty ugly issue of the Saving/Saved events not being raised when using CreateWithIdentity 2014-03-06 17:35:47 +11:00
Stephan 792ab8d088 Introduce support for content fragments 2014-03-05 15:46:37 +01:00
Stephan 3d4409e52a Refactor CacheRefreshersResolver.CacheResolvers into .CacheRefreshers 2014-03-05 15:46:35 +01:00
Stephan acd377956f Improve how DomainHelper determines domain 2014-03-05 15:46:34 +01:00
Stephan 3b6dcc3421 Factor Dictionary.ReplaceKey method 2014-03-05 15:46:33 +01:00
Stephan cec4d41df7 Add comments to UmbracoViewPageOfTModel 2014-03-05 15:46:32 +01:00
Stephan ff0bcffefa Implement DefaultShortStringHelper.PostFilter to cut url segments at 240 chars 2014-03-05 15:46:31 +01:00
Stephan 5dbc72897a Add method to reset PublishedContentRequest template 2014-03-05 15:46:30 +01:00
Stephan 83736bec01 U4-4190 - enable retrieval of wildcard domains 2014-03-05 15:46:29 +01:00
Stephan 2f953c3819 Fix a38e0dc - use UInt64 instead of int 2014-03-05 15:46:28 +01:00
Stephan 026d040a62 Enable StandaloneApplication to work with Powershell 2014-03-05 15:39:16 +01:00
Stephan 7747b8f64f U4-3579 - support chars such as <, > or & in prevalues 2014-03-05 15:33:15 +01:00
Shannon feb9f40237 updates some ctors on umbraco context and routing context to have lazy overloads which allows us to more easily create/mock the umbraco context. 2014-03-03 04:16:09 +01:00
Shannon 651182f5de Fixes sql statement - to be like we have in v7 that supports all sql servers 2014-02-25 02:37:48 +11:00
Shannon 22b15a06f6 Fixes how member is approved is set by defaut and adds unit test for it. Also ensures that it returns true if the property value is invalid for whatever odd reason. 2014-02-25 02:10:25 +11:00
Shannon cb09795280 Removes new member service Creating event, as only Created makes sense. Deprecates the other 'Creating' events with a note to just use the Created event. 2014-02-25 01:45:41 +11:00
Sebastiaan Janssen a5637af2d8 Adding missing CreateMember method that also as a convenience allows you to pass in the member type alias instead of a whole membertype 2014-02-22 18:32:26 +01:00
Sebastiaan Janssen ac59c5deb0 Fixing some potential upgrade issues and two issues found with the legacy member API
- For legacy API we never had and "approved" checkbox, so the assumption is that members are always approved
- The RequiresUniqueEmail check was wrong, previously the assumption was: if there's no e-mail then don't check for uniqueness
2014-02-22 16:44:02 +01:00
Sebastiaan Janssen 683ddf6d34 Apparently we rely on <error404>1</error404> to be in umbracoSettings.config 2014-02-22 16:03:59 +01:00
Sebastiaan Janssen eda33b1ac4 Update incorrect summary 2014-02-22 14:47:59 +01:00
Sebastiaan Janssen ed0f884348 Been a while: properly syncing /config/*.config with /config/*.Release.config 2014-02-21 17:50:58 +01:00
Sebastiaan Janssen b561351340 Update UI.Release.xml with the correct Partial View references 2014-02-21 17:33:19 +01:00
Sebastiaan Janssen 690ab29863 Use the database "agnostic" query for this (see U4-3876) 2014-02-21 17:01:59 +01:00
Shannon 27cb1d5223 completes: U4-4275 Hide built-in member type properties from the insert umbraco field list 2014-02-21 16:20:07 +11:00
Shannon c677f36f08 Changes some of the naming conventions for the underlying membership provider services bits. 2014-02-21 16:03:32 +11:00
Shannon 750f7a6b33 Updates some method names to be less confusing regarding permissions 2014-02-21 15:55:56 +11:00
Shannon dea804b402 fixes some permission logic and a unit test 2014-02-21 15:46:39 +11:00
Shannon 3803d1d7da fixes reflected property on dynamicnode and unit test 2014-02-21 15:22:02 +11:00
Shannon 3e67b3034d Added the ability to specify explicit db type's for a property type using an overloaded ctor argument. This allows us to specify explicit db types for properties without having them get overwritten during the repository saving logic which will always reset it to be the db type of the underlying property editor. In the case of our built-in membership properties we do not want this to happen. Fixes some unit tests. Removes built-in props from being included in the property types on the profile model on the front-end. 2014-02-21 12:56:00 +11:00
Shannon 1ada5210ad updated to latest examine 2014-02-21 09:54:53 +11:00
Shannon 9a608674eb fixes another test 2014-02-20 23:11:27 +11:00
Shannon 7dae412a29 fixes most of the newly failing unit tests and adds better null checking 2014-02-20 23:00:04 +11:00
Shannon b7f7775b89 adds initial commit of entity cloning 2014-02-20 22:34:54 +11:00
Shannon a1067e676f publicizes some repository factory methods and interfaces 2014-02-20 21:56:58 +11:00
Shannon ce649f54d7 Upgraded to latest examine, completes: U4-4240 Update with new examine version 0.1.53 2014-02-20 15:01:47 +11:00
Shannon d159792256 Updates last step of installer logic, we don't care about other providers as that would never have worked anyways 2014-02-20 14:38:00 +11:00
Shannon 606b5aa60a fixes logic in membershiphelper updatemember 2014-02-20 13:55:56 +11:00
Shannon a206652a0d updates login redirect logic to be more inline with v7, less greedy which is better. 2014-02-20 13:37:12 +11:00
Shannon 545040fdf0 Fixes installer upgrade 2014-02-20 13:09:54 +11:00
Shannon 40d1a09609 Updates the membership helper in how it updates the membership provider data, updates the editMember page to update the membership provider properties all via the membership provider 2014-02-19 23:49:53 +11:00
Shannon 2e25bc8fdb Moves all FindCOntrolRecursive calls to an extension method 2014-02-19 23:49:08 +11:00
Shannon 1618ac86b8 Adds implicit bool operator for Attempt, makes things nicer to check for success :) 2014-02-19 22:45:22 +11:00
Shannon a4adbca12c Removes the ability to edit the data type for a built-in membership property. Ensures that even if a data type is attempted to be changed with the API that the built-in properties are always persisted with the data type that we have defined by convention. 2014-02-19 21:56:33 +11:00
Shannon 8728e2f918 Fixes: U4-4260 When changing sort order on member type and saving, this doesn't get reflected on the member 2014-02-19 20:17:21 +11:00
Shannon cd53682ddb removes ability to configure custom fields for the new membership provider 2014-02-19 17:52:45 +11:00
Shannon e2d5fbf545 Fixes issue with ensuring properties on entities when a new property type has been created - but if the property type doesn't have an id, we should ignore it. 2014-02-19 17:27:08 +11:00
Shannon d339e7c814 updates the property type editability for built in member types 2014-02-19 16:57:33 +11:00
Shannon 078deb704b Completes: U4-4255 Add readonly membership provider properties to the profile model 2014-02-19 16:27:14 +11:00
Shannon 6858eb3330 Fixes: U4-4257 Fix member type editor to not have to re-call 'Save' so many times,
streamlines how the show property and editable property on member type's are dealt with (removes tuples)
2014-02-19 16:14:34 +11:00
Shannon e267b7700a Ensures that member properties are created when member type property type's are added (same as U4-1407), streamlines how this occurs on the base class. Streamlines how empty aliases are validated at the repo level for members, media, content. Makes built-in member property type's non-editable 2014-02-19 14:23:48 +11:00
Kevin Jump 366697f4eb PackageService: Fixes Single import for DataTypes
Importing a file with a single data type failed, because the DataType
element is at the root when exported.
2014-02-18 15:10:11 +00:00
Kevin Jump 987644379e Fix U4-4119 - Export Fails for Generic Properties
Adds null checking for PropertyGroupID on export so that properties with
no group (tab) don't throw an exception.
2014-02-18 15:07:47 +00:00
Shannon 1e45abe71e oops, changes the failedpassattempts back to noedit 2014-02-18 17:58:57 +11:00
Shannon a556b4ed21 Logs warnings if accessing built-in properties on the member model but the underlying property type is missing. 2014-02-18 17:53:02 +11:00
Shannon 953c711ca4 Updates the default member type property types to use "Labels", then needed to update the member type repo and membertypereadonlyfactory to ensure that even though the underlying data type for the property exposes a different Db Type that we 'reset' that Db Type to what it always should be. This means that no matter what underlying data type a developer changes a property to, if it is a built-in membership property, the Db Type will always stay consistent and save in the correct column. Of course if someone enters some invalid data, then the data will not be saved. 2014-02-18 17:19:38 +11:00
Shannon f06c9e8235 Ensures the default member type properties are put on a custom tab 2014-02-18 15:39:00 +11:00
Shannon f1a439e851 removes version specific references to mysql in the proj files and web.config
ensures that escaping in the sql expression classes is done correctly without any double escaping. Also ensures that escaping is happening using the equals operator, not just the Equals() method and adds unit tests for them.
Fixes: U4-4232 Umbraco.Core.Persistence.Querying issue with backslashes
2014-02-18 14:57:03 +11:00
Shannon a0e496e589 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-02-17 21:38:38 +11:00
Shannon e0dcc3afbc Streamlines how strings are escaped with the sql expression helpers and syntax providers. Fixes: U4-4232 Umbraco.Core.Persistence.Querying issue with backslashes 2014-02-17 21:38:13 +11:00
Stephan 3634a77d61 U4-4241 - UrlAbsolute() returns relative urls 2014-02-17 10:47:51 +01:00
Shannon 846f4b5b6c Removes the various old hacks for the legacy user's membership provider, now that we have the AllowManuallyChangingPassword flag, these hacks are not required. 2014-02-17 19:32:04 +11:00
Shannon 2869f17eff ensures the default property aliases are set during ctor 2014-02-17 18:02:29 +11:00
Shannon feefb052fd Updates the BulkInsertRecords method to optionally close the trans - shouldn't by default. Updates how permissions are handled in the new services and exposes another method, ensures it's all wrapped in trans and ensures that cache is cleared properly. Fixes: U4-4213 "Replace child node permissions" does not work if all permissions cleared 2014-02-17 17:45:59 +11:00
Shannon 4d2d9156ba updates more plugin manager defs 2014-02-17 15:58:57 +11:00
Shannon 82ba1a24a3 Ensures we perform null checks in both GetAll and GetByQuery as we never want to include a null item in the resultant collection - which could happen depending on what the sub class repository is doing.
Fixes: U4-3145 Cache file periodically becomes corrupted: "Oops: this document is published but is not in the cache (internal error)"
2014-02-17 15:45:36 +11:00
Shannon 357db9d0b6 completes: U4-3282 Expose permission assignment methods at the service layer 2014-02-17 15:33:17 +11:00
Shannon 61766287bc Cleans up some more of the old 'object' User Id references. 2014-02-17 15:26:38 +11:00
Shannon ffbf8b2fd6 completes: U4-4103 Publicize PluginManager for devs to use to create their own plugins 2014-02-17 15:08:27 +11:00
Shannon f7a703195c Fixes: U4-4215 Tree.config registeres tree inconsistently 2014-02-17 14:56:12 +11:00
Shannon 509be9b431 Updates the underlying UmbracoServiceMembershipProvider to deal with 'object' for provider key, this then lets us deal with either guid or int for the new membership provider, just like the old one does. 2014-02-17 14:14:17 +11:00
Shannon 10ef5eb7bc adds new interface for members' membership providers to implement so we know what aliases to store data against. 2014-02-17 13:16:28 +11:00
Shannon 2849ecadb7 fix legacy member wrapping new api and mixing email/login name 2014-02-17 12:24:11 +11:00
Shannon 697f93c3ce removes null check for LoginName, since it gets set to the name passed in if it is empty 2014-02-17 12:09:27 +11:00
Shannon 18121e8726 Enxures user start node's are -1 by default when creating the model. 2014-02-17 11:48:32 +11:00
Shannon 81cdc71145 Ensures new user objects are approved by default. 2014-02-17 11:17:15 +11:00
Shannon 4069fc8d1f fixes issue with legacy user.Password property and fixes comparison of sections 2014-02-13 17:19:28 +11:00
Shannon 0a80c39962 Fixes merge 2014-02-13 15:25:57 +11:00
Florian Verdonck edee8134c2 Updated request after feedback 2014-02-13 15:21:40 +11:00
Shannon 30a73c0886 updated web.config template to use new role provider. 2014-02-13 14:45:24 +11:00
Shannon f5ee02a3e9 Updates the membership partial view templates to redirect to current page by default but allows this to be overridden. Creates a new RedirectToCurrentUmbracoUrl method which is slightly diff from RedirectToCurrentUmbracoPage since it doesn't care about the actual page item rendering, just the currently rendered URL which is useful if coming from a rewritten URL (which is what happens with public access rewrites) 2014-02-13 13:30:32 +11:00
Shannon 9827b40bea Fixes: U4-4223 MVC based forms with SurfaceControllers don't work when rendered in Webforms mode.
This slightly changes how the routing works in the module, now we always send the request to the RenderRouteHandler, this will first process the logic for route hijacking, then it will determine if the request was found to be a WebForms template, if so then we'll return the webforms handler. This also now allows us to have POSTed values to SurfaceController's from forms that have been rendered in Webforms whilst maintaining all viewdata, tempdata and model state on postback even when rendering in webforms!
2014-02-13 13:19:51 +11:00
Stephan f9323c85e4 Fix issue with 9d7b3b96 in .designer.cs file 2014-02-12 13:22:35 +01:00
Stephan 2677672e50 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-02-12 13:22:30 +01:00
Morten Christensen a38e0dcf86 Adding integer overload for UmbracoEntity so it can be used with a dynamic object containing either a boolean or integer retrieved from the database to initialize the UmbracoEntity object. 2014-02-12 12:47:47 +01:00
Stephan fdd7227494 Fix DynamicPublishedContent to use CleanStringType.ConvertCase 2014-02-12 10:46:57 +01:00
Stephan 6b74e14cdd Backport DefaultShortStringHelper from 7.1 2014-02-12 10:40:00 +01:00
Shannon 9d7b3b965a fixes some issues with new bundles. 2014-02-12 18:19:20 +11:00
Shannon 806008a7e9 Fixes issue with @ symbols in login name and a member group query 2014-02-12 18:02:00 +11:00
Shannon 45fa192c95 Fixes some unit tests 2014-02-12 17:25:45 +11:00
Shannon 92235128f1 Got new MemberGroupService done, completed the MemberService for role based stuff, created a member group cache refresher since we are caching member groups by name (probably should cache others too). Public access stuff changes if a name of a member group is changed which is now done with an event instead of coded into the biz logic. 2014-02-12 17:14:16 +11:00
Shannon 7622937cfd implemented remaining methods for member groups/roles + unit tests 2014-02-11 20:38:48 +11:00
Shannon bf41694572 Fixed up some more of the member group + member stuff with more unit tests 2014-02-11 19:21:36 +11:00
Shannon 7b897ce64c Member group repo updated along with the member service to support roles, etc... got first of many unit tests passing. 2014-02-11 12:43:55 +11:00
Shannon 1ca950f721 Starts creating the IMemberGroupService and supporting classes. 2014-02-10 19:48:16 +11:00
Shannon ffba271fd0 Creates the MemberGroupRepository and supporting models. 2014-02-10 19:35:32 +11:00
Shannon ec08d3e910 Updates MembershipHelper to not change the email/name if the value has not changed. Updates the templates to show only validation summaries for their own values/prefixes. Fixes some underlying MVC methods that merge view state to ensure the prefixes work with validation summaries properly when not showing property level errors. Updates the Umb controllers to add model level validation msgs when failed. 2014-02-10 18:34:12 +11:00
Shannon 0bfd032fad Obsoletes the RedirectOnSucces on the RegisterModel as it is not needed. Adds RedirectUrl to the ProfileModel and updates the controller to redirect properly (ensures it doesn't just redirect to home!) 2014-02-10 16:46:45 +11:00
Shannon 2bb58b6fca Updates MembershipHelper to ensure that the membership provider is used when updating a profile, specifically to deal with unique emails. Updates the profile edit template to have correct validation procedures. 2014-02-10 16:22:15 +11:00
Shannon 4d2d656b3d Moved ChangePassword method to MembershipHelper and makes it public, adds an overload. 2014-02-10 14:29:29 +11:00
Shannon fa625d72f9 updates some comments 2014-02-10 14:12:44 +11:00
Shannon 1991380e02 Changes CDF version to be the hash code of UTC now 2014-02-10 13:53:12 +11:00
Shannon 3b8d6dc2c7 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-02-10 13:50:43 +11:00
Shannon 1faeb76c27 Removes the need for duplicate templates for partial views. Of course we can have partial view only templates if necessary but currently we just borrow them from the partial view macros and update the header 2014-02-10 13:50:31 +11:00
Sebastiaan Janssen 3a513668fd U4-4185 Log fails to show unicode (cyrillic) characters 2014-02-05 15:52:20 +01:00
Stephan 3ef51d7357 U4-2317 - issue with domains & languages management 2014-01-30 16:18:06 +01:00
Stephan 8b553dd067 U4-4144 - work around media cache exceptions on invalid properties 2014-01-29 19:30:17 +01:00
Shannon ccaf82d797 Fixes object extensions for dates with a 'kind' specified. 2014-01-29 11:21:35 +11:00
Shannon f28ae52ae3 moved logic to update a profile to MembershipHelper. 2014-01-28 21:57:00 +11:00
Shannon cfd0973f00 Moves the registration logic to the MembershipHelper, fixes up the views to keep the indexes so props save. 2014-01-28 21:42:30 +11:00
Shannon 1bfdd83ba7 Cleans up more of the membership controllers and snippets to be using the membership helper and fixes up a few issues 2014-01-28 19:41:21 +11:00
Shannon 6fefcacc61 Adds more methods to the MembershipHelper, updates the RegisterModel and obsoletes the standard ctor so biz logic is not happening in the model, updates the snippets to use the correct way. Fixes an issue in the membership repo for persisting new members when the member type doesn't contain all the built-in props. 2014-01-28 18:59:27 +11:00
Shannon 3b639e61b2 Exposes MembershipHelper onthe UmbracoViewPage so people can use it directly in views. 2014-01-28 17:02:20 +11:00
Shannon 9959ff667e publicizes MembershipHelper and exposes it on the various base classes: SurfaceController, UmbracoApiController and UmbracoUserControl as the property "Members", will add more helper methods. 2014-01-28 16:58:55 +11:00
Shannon de1f86c7a1 adds logic to the membership helper to create a new LoginStatusModel with the values filled in, obsoletes the empty ctor on LoginStatusModel since that does some biz logic lookups, instead replaces it with a static method to create an empty one. 2014-01-28 16:30:58 +11:00
Shannon 28d8fd0531 Changes LoginStatusModel to use the correct api and updates the new membership provider stuff to ensure that the provideruserkey is the int id of the model for backwards compatibility. 2014-01-28 16:13:05 +11:00
Shannon e4e76eb0bf Backports commit: Prefixed built in controllers to better avoid conflicts with people's custom code
Conflicts:
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/EditProfile.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Login.cshtml
	src/Umbraco.Web/Controllers/UmbLoginController.cs
	src/Umbraco.Web/Controllers/UmbLoginStatusController.cs
	src/Umbraco.Web/Controllers/UmbProfileController.cs
	src/Umbraco.Web/Controllers/UmbRegisterController.cs
	src/Umbraco.Web/Umbraco.Web.csproj
2014-01-28 13:47:16 +11:00
Shannon 677cc8c8fd Fixes ProfileController to use normal .Net APIs and the new members service - also removes the Response.Redirect that was in there, why was it like that? 2014-01-28 13:35:43 +11:00
Shannon 3fa5c4e0b2 Updates RegisterController with the standard ASP.Net APIs to create and login a member. 2014-01-28 13:21:30 +11:00
Shannon 360393c464 Fixes LoginStatusController to use the standard ASP.Net APIs 2014-01-28 13:07:25 +11:00
Shannon d3daf88a8d Fixes the LoginController to use the correct APIs 2014-01-28 12:58:22 +11:00
Shannon 7a99ebd6d9 Starts the implementation of the new role provider. 2014-01-28 12:48:41 +11:00
Shannon a7298e2e5a Completes: U4-4148 Anytime RuntimeCacheProvider or InMemoryCacheProvider is used, a cache refresher will need to handle it's distribution! 2014-01-28 12:20:10 +11:00
Shannon 15d7443c61 Streamlines the content type cache refreshing, leaving some of the legacy cache clearing but that shouldn't really have an effect, with these new changes it should be guaranteed that the distributed cache is executed always for Doc, media and member types. 2014-01-28 12:13:27 +11:00
Shannon f2b7e27b34 Fixes: U4-2721 RuntimeCacheProvider is not cleared when data type changes and updates the repo factory to not use the InMemory cache provider since we should only ever use that for very very specific reasons since the memory can never auto-clear with that provider. 2014-01-28 11:30:02 +11:00
Shannon 690d08aa8c Completes wrapping the new IUserService from the legacy User object. Ensures User cache is handled correctly and distributed cache is updated for Users. 2014-01-28 10:46:59 +11:00
Shannon 6719d70cc0 Updates UserTypeCacheRefresher to clear the runtime cache accordingly. 2014-01-28 09:22:01 +11:00
Shannon 3cdcf513ec removes ancient test project 2014-01-28 09:00:17 +11:00
Shannon 43c426b46c Update booting.aspx
Throw the exception immediately if the parameter is not there or empty.

If the parameter is not there it's defaulted to the current url, and this will redirect to itself and create an endless loop here.
2014-01-24 12:36:02 +11:00
Shannon e2ac82abca Gets most of the User and UserType legacy objects wrapping the new services, yay! Now just need to sort out all the caching stuff which I have tasks for. 2014-01-23 18:44:41 +11:00
Shannon 64d1a484bd Fixes User Id issues with HasIdentity, wraps legacy UserType to the new service, fixes the uninstalling db schema to not throw exceptions and clog up the unit test log. 2014-01-23 17:11:58 +11:00
Shannon 585b42af48 More Save()'s missing and removes the extra calls to XmlGenerate - should save some processing time. 2014-01-23 16:13:29 +11:00
Shannon 7c4412fc4b Ensures that Save() is called wherever member data is saved 2014-01-23 16:09:59 +11:00
Shannon 0be8039c8f Changes how IProfile works which is now just exposed by the IUser instead of implemented, this cleans up the Id situation. 2014-01-23 15:31:49 +11:00
Shannon 668265f1ac Allows forcing pass change with new provider, updates conventions to not allow editing of question/answer - unfortunately cannot make the other ones readonly because noEdit data type is the wrong clr type. 2014-01-23 15:11:54 +11:00
Shannon 4735f27a66 Fixes more naming conventions with CreateMemberWithIdentity, fixes memberTasks to ensure the name is set, fixes new membership providers which had the name/email call reversed. Updates the cache refresher event handler to listen to MemberService events instead of the old legacy API events. 2014-01-23 14:55:41 +11:00
Shannon 6377b9aa50 Fixes some underlying type conversions, fixes more of the member type wrapping, updates contenttypecontrolnew to work with member types properly, ensures the property type cache is cleared when member types change. 2014-01-23 13:33:58 +11:00
Shannon 011be60205 Finishes wrapping the member service and fixes a few bugs - ensures the RepositoryBase doesn't keep enumerating when getting all 2014-01-23 12:30:28 +11:00
Shannon a272675ed8 Wraps the MemberService from the legacy Member object 2014-01-23 11:41:01 +11:00
Shannon 80697cf9ca MemberType fully wraps new MemberTypeService 2014-01-23 10:57:24 +11:00
Shannon f4534aa94c adds unit tests for member type can view/can edit properties 2014-01-23 10:55:22 +11:00
Shannon 56dec485a5 Starts wrapping MemberTypeService from the legacy MemberType object. Changes the User.Id to an int - no more casting. Changes CreateMember to CreateMemberWithIdentity for consistency. Adds raiseEvent params to the create/save methods. Updates the MemberTypeService to have consistent naming conventions. Starts wrapping more of the MemberService from the legacy Member object. 2014-01-23 10:41:57 +11:00
Shannon ffde0f48cf Starts wrapping MemberTypeService from the legacy MemberType object. Changes the User.Id to an int - no more casting. Changes CreateMember to CreateMemberWithIdentity for consistency. Adds raiseEvent params to the create/save methods. Updates the MemberTypeService to have consistent naming conventions. Starts wrapping more of the MemberService from the legacy Member object. 2014-01-23 10:35:30 +11:00
Shannon 2956aee4e3 Fixes: U4-4108 The backoffice should not be accessible when the app is not configured, it should redirect to the installer and U4-4106 Set the new membership providers to be shipped as default. 2014-01-22 15:26:45 +11:00
Shannon 9bd8d729fa publicizes user stuff, changes the IUser.Id to an int - no need for it to be an object and casted everywhere. Updates the login logic to perform the mapping logic for custom membership providers with an extension method. 2014-01-22 14:07:18 +11:00
Shannon fb9569d914 Fixes user membership providers to throw exceptions on duplicate emails when the provider is configured to not allow duplicates. 2014-01-22 13:20:00 +11:00
Shannon 47974d49fe obsoletes old providers, creates new membership role provider stub 2014-01-22 12:16:47 +11:00
Shannon 3f8b3031c2 completes: U4-3996 Fix EditUser to use the membership provider properly, U4-3997 Fix EditMember to use the membership provider properly 2014-01-22 11:57:33 +11:00
Shannon 7da41594fd re-publicizes member services, fixes: U4-4102 Un-obsolete ContentService.Publish 2014-01-22 11:27:44 +11:00
Shannon 9796b30bbb Fixes: U4-4104 Using strongly typed Html.Action<T> with a PluginController causes exception 2014-01-22 11:02:24 +11:00
Shannon c2c4763faa Ensures username is escaped in user service 2014-01-20 16:11:38 +11:00
Shannon c062d3b71b Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-01-20 16:01:53 +11:00
Shannon ed83fb8216 updates user task creation for release 2014-01-20 16:00:19 +11:00
Stephan 326309e61e U4-4056 - better unicode/ascii support for urls 2014-01-16 17:09:21 +01:00
Shannon c38030def2 Fixes: U4-3855 Preview cookie should be a session cookie not persisted 2014-01-16 20:47:13 +11:00
Shannon 949861a890 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-01-16 20:03:52 +11:00
Shannon 122069752a fixes legacy validate member logic 2014-01-16 20:03:29 +11:00
Sebastiaan Janssen ae83b0fbaf Hardcoded empty snippets need to be updated as well.. 2014-01-15 21:07:24 +01:00
Sebastiaan Janssen 99e91a1053 U4-2737 Snippets that are available when creating new MacroScripts should also be available for Partial Views 2014-01-15 20:55:17 +01:00
Sebastiaan Janssen bad118ac6b U4-4046 Rename "empty template" to "empty" 2014-01-15 10:17:46 +01:00
Shannon 5c614a88a2 ensures webapi plugincontrollers are routed to /backoffice if [IsBackOffice] is specified 2014-01-15 13:29:17 +11:00
Shannon 3ef9635406 Fixes: U4-4010 Member and user session gets mixed - fixes how we detect a back office request + unit tests and added new IsBackOffice attribute 2014-01-15 13:17:38 +11:00
Shannon 75a42fd0d6 fixes the protect page logic 2014-01-15 10:42:01 +11:00
Shannon 84da5f43a2 U4-4045 The "Empty" partial view snippet should have @inherits 2014-01-15 10:41:37 +11:00
Shannon 000c2637d6 fixes view state and err msg 2014-01-14 16:54:32 +11:00
Shannon 563867cd8b Temp fix for: U4-3968 Umbraco 7.01 - Membership - Public Access - Add Single User protection - crash, fixes protectPage so that it uses the membership provider to make changes, updates the UI logic so that if you choose an existing user it will you about it, fixes it so you cannot arbitrarily change a member's password. 2014-01-14 16:21:00 +11:00
Shannon 86c66511dd changes all calls from Member.InUmbracoMemberMode() to Membership.Provider.IsUmbracoMembershipProvider() and obsoletes the InUmbracoMemberMode 2014-01-14 14:17:28 +11:00
Shannon 7d57521ad8 Fixes some thread safety issues with old membership API 2014-01-14 11:53:41 +11:00
Shannon e74e8f9d73 Fixes: U4-4005 Member custom properties not saving from code, only from backend, wraps more of the getter functions in legacy member class with new member service methods, fixes paged result method when there are no results. 2014-01-13 18:36:08 +11:00
Shannon 23b0c89848 ensures the mail usage is disposed. 2014-01-13 17:28:49 +11:00
Shannon aebc30c7a3 Removes the version specific info from the CDF and Examine references in all proj files. 2014-01-13 14:02:50 +11:00
Shannon 44bc365fdd Moves all notification sending logic to the notification service, improves performance during any action when notifications are to be sent, ensures emails are sent out async to not block up the current request. 2014-01-13 13:50:30 +11:00
Shannon 06defee410 Completed new NotificationService, moved Diff to Core 2014-01-13 13:05:25 +11:00
Morten Christensen 955573256d Updating the legacy Installer class to use the new methods in the PackagingService 2014-01-10 15:11:07 +01:00
Morten Christensen d963f5cd7d Updating a few methods that are made public in 7.0.2 2014-01-10 14:57:27 +01:00
Morten Christensen 2467b5ee3b Removing some internal experimental stuff that isnt used 2014-01-10 14:53:27 +01:00
Morten Christensen f86eb4b741 Adds import and export of languages along with tests 2014-01-10 14:48:55 +01:00
Morten Christensen 33b99073f0 Moving events out of the repository scope.
Adding Get Language by Iso Code method
2014-01-10 14:48:31 +01:00
Morten Christensen 880636c5a6 Adding languages xml to existing xml file for testing purposes 2014-01-10 14:47:31 +01:00
Morten Christensen 6e344f335e Adding Export of DictionaryItems including test 2014-01-10 13:08:33 +01:00
Morten Christensen 6b205bd725 Updates from PR#127 from Lars-Erik. Had to manually copy in the changes because the PR was closed.
Adds Import of Dictionary Items to the PackagingService along with tests and a fix for the DictionaryRepository.
2014-01-10 11:45:41 +01:00
Shannon 531306a091 Created notifications repository and service with unit tests, then need to start integrating that so notifications are properly sent. 2014-01-10 17:03:00 +11:00
Shannon 4346f73159 Fixes naming conventions from old Notification class 2014-01-10 15:13:25 +11:00
Shannon 4db6ce4b22 Fixes various issues relating to File Repositories and Services: U4-4014 FileRepositories offer no way to create folders, U4-4013 The models that the FileService produces causes security exceptions, U4-3993 Replace system.io calls in umbraco.scriptTasks legacy task
updates to latest CDF
2014-01-09 18:08:13 +11:00
Shannon 7c720460f5 Fixes: U4-3876 MySQL cmsContentXml Migration Error on 7.0.1 Upgrade 2014-01-09 10:33:35 +11:00
Shannon 961755336a adds another test for #U4-3876 2014-01-08 20:34:20 +11:00
Shannon e0aff8a1e4 adds a unit test 2014-01-08 20:25:35 +11:00
Shannon 6fa0c627a5 working on #U4-3876 2014-01-08 20:19:08 +11:00
Shannon 66a63b3cbb ignores these tests for now, they are successful when running isolated but as a whole they don't pass because of something with the legacy data layer. 2014-01-08 18:39:37 +11:00
Shannon 21c5b6fe02 fixes user lookup on legacy provider 2014-01-08 18:20:18 +11:00
Shannon ffed85640d fixes provider user key issue 2014-01-08 18:12:07 +11:00
Shannon cdbf89ee57 Fixes up the unit tests 2014-01-08 17:08:13 +11:00
Shannon 056b13eb98 fixes up the double member creation in the createuser method 2014-01-08 16:29:09 +11:00
Shannon 9467a67661 Backports the permissions repo updates, permissions on user/content repo updates and default permissions for users 2014-01-08 15:42:49 +11:00
Shannon 0f9f11bbcf re-internalizes some classes for now 2014-01-08 14:03:10 +11:00
Shannon 5b6cc51516 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-01-08 13:04:01 +11:00
Shannon 80b83ab64b Fixes up password changer on postback, fixes up more of the edit user and edit member pages. 2014-01-08 13:03:33 +11:00
Morten Christensen c6751f0374 Correcting the legacy template MakeNew private method so the OnNew event is fired after the design is added and file is created. 2014-01-07 13:24:05 +01:00
Morten Christensen d71c686aea Typo or missing update in legacy User class 2014-01-07 13:23:03 +01:00
Morten Christensen 4c5dfb42d5 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-01-07 13:13:38 +01:00
Shannon 0245efe3cb Fixes the change password dashboard to work properly. Fixes the EditUser to property save the member and the user. Adds new (probably temporary) MembershipHelper which is used to update a MembershipUser. Updates the User model to ignore the membership properties that we currently cannot persist. Ensures the legacy User membership provider still looks for a typed membership user (which should never have happened). Fixes small issue with underlying membership provider trying to encrypt an empty string. 2014-01-07 17:01:22 +11:00
Shannon 0b4ddf82aa Adds more user service tests 2014-01-06 17:43:29 +11:00
Shannon 3ff173732b implements the remaining incomplete parts of the UserService, adds more unit tests 2014-01-06 17:30:08 +11:00
Shannon f3f7aa70d1 Ensures a default member/user type is assigned on membership provider initialize, adds more unit tests 2014-01-06 16:18:25 +11:00
Shannon cd82bc6d21 streamlined the new membership provider classes so now they all share the same logic and use IMembershipMemberService<T> which is used by both IMember and IUser services 2014-01-06 15:38:34 +11:00
Shannon c3a6c7c473 fixes up more of the legacy user membership provider 2014-01-06 14:02:09 +11:00
Shannon 5538a2e793 fixed up the failing unit tests for member service counts, added more unit tests for UserService and implemented more of the required methods. 2014-01-06 12:25:14 +11:00
Shannon 1b7dc76df2 Updated much more of the UserService + some unit tests 2014-01-06 11:56:53 +11:00
Shannon 85c85cd1eb Simplifies and streamlines the models used between IMember and IUser along with the services used for both of these entities.
Updates the model used to store and retreive permissions, instead of a single string it is an Enumerable<string> which gives us some flexibility in the future and since this was not public (yet) it's the perfect time to do this.
Removes the base Profile classes from User since these are not required, since we cannot share base classes between Member and User, these weren't necessary.
2014-01-06 11:04:26 +11:00
Shannon ba5f2bc69d Ensure the old membership provider's count online members is implemented 2014-01-02 15:57:27 +11:00
Shannon 17883358b6 Fixes some issues with the User membership provider, updates user create dialog to also have an email address (which is required by membership), adds validation to the member and user create dialogs to ensure that the email address is validated to be a correcty formatted address. 2014-01-02 14:13:43 +11:00
Shannon fc0c6a1cd8 fixes stored password check with legacy encoding. 2013-12-31 13:27:47 +11:00
Sebastiaan Janssen 934d4020b2 Merge pull request #224 from Attackmonkey/Hackathon-2760
Fixes issue U4-2760, sorting installed packages
2013-12-29 06:30:09 -08:00
Sebastiaan Janssen 8b03ba4f42 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-12-29 15:26:44 +01:00
Sebastiaan Janssen 3caf84c63c Merge branch 'Hackathon-U4-3063' of https://github.com/Attackmonkey/Umbraco-CMS into Attackmonkey-Hackathon-U4-3063 2013-12-29 15:24:47 +01:00
Sebastiaan Janssen aae16f227e Merge pull request #227 from mattbrailsford/6.2.0-3454
Maintains tab sort order for doc type imports/exports.
2013-12-29 06:20:09 -08:00
Sebastiaan Janssen 443002cdde Merge pull request #273 from esunxray/patch-2
Update zh.xml
2013-12-29 06:19:30 -08:00
Sebastiaan Janssen 75150f0bfa Merge pull request #223 from Attackmonkey/Hackathon-2757
Fixes issue U4-2757 where generic properties are not ordered correctly.
2013-12-29 06:18:19 -08:00
Sebastiaan Janssen af73fd8b68 Merge pull request #218 from dipunm/U4-2551
Missing languages in RTE insert link dialog.
2013-12-29 06:11:53 -08:00
Sebastiaan Janssen 139df63ddf Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-12-29 15:08:10 +01:00
Sebastiaan Janssen a49058fe00 Fixes U4-510 Copy node makes multiple copies 2013-12-29 15:07:28 +01:00
Sebastiaan Janssen dcde00cec1 Merge pull request #213 from leekelleher/U4-3452
Fixes: U4-3452 Update the MIT License URL (Packager)
2013-12-29 05:58:02 -08:00
Sebastiaan Janssen bcc70f7a1e Merge pull request #197 from mkariti/u4-415
U4-415
2013-12-29 05:39:30 -08:00
Sebastiaan Janssen 32bc2f1d69 merge ismailmayat-UK-Festival 2013-12-29 14:34:54 +01:00
Sebastiaan Janssen 4d3f67885a Fixes U4-1076 Apostrophes in document type description are shown preceded/escaped by a slash in the Create Node dialog 2013-12-29 14:12:23 +01:00
Sebastiaan Janssen a269e9d426 Merge branch 'BatJan-master' into 6.2.0 2013-12-29 13:51:54 +01:00
Sebastiaan Janssen af5a382f93 Merge branch 'master' of https://github.com/BatJan/Umbraco-CMS into BatJan-master 2013-12-29 13:51:18 +01:00
Sebastiaan Janssen dad910b8ab Merge pull request #212 from mattbrailsford/6.2.0-1004
Added ValidateRequest="false" on package installer page to allow user co...
2013-12-28 03:50:10 -08:00
Shannon 8a70c440f2 Added many more unit tests for the membership provider base class and fixed some logic inconsistencies. 2013-12-28 18:55:43 +11:00
Shannon fbdb1d5d6c Fixes: U4-3942 Cannot configure the request if there is not content assigned - exception
Conflicts:
	src/Umbraco.Tests/Umbraco.Tests.csproj
2013-12-28 14:01:08 +11:00
Shannon edaa5ebd43 Lots more unit tests for the membership providers and some other fixups - have a new failing test as i need to sort out salting issue with encrypted passwords. 2013-12-24 14:03:18 +11:00
Shandem c12b270511 Merge pull request #268 from james-melville/6.2.0
Fixes: U4-3814 - 6.1.6 XSS vulnerability in backoffice
2013-12-23 16:14:52 -08:00
Shannon c8fa2b3880 Merge branch 'abjerner-patch-1' into 6.2.0
Conflicts:
	src/Umbraco.Web/PublishedContentExtensions.cs
2013-12-24 11:08:48 +11:00
Shannon 1c139b685a updates legacy membership provider to use efficient paging. 2013-12-20 18:12:54 +11:00
Shannon 7a8b3dc9bc Updated the member service/repo to have paged queries and results which use db paging for maximum efficiency (of course only works for things like email, username but those are 2 specific things that are needed by the membership provider) 2013-12-20 18:11:12 +11:00
Shannon a4dde1948f Implements the member count methods on the member service and adds unit tests. 2013-12-20 16:20:32 +11:00
Shannon 0f68818a19 Updated member service with the newer property value queries and added unit tests for all of them 2013-12-20 15:44:53 +11:00
Shannon 414b65b269 More WIP on the membership providers - both new and old. They are now both working with the same up-to-date logic and base classes. Updated the interface definitions on the member services to support the membership provider queries - now to implement the logic. 2013-12-20 14:01:10 +11:00
Shannon 2dd04799b2 WIP membership provider updates 2013-12-19 18:33:25 +11:00
esunxray 1c901e00cc Update zh.xml
add line <key alias="resetPassword">重设密码</key>
2013-12-19 14:53:50 +08:00
Shandem c589c741e8 Merge pull request #220 from leekelleher/U4-2006
Fixes: U4-2006 Domain.GetDomain(string DomainName) is case-sensitive
2013-12-18 20:56:03 -08:00
Shandem c8923cbc27 Merge pull request #221 from AnthonyCogworks/U4-2272
Replaced HttpContext.Current.Cache with HttpRuntime.Cache
2013-12-18 20:54:57 -08:00
Shandem 063f405a06 Merge pull request #230 from Yawka/U4-2772
U4 2772
2013-12-18 20:51:17 -08:00
Shandem addfbcf2a7 Merge pull request #232 from Yawka/U4-2034
U4 2034
2013-12-18 20:48:52 -08:00
Shandem 8ee133bb75 Merge pull request #239 from OptimisticCoder/U4-451
U4-451 Inconsistent line endings in template files created by Umbraco
2013-12-18 20:46:46 -08:00
Shandem fa1185cbd8 Merge pull request #241 from OptimisticCoder/U4-3039
U4-3039 Import Document Type leaves files in App_Data
2013-12-18 20:43:15 -08:00
Shandem 68e0a414a0 Merge pull request #245 from esn303/patch-1
Fixed minor typos
2013-12-18 20:39:43 -08:00
Shandem 89860bd786 Merge pull request #261 from esunxray/patch-1
Update zh.xml
2013-12-18 20:26:48 -08:00
Shandem b5cfefa052 Merge pull request #265 from Jeavon/U4-3247
Fixes U4-3247 - TinyMce v3 doesn't work with IE11
2013-12-18 20:22:19 -08:00
Shannon b2c0f3c35a some file formatting 2013-12-19 15:21:02 +11:00
Shannon a43f4b7b7f Completes: U4-1521 Updated back office to use ClientDependency bundles for common files 2013-12-19 15:05:05 +11:00
Shandem 7ce3949852 Merge pull request #209 from ProNotion/U4-1521
U4 1521
2013-12-18 18:37:02 -08:00
Shandem 4862419744 Merge pull request #198 from craigacronin/U4-1891
Fixed as per issue comments, but also implemented for another 3 overload...
2013-12-18 18:33:57 -08:00
Shannon 6b810c89f6 un-ignores PublishedContentExtensionTests 2013-12-19 13:28:17 +11:00
Shandem 89b0a2fd89 Merge pull request #170 from lars-erik/6.2.0_fix_publishedcontentextensiontests_sidebysidefriendly
Should make the PublishedContentExtensionTests green when ran together w...
2013-12-18 18:25:38 -08:00
Shannon 8aceae9880 re-formats some code, simplifies calls using InvariantEquals extension method 2013-12-19 13:22:33 +11:00
Shandem 384d4d60f1 Merge pull request #168 from stevetemple/6.1.6-multiple-action-route-issue
Fix error when multiple routes have the same controller
2013-12-18 18:18:44 -08:00
Shannon 67caf81a74 adds a couple of null checks. 2013-12-19 13:14:38 +11:00
Shannon 763ab26446 Updates packaging service to not export empty properties. 2013-12-19 13:13:13 +11:00
Shannon 67a8fa5f07 Merge branch 'wtct-U4-3091' into 6.2.0 2013-12-19 13:05:27 +11:00
Shannon 5c59317bf8 changes casing of col names 2013-12-19 12:52:37 +11:00
Shannon a2ec53dd4f Merge branch 'wtct-U4-3071' into 6.2.0 2013-12-19 12:50:42 +11:00
Shannon db78c78df2 fixes some merge issues with view engine wrapping PR. 2013-12-19 12:45:46 +11:00
Shannon 4558549d5a Fixes appendformat issue 2013-12-19 12:40:41 +11:00
Shannon d98801d5d1 Merge branch '6.2.0' of https://github.com/mortenbock/Umbraco-CMS into mortenbock-6.2.0
Conflicts:
	src/Umbraco.Web/WebBootManager.cs
2013-12-19 12:35:33 +11:00
Shandem de9ecf6afc Merge pull request #143 from IDisposable/patch-1
Added contextualKeyBuilder optional argument to allow the key used for cachin...
2013-12-18 17:32:26 -08:00
Shandem 702790bf77 Merge pull request #144 from IDisposable/patch-2
Make CacheHelperExtensions public so we can call CachedPartialView and C...
2013-12-18 17:30:01 -08:00
Shannon c912e80134 modified media service tests to not have to create data in teh base tests 2013-12-19 12:27:21 +11:00
Shannon 098c856138 Merge branch '6.2.0' of https://github.com/sniffdk/Umbraco-CMS into sniffdk-6.2.0
Conflicts:
	src/Umbraco.Tests/Umbraco.Tests.csproj
2013-12-19 12:11:33 +11:00
Shannon b45306e1ff Merge branch '6.2.0' of https://github.com/dprothero/Umbraco-CMS into dprothero-6.2.0
Conflicts:
	src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs
2013-12-19 11:59:22 +11:00
Shannon 3499f39970 Merge branch 'kipusoep-patch-1' into 6.2.0 2013-12-19 11:49:30 +11:00
Shannon 9115aa1a6d merge issue with proj file 2013-12-19 11:46:31 +11:00
Shannon 904cbbb906 missing proj file update 2013-12-19 11:41:26 +11:00
Shannon 8656d3e4b9 adds some null checks, removes old unused webforms files for tree control 2013-12-19 11:35:53 +11:00
Shannon 40988b4655 Merge branch 'select-parent-on-movecopy' of https://github.com/pynej/Umbraco-CMS into pynej-select-parent-on-movecopy
Completes: U4-3920 Move/Copy/Content-Picker time saver - pre-selects current node
2013-12-19 11:25:54 +11:00
Shannon 06dbea84d8 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-12-19 11:06:11 +11:00
Shannon f54cf32057 Converted spell checker deserialization to json.net and changed the deserialized object to internal with correct naming conventions. 2013-12-19 11:06:00 +11:00
Shannon 64dbf0207b Merge branch 'DougMac-6.1.4' into 6.2.0 2013-12-19 10:38:56 +11:00
Stephan 206c88105e Left some Console.WriteLine statements uncommented 2013-12-18 17:50:47 +01:00
Morten Christensen 3177b979d3 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-12-18 10:00:47 +01:00
Shannon 4ab32dd270 moves classes into sep files 2013-12-18 18:09:54 +11:00
Shannon fec55e9d1c Updates IMemberService with methods to search on string properties with an option to define how to match the string property, adds all supporting unit tests. 2013-12-18 17:37:46 +11:00
Shannon a21aa079ff Adds ability to use the query builder with string matches based on an NText column 2013-12-18 17:22:00 +11:00
Shannon ef4246478d Fixes: U4-2294 6.1.0: umbracoServer table can't be created on MySQL <5.6.5 2013-12-18 15:30:40 +11:00
Shannon 137d859532 backports missing logic and tests from 7 that I overlooked. 2013-12-17 16:13:38 +11:00
Shannon 82b2821e27 Gets the members services ensuring members xml is being handled correctly, fixes issue with the static variable holding the default member type properties (this was then persisted in mem and then reused across all member types). Added more unit tests to verify all. 2013-12-17 15:40:47 +11:00
Shannon b270cefacc Upgrading member repositories and services with tests 2013-12-17 14:53:21 +11:00
Shannon b4e984fe6a adds/updates unit tests for member and member type repository 2013-12-17 12:38:11 +11:00
Shannon f62e4fa973 adds/updates member type repo tests 2013-12-17 11:42:03 +11:00
Shannon ee8050f38f Fixes ContentTypeBase event assignment issue - an event handler was added for every property type added - that was not correct. 2013-12-17 11:35:56 +11:00
Stephan b506b5c8e9 U4-3710 - bugfix 2013-12-16 17:01:35 +01:00
stefana99 067268a96e Changes to imageCropper, supports new mediafilesystem 2013-12-16 13:35:18 +00:00
Morten Christensen d9e843f0ba Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-12-16 09:48:18 +01:00
Shannon 66dd0d073c backports the member type service updates 2013-12-16 19:05:03 +11:00
Shannon 29c22cc4b5 exposes repository service 2013-12-16 19:02:53 +11:00
Shannon e29031a2c4 Back ported relationship repo/service updates 2013-12-16 18:44:11 +11:00
Shannon 3ff0cca033 back ports entity service updates 2013-12-16 18:23:40 +11:00
Shannon fe16cc91fa back ports packaging service updates 2013-12-16 18:17:30 +11:00
Shannon 7e6fdcb05e back ported template repo and file service updates 2013-12-16 18:10:44 +11:00
Shannon d1e071b9cb adds additional unit tests for the data type service to include pre-value handling. 2013-12-16 17:47:40 +11:00
Shannon 2ce952bdbb backports data type service updates and fixes unit tests with correct seeding value. 2013-12-16 17:17:23 +11:00
Shannon 6a9b8d5540 Fixes a unit test issue with the mntp editor initialization. 2013-12-16 16:27:59 +11:00
Shannon af86a5d7b1 backporting imediaservice changes 2013-12-16 16:04:37 +11:00
Shannon 0f25029ff6 Fixed typo 2013-12-16 16:02:34 +11:00
Shannon 060e584503 backported IContentService updates 2013-12-16 15:57:59 +11:00
Shannon 743c0bb31c Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-12-16 14:19:10 +11:00
Shannon 4bac3e19fe Fixes up webbootmanager with new cachehelper updates. 2013-12-16 14:18:58 +11:00
Shannon b86cddda94 fixes up unit tests 2013-12-16 13:55:46 +11:00
Shannon 11103c0bc5 proj file 2013-12-16 13:23:07 +11:00
Shannon 8210702474 removes the xquery tests - we don't need these and r# keeps wanting to run them 2013-12-16 13:22:52 +11:00
Shannon a42b660648 Backporting the cachehelper and associated cache classes. 2013-12-16 13:19:10 +11:00
Shannon f11d4fbedd Worked on the application cache, added request cache, changed some stuff over to be interfaces, added unit tests suite (need mroe) to test all caching providers.
Conflicts:
	src/Umbraco.Core/Cache/CacheProviderBase.cs
	src/Umbraco.Core/Cache/HttpRuntimeCacheProvider.cs
	src/Umbraco.Core/Cache/NullCacheProvider.cs
	src/Umbraco.Core/Cache/StaticCacheProvider.cs
2013-12-16 12:51:02 +11:00
Shannon 9105c08a4c getting membership provider to the same state as v7 2013-12-16 12:20:38 +11:00
Stephan 5aec753859 U4-3710, -3732 - Fix default ShortStringHelper 2013-12-13 12:20:57 +01:00
james-melville eeaa9166ac Fixes: U4-3814 - 6.1.6 XSS vulnerability in backoffice 2013-12-13 10:25:32 +00:00
Shannon 751ace1168 Merge branch '6.2.0-membershipprovider' into 6.2.0
Conflicts:
	src/Umbraco.Web/Umbraco.Web.csproj
	src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs
2013-12-13 17:17:24 +11:00
Shannon 51da5343ea Fixes installation issue with rebuilding media cache
Conflicts:
	src/Umbraco.Core/Umbraco.Core.csproj
	src/Umbraco.Web.UI/config/trees.config
	src/Umbraco.Web/Umbraco.Web.csproj
2013-12-13 17:07:29 +11:00
Shannon 34df5009e0 Upgraded installer to do a two part install - first install then if an upgrade is required do the upgrade in a second call - this way we can have the progress bar update since the media xml installer can take some time. 2013-12-13 16:58:21 +11:00
Anders Bjerner e17b5e6a7b Update PublishedContentExtensions.cs
Added overloaded extension methods for Next() and Previous() to take a delegate (eg. lambda expression) as a second parameter. The methods are based on this thread by Jeavon Leopold: http://our.umbraco.org/forum/developers/razor/46832-Filtered-Next()-and-Previous()-v7-UmbracoHelperMVC

The code is tested in 7.0.0, but since it only relies on the existing Next() and Previous() methods, it should work in 6.1.x and 7.1.1 as well.
2013-12-12 15:32:52 +01:00
Shannon a1c65f0518 Gets that naggy unit test passing 2013-12-12 17:52:03 +11:00
Shannon c5047148b3 Fixes legacy media business logic to return null when calling ToXml if the media item is trashed - this makes it consistent with how content works and also prevents being able to show the media on the front-end when it is trashed. Fixes up how the MediaService rebuilds the XML to make sure it's transactional based. Fixes: U4-3820 cached media xml is not cleared from the cmsContentXml table when recycled
Conflicts:
	src/Umbraco.Web/umbraco.presentation/library.cs
2013-12-10 12:56:31 +11:00
Shannon ed2126eef9 ensures media xml cache is rebuilt on upgrade 2013-12-10 11:54:18 +11:00
Shannon ce4b56895e fixes installer login check 2013-12-10 11:51:41 +11:00
Shannon 94db371234 Ensures macro and urls are not parsed in the ItemRenderer when a content item is assigned since that parsing will occur with the value converters 2013-12-10 09:59:13 +11:00
Sebastiaan Janssen 103e226b51 Merge pull request #215 from dipeshhirani/U4-752
U4-752 Add culture invariant languages to create language dialog
2013-12-09 13:40:21 -08:00
Shannon 57f2250f13 Fixes: U4-3820 cached media xml is not cleared from the cmsContentXml table when recycled 2013-12-09 16:56:02 +11:00
dipeshhirani bb1edd2051 remove commented line 2013-12-08 16:23:03 +00:00
Sebastiaan Janssen 14790559cb Merge pull request #140 from pynej/search-node-type
Add node type to search results
2013-12-08 07:56:50 -08:00
Sebastiaan Janssen 97457087c7 Merge pull request #266 from greystate/patch-1
Fix a typo/grammar error in da.xml
2013-12-08 06:21:31 -08:00
Shannon 37eb66510f Fixes: U4-3505 Sometimes macro parameter types are not resolved during startup 2013-12-06 14:07:29 +11:00
Shannon 4cb4ff0617 Fix MySQL migrations.
Conflicts:
	src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagRelationsTable.cs
2013-12-06 10:26:32 +11:00
Chriztian Steinmeier dc60eb8383 Fix a typo/grammar error in da.xml 2013-12-05 13:06:24 +01:00
Jeavon Leopold 3f1b057f45 Fixes U4-3247 - v6.1.6 RTE view/edit HTML doesn't work with IE 11 by upgrading TinyMce to v3.5.10 2013-12-05 09:06:01 +00:00
Shannon f6179ff813 Strange, somehow these updates got overwritten 2013-12-05 16:11:15 +11:00
Shannon 1735c5adca adds Exists(string username) to member service and wraps IsMember with that call. 2013-12-05 16:04:53 +11:00
Shannon 31e715e146 Updates legacy Member class to setupNode based on the new IMember object (just like we do with media/content) - this will speed up data retrieval and is the start of wrapping the new API from the old one. 2013-12-05 15:51:38 +11:00
Shannon 5f50bae65c Cleaning up a bit of the legacy member class
Conflicts:
	src/umbraco.cms/businesslogic/member/Member.cs
2013-12-05 14:48:30 +11:00
Shannon e6d8a83519 Ensures that the ContentBase item is set on Document/Media and that the property value is set based on the already loaded value in the model if IData implements IDataValueSetter (which DefaultData does). This streamlines how properties get their data and will save on a ton of queries when using the legacy API. 2013-12-05 14:26:18 +11:00
Shannon 38df2017de Fixes issue with deleting content types that have content 2013-12-04 15:01:27 +11:00
Shannon 33aa4e2062 Fixes potential xss 2013-12-04 13:33:24 +11:00
Shannon 1efa75c891 Fixes potential xss 2013-12-04 12:42:40 +11:00
Shannon d4514844f8 Fixes a few other potential xss entry points 2013-12-03 17:58:42 +11:00
Shannon 6b7a495d19 Fixes a few other potential xss entry points and cleans up some legacy webforms files 2013-12-03 16:38:58 +11:00
Shannon 601eb0bf38 Fixes a few other potential xss entry points and cleans up some legacy webforms files 2013-12-03 16:28:51 +11:00
Shannon 037e7e0797 Fixes remaining xslt injection U4-3175 2013-12-03 15:56:50 +11:00
Shannon a7e32e97e3 Fixes xss issue 2013-12-03 15:40:12 +11:00
esunxray cacf87be2d Update zh.xml
update Chinese file for 6.2, this can be merged into V7.
2013-11-29 21:26:16 +08:00
Shannon e981776e6d Created new EnsurePublishedContentRequestAttribute for custom routing to still be able to render macros. 2013-11-29 17:41:38 +11:00
Shannon 250276bbd4 Merge branch '6.1.6-U4-3619' into 6.2.0 2013-11-29 11:26:01 +11:00
Shannon af29f61478 Fixes csrf issue 2013-11-29 11:10:25 +11:00
Shannon 58fc51ae93 Fixes: U4-3736 Unit test Can_Get_File_Dates() now testing correctly, disregarding local (nont-UTC) time. 2013-11-28 09:30:50 +11:00
Shannon 20813ef207 Fixes: U4-3673 Creating content with Services API always sets created by to admin
Conflicts:
	src/Umbraco.Tests/Services/ContentServiceTests.cs
2013-11-25 13:25:01 +11:00
Shannon d04f2a98b9 Fixes tests 2013-11-21 17:47:57 +11:00
Shannon f41f82adc5 Changes locker to be static 2013-11-21 14:46:18 +11:00
Shannon e6ae88c016 Fixes hash generation and checking with the trees.config file - since this is changed during startup our plugin cache was never active :( 2013-11-21 14:45:52 +11:00
Shannon 474dcd0754 Fixes: U4-3587 Can't delete a member when there is a group assigned
Conflicts:
	src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
2013-11-20 18:24:44 +11:00
Shannon 369f6ac935 fixes merge issue 2013-11-20 18:15:11 +11:00
Shannon 5a928aa459 FIxes installer when duplicate conflicts: U4-3612 Cannot install Txt starter kit in the back office
Conflicts:
	src/umbraco.cms/businesslogic/Packager/Installer.cs
2013-11-20 17:28:33 +11:00
Shannon 416a9ed064 Comments out backported code - need to wait till we merge in the custom membership branch. 2013-11-20 17:10:15 +11:00
Shannon b13c3aa3b9 Fixes: U4-3610 When adding another tab to a member type no members will load and result in a YSOD
Conflicts:
	src/Umbraco.Core/Persistence/Relators/PropertyTypePropertyGroupRelator.cs
2013-11-20 16:59:41 +11:00
Shannon 99ae94a82f Ensures that members are auto-approved if creating a member via the legacy members API. 2013-11-20 16:40:30 +11:00
Shandem 96440c9ee5 Merge pull request #248 from lars-erik/6.2.0-fix-sqlsyntaxprovider-indexclustring
6.2.0 fix sqlsyntaxprovider indexclustring
2013-11-14 22:00:31 -08:00
Shannon b4c005c140 Fixes up the EntityRepository to use dynamics for media as well so that *all* fields in the main table are returned so we can store this information in AdditionalData, now that this is working nicely we should make the entity repo lookup the properties for content too just like we're doing for media since these get put into AdditionalData as well and there's really not much overhead to do that.
Conflicts:
	src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs
2013-11-15 14:53:26 +11:00
Shannon eca823ea90 Fix for U4-3529 Ysod editing Partial View 2013-11-15 13:49:20 +11:00
Marc Stöcker 376fe0bf55 changed wording to correct one in context of content
wording was wrong until today, needed a completely different meaning in the context of the content section; ironically it's just "Alias" now ;)
2013-11-14 22:22:25 +01:00
Lars-Erik Aabech e3cd85a6a2 Made CreateIndexBuilder set IndexType in Clustered(), NonClustered() and Unique(). 2013-11-14 10:55:35 +01:00
Lars-Erik Aabech 69f805ecca Proof that CreateIndexBuilder.NonClustered() does not affect index creation statement on SQL Server.
CreateIndexBuilder_SqlServer_NonClustered_CreatesNonClusteredIndex() fails expecting NONCLUSTERED but getting CLUSTERED.
CreateIndexBuilder_SqlServer_Unique_CreatesUniqueNonClusteredIndex() fails expecting UNIQUE NONCLUSTERED but getting CLUSTERED.
2013-11-14 10:53:58 +01:00
Shandem c037e2e09f Merge pull request #246 from lars-erik/6.2.0-fix-U4-3508
Fixes Template.ToXml() (U4-3508) and refactored Template.Import to use P...
2013-11-13 15:51:29 -08:00
lars-erik d8debf6789 Fixes Template.ToXml() (U4-3508) and refactored Template.Import to use PackagingService.ImportTemplates.
Fixed nullreference bug in ImportTemplates when used with XElement("Template"). (Added test for case with one template only)
2013-11-13 14:27:05 +01:00
Marc Stöcker 282da69d61 Fixed minor typos 2013-11-13 13:27:56 +01:00
Shandem e9ed1bf17a Merge pull request #244 from leekelleher/U4-3051
Fixes: U4-3051 GetAncestorOrSelfDocuments gets stuck in infinite loop
2013-11-12 14:11:05 -08:00
leekelleher cfcfb75dcc Fixes: U4-3051 GetAncestorOrSelfDocuments gets stuck in infinite loop 2013-11-12 21:26:21 +00:00
Morten Christensen 181593f5ea Merge pull request #234 from saciervo/fix/petapoco-fetch
SqlHelper Refactoring
2013-11-11 02:59:49 -08:00
Shannon a311a54d3d Hugely simplifies setting properties from macro parameters on user control macros with tests. 2013-11-11 12:22:29 +11:00
OptimisticCoder c83844468d U4-3039 Import Document Type leaves files in App_Data
Added File.Delete to clean up temp files.
Added try/catch round it and logging if it fails for any reason.
2013-11-09 15:18:43 +00:00
OptimisticCoder 80b5cfbb07 U4-451 Inconsistent line endings in template files created by Umbraco
Changed all "\n"'s to Environment.NewLine
Changed a string that was being appended in that method to a StringBuilder to be more efficient.
Cleaned up old commented out code from the method.
2013-11-09 14:37:22 +00:00
Sandro Ciervo 9911f03745 Fixed potential DbReaderException
- Use Fetch<T> instead of Query<T> because we create another DbReader inside the loop with DoesMacroHaveParameters().
2013-11-07 20:09:06 +01:00
yawka aacb86bf92 Add trim to all urls 2013-11-07 19:09:50 +02:00
yawka 59391f58ec Remove previous fix, and move it to IsReservedPathOrUrl 2013-11-07 19:06:25 +02:00
yawka 0debf9c34f Add check is path is whitespace 2013-11-07 19:05:50 +02:00
Morten Christensen 9fa17ef6cb Initial datalayer refactoring work on the legacy User class 2013-11-07 17:56:38 +01:00
Morten Christensen d227aa19b8 Leaving the original internal method intact 2013-11-07 17:56:12 +01:00
Sebastiaan Janssen d76336cd39 Merge pull request #194 from Attackmonkey/Hackathon-U4-3228
Fixes issue U4-3228, where dictionary item names are not trimmed.
2013-11-07 08:45:21 -08:00
yawka e0a10080b1 Add UI validation for regular expression property 2013-11-07 18:39:27 +02:00
yawka 807df434f6 Add validation for regular expression property 2013-11-07 18:39:02 +02:00
Sebastiaan Janssen 0dc3920309 Merge pull request #191 from dipeshhirani/U4-2756
Fixed the issue below: U4-2756
2013-11-07 08:38:44 -08:00
Sebastiaan Janssen 98d1aafb75 Merge pull request #187 from wpyz/6.2.0
Fixes issue with opening VS solution when only Visual Studio 2013 is installed (fixes U4-3445)
2013-11-07 08:36:40 -08:00
mattbrailsford d963917556 Added SortOrder to XML for document types (used by export)
Added ability for doctype importer to set the sort order if a sort order element is available
2013-11-07 16:30:23 +00:00
Tim Payne 347d41c841 Fixes issue U4-2760, and makes the installed packages list by name in alphabetical order to make it easier to see what's installed. 2013-11-07 16:06:16 +00:00
Tim Payne f16aa38fff Fixes issue U4-2757 where generic properties are not ordered correctly. 2013-11-07 15:51:58 +00:00
Sebastiaan Janssen 6a0d7ec8d6 Merge pull request #183 from mkariti/U4-1477
fix U4-1477
2013-11-07 07:49:27 -08:00
adang@thecogworks.co.uk 62a7e0acd0 Replaced HttpContext.Current.Cache with HttpRuntime.Cache 2013-11-07 15:44:55 +00:00
leekelleher 8e89d13142 Fixes: U4-2006 Domain.GetDomain(string DomainName) is case-sensitive 2013-11-07 15:41:34 +00:00
dipunm a5782a40af Missing languages in RTE insert link dialog.
Also included files in csproj file to ensure proper build.
2013-11-07 14:59:00 +00:00
dipeshhirani c6af319805 commented out the line that checked if the language is neutral. 2013-11-07 14:56:00 +00:00
leekelleher 516beedbbb Fixes: U4-3452 Update the MIT License URL (Packager) 2013-11-07 14:48:20 +00:00
mattbrailsford 7cd01fc50b Added ValidateRequest="false" on package installer page to allow user controls which postback html / code. 2013-11-07 14:35:44 +00:00
Simon Dingley e9d12ae0d8 Revert "Group jQueryTree script files"
This reverts commit baed01518c.
2013-11-07 14:23:53 +00:00
Tim Payne 02e167c1f6 Fixes issue U4-3063 where copying a document type uses the rename for the node alias, but not the title, resulting in two Doctypes with the same name, but different aliases, rather than different names AND aliases. 2013-11-07 14:20:47 +00:00
Simon Dingley baed01518c Group jQueryTree script files 2013-11-07 13:21:01 +00:00
Morten Christensen f9a86385b5 Rearranging the create schema extensions methods to provide a bit more flexibility for external usage. 2013-11-07 14:03:34 +01:00
Craig Cronin a0106ff811 Fixed as per issue comments, but also implemented for another 3 overloads 2013-11-07 12:50:26 +00:00
Simon Dingley e0da5a9cb2 Groups jQuery dependencies using the ClientDependency Group property 2013-11-07 12:45:35 +00:00
mkariti 451d5eb484 U4-415 2013-11-07 14:40:26 +02:00
Morten Christensen b8f7df1a96 Fixing the broken stylesheetrepository test and ignoring the StylesheetRepository in the RepositoryResolverTest for the time being as it takes two different UOWs as opposed to other repositories. 2013-11-07 13:33:49 +01:00
Tim Payne 425fd80e65 Fixes issue U4-3228, where dictionary item names are not trimmed. 2013-11-07 12:28:43 +00:00
Morten Christensen 04bb778dc1 Fix StylesheetRepositoryTest which broke as a result of PR #176 2013-11-07 12:52:25 +01:00
dipeshhirani 3f2be3342a Fixed the issue below:
The "Unpublish" button (under Properties tab) is bad translated to Italian.
The used word is "Non pubblicato". This phrase is mean "It is not published".
A best translation is "Non pubblicare" (unpublish).

Did not do any of the others as they are either already done or the requesters change seems incorrect/irrelevent
2013-11-07 11:42:08 +00:00
Morten Christensen 3ba50e7bae Merge pull request #176 from pynej/add-stylesheet-ids
Fix for missing Id's on FileService.GetStylesheets() call.  This is need...
2013-11-07 03:41:33 -08:00
Morten Christensen 7306ddef14 Merge pull request #182 from stocksr/6.2.0-petapoco-refactor
6.2.0 petapoco refactor - umbraco.cms.businesslogic.language.Item
2013-11-07 03:37:37 -08:00
Morten Christensen 17bb29eb66 Merge pull request #185 from saciervo/6.2.0
Use PetaPoco instead of SqlHelper
2013-11-07 03:35:49 -08:00
Morten Christensen 8bf3de738f Merge pull request #188 from stocksr/6.2.0-petapoco-refactor-umbraco.cms.businesslogic.language.Language
Refactoring umbraco.cms.businesslogic.language.Language class
2013-11-07 03:34:08 -08:00
Robert Stocks 2d37502a44 Refactoring umbraco.cms.businesslogic.language.Language class 2013-11-07 11:28:00 +00:00
Ryan Lewis d5c485205a Whitespace 2013-11-07 11:24:40 +00:00
Ryan Lewis 9533198365 Can open VS solution with only Visual Studio 2013 installed (fixes U4-3445) 2013-11-07 11:23:41 +00:00
Morten Christensen 66f20e3800 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-11-07 12:19:27 +01:00
Sandro Ciervo 9269a98806 Refactored Umbraco.Web.UI.Controls.InsertMacroSplitButton
- CreateChildControls()
- DoesMacroHaveParameters (Int32)
2013-11-07 12:15:03 +01:00
mkariti 7c97fddec5 fix U4-1477 2013-11-07 13:08:56 +02:00
Morten Christensen a567cf2a87 Minor update to the DefaultData so the used PetaPoco db object is consistent 2013-11-07 12:00:45 +01:00
Morten Christensen 1e319d667b Updating the remaining methods in the Notification class so it no longer uses the legacy SqlHelper. 2013-11-07 11:59:59 +01:00
Sebastiaan Janssen cc039e365d Merge pull request #181 from Attackmonkey/Tim-Payne-Hackathon-U4-2708
Fixes issue U4-2708
2013-11-07 02:55:03 -08:00
Morten Christensen f91ff5dc31 Special commit for a special Lars-Erik 2013-11-07 11:48:25 +01:00
Robert Stocks 9347a2edbb Refactoring umbraco.cms.businesslogic.language.Item class - Fix Update and Delete calls 2013-11-07 10:40:23 +00:00
yawka 1923b68594 Fix 2034, add check for whitespaces 2013-11-07 12:36:35 +02:00
Robert Stocks 64a73ef528 Refactoring umbraco.cms.businesslogic.language.Item class 2013-11-07 10:20:55 +00:00
Tim Payne 4ea04f5ffe Fixes issue U4-2708 2013-11-07 10:08:11 +00:00
Morten Christensen 6b006e6fd7 Refactoring GetUserNotifications method in the Notification class 2013-11-07 11:00:19 +01:00
Shannon fc0654a80f Fixes: U4-2241 Native Multi-node tree picker in Member Types: Saving clears selected items 2013-11-07 12:02:41 +11:00
Sebastiaan Janssen 4717faaf1b Merge pull request #180 from Jeavon/U4-3432
Fix for U4-3432Rollback Dialog - CreateDate/Creator formatting tweaks
2013-11-06 09:48:08 -08:00
Jeavon Leopold e7d587f776 Fix for U4-3432Rollback Dialog - CreateDate/Creator formatting tweaks required 2013-11-06 17:19:18 +00:00
Stephan dca0c85db5 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2013-11-04 12:54:07 +01:00
Shannon 5006115b2d Fixes object extensions and tests
Conflicts:
	src/Umbraco.Core/ObjectExtensions.cs
	src/Umbraco.Tests/ObjectExtensionsTests.cs
2013-11-02 15:20:04 +11:00
Stephan 058cec7551 Cache AspNet hosting permission level 2013-11-01 16:57:31 +01:00
Stephan 2671709991 U4-2518 - issue with virtual dir named Umbraco 2013-11-01 09:53:50 +01:00
Shannon ac2d8633af Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-11-01 18:07:18 +11:00
Shannon 76bc312842 Fixes an issue with empty string conversions to date time - should fail 2013-11-01 18:06:58 +11:00
Stephan 767719357e U4-3279 - better exception message when failing to find a content type 2013-10-31 18:28:49 +01:00
Stephan 7b29bd67f3 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2013-10-31 15:29:16 +01:00
Shannon dc4a0fec80 Merge branch '6.2.0' into 6.2.0-membershipprovider
Conflicts:
	src/Umbraco.Web/Umbraco.Web.csproj
2013-10-31 11:36:04 +11:00
Shannon 4c3d700c54 Changes the UserMembershipProvider to validate an already hashed/encrypted password and then validate a non hashed/encrypted attempt, this is to maintain compatibility with how v6 works, it's not ideal but needs to be there. Creates a settable property on the password changer to be able to dynamically hide the old password field if you are going to manually set the old password. Updates the EditUser to hide the old password field and pass in the alraedy encrypted pword to validate against like it used to be. 2013-10-31 11:35:12 +11:00
Jeremy Pyne 6451f6ad68 Fix sql errors in prev change. 2013-10-29 10:00:25 -04:00
Jeremy Pyne 7cd6882f28 Removed dependence in Stylesheet repository on Entity Service. 2013-10-29 09:24:05 -04:00
Jeremy Pyne dc336728b5 Fix for missing Id's on FileService.GetStylesheets() call. This is needed as sytlesheets can only be loaded in the editor via their Id so listing stylesheets needs to list there Id as well for custom plugins to render the build in editor. 2013-10-28 14:32:18 -04:00
Shannon 49d5791825 Adds DescendantsOrSelf extensions on ienumerable to published content extensions 2013-10-28 12:35:50 +11:00
Shannon 6cfb864055 Fixes DataTypeDefinitionRepository to properly delete a data type including it's pre-values 2013-10-28 11:23:09 +11:00
Stephan 89c5d5d613 PublishedContent - get published properties to report the CLR type of the value 2013-10-28 01:09:34 +01:00
Stephan 73b7729b82 Standalone - fix so it works again 2013-10-28 01:07:29 +01:00
Stephan c66d49dbfe PublishedContent - remove useles code in model factory 2013-10-28 01:07:17 +01:00
Shannon 9a3b70149c Fixes packaging service to export data type's property with the ID as the property editor ID 2013-10-28 11:00:14 +11:00
Shandem 98cc1c63ce Merge pull request #173 from pynej/trees-config-action
Trees config action
2013-10-27 16:00:00 -07:00
Stephan 128a08f169 Web.Mvc - Refactor UmbracoViewPage, UmbracoTemplatePage, support strongly-typed content
Conflicts:
	src/Umbraco.Web/Umbraco.Web.csproj
2013-10-25 13:21:29 +02:00
Stephan 4487e686d7 Core.TypeExtensions - add methods 2013-10-25 13:19:20 +02:00
Shannon ae32968efd Updates the legacy membership providers and WebSecurity/Password changer to stay backwards compatible with their previous settings whilst still keeping all of the provider fixes. 2013-10-23 10:19:43 +11:00
Shannon c1778918b5 Fixes more membership provider woes. 2013-10-22 17:37:03 +11:00
Shannon 680a4b9570 Fixes a lot -
U4-3208 Ensure all membership provider properties exist on the default Member type shipped with Umbraco
U4-3158 user back office password policies doesn't adhere to membership provider rules
and even more fixes to the membership provider like actually integrating the last locked out date and last pword change date. Fixes member creation to actually use the membership provider - this means that the password is created properly based on the provider config. Fixes the provider to have default fields specified so people don't actually have to specify in config.
2013-10-22 13:41:04 +11:00
Jeremy Pyne ba6ba15732 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.1.3-clean 2013-10-18 11:37:28 -04:00
Jeremy Pyne 291f526368 Fix to properly read actions from trees.config. 2013-10-18 11:37:06 -04:00
Shannon ff61812e65 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0-membershipprovider 2013-10-18 16:14:24 +11:00
Shannon d20ea58467 Fixes: U4-3193 Partial view cache needs to invalidate based on cache refreshers 2013-10-18 16:13:41 +11:00
Shandem c4f3dae317 Merge pull request #172 from IDisposable/6.2.0
Reduce Exceptions thrown during type conversions.
2013-10-17 18:07:52 -07:00
Marc Brooks 4d5b330567 Reduce Exceptions thrown during type conversions.
There are tons of places where null, blank or empty strings are being
converted to primative types (like int,, long, etc) or other ValueTypes
(like Guid, DateTime, etc.). When this is attempted, Exceptions are
thrown (and caught/swallowed) to allow for value defaulting. Since this
happens all the time in normal operation, tons of Exceptions are being
thrown. By switching to the TryParse methods available on all primative
types and the interesting ValueTypes, we can greatly speed the
processing of content data.
2013-10-17 19:12:08 -05:00
Shannon a87e699f8d Updates the web.config template to allow password reset 2013-10-18 09:54:34 +11:00
Shannon 40287fd427 adds some tests for membership provider base 2013-10-18 09:33:10 +11:00
Shannon 5d5f7a4516 Updated edit member with correct usage of password changer. 2013-10-18 08:52:46 +11:00
Shannon 61ef83c748 Gets the password changer working - on the edit user page. reset/change password wth validation 2013-10-18 00:37:51 +11:00
Shannon f82329b371 More updates the password changer and edit user 2013-10-17 22:52:37 +11:00
Shannon 0fee434ac2 Working on the password changer control to present the correct inputs based on the membership provider given.... nearly there. 2013-10-17 22:40:38 +11:00
Shannon 3aab41b1e4 Fixes lots of membership provider stuff
U4-3057 MembershipPasswordFormat problem at EncodePassword method in UmbracoMembershipProvider class
U4-3176 UsersMembershipProvider.CreateUser does not encrypt/hash the password
U4-3173 UserMembershipProvider.ChangePassword does not work

- Now we need to update the UI for the member

Signed-off-by: Shannon <sdeminick@gmail.com>
2013-10-17 20:20:43 +11:00
Jan Skovgaard 3abd4df8bd Enabled lists plugin in tinymce by default
Fixes http://issues.umbraco.org/issue/U4-3023
2013-10-16 16:01:17 +02:00
Jan Skovgaard ea239e6122 Missing languages in RTE insert link dialogue
Fixes this issue: http://issues.umbraco.org/issue/U4-2551
2013-10-16 15:53:56 +02:00
Lars-Erik Aabech 3fe99a402e Should make the PublishedContentExtensionTests green when ran together with everything else in TeamCity 2013-10-16 15:45:39 +02:00
Sebastiaan Janssen f9ad06be29 Something odd going on with the new tests being affected by tests that ran before them, no time to fix. Runs fine independently. 2013-10-16 14:19:24 +02:00
Steve Temple e738738e54 Only check actions if more than 1 route matches & ignore case when comparing controller names 2013-10-16 12:02:20 +01:00
Sebastiaan Janssen 699c651daa Merge pull request #169 from stocksr/U4-3033-take2
Really Fix U4-3033 - inserting extra blank line at end of CSS
2013-10-16 04:00:26 -07:00
Robert Stocks 79299175c1 Really Fix U4-3033 - inserting extra blank line at end of CSS 2013-10-16 11:49:02 +01:00
Sebastiaan Janssen 14e3976e88 Merge pull request #142 from lars-erik/6.2.0-recursive_isofdocumenttype
Recursive PublishedContentExtensions IsDocumentType
2013-10-16 02:55:09 -07:00
Sebastiaan Janssen 76c86daf24 Update da.xml 2013-10-16 11:50:12 +02:00
Lars-Erik Aabech a1ef40e4be Split the recursive IsDocumentType into an overload for "real" backwards compatibility.
Changed string comparison to use InvariantEquals. (guessing it doesn't _really_ break backw. compat?)
Added XML docs.
2013-10-16 11:38:58 +02:00
Sebastiaan Janssen e4a0904de6 Merge pull request #167 from lars-erik/change-doctype-defaultnone
Change doctype - default suggestion none when no matching alias.
2013-10-16 01:09:02 -07:00
Steve Temple f502912225 Updated to use invariant culture 2013-10-15 23:51:39 +01:00
Steve Temple c8a26bf6a3 Merge branch '6.1.6-multiple-action-route-issue' of github.com:stevetemple/Umbraco-CMS into 6.1.6-multiple-action-route-issue 2013-10-15 17:18:46 +01:00
Steve Temple e06e50c4fc Tidied up tabs to match Umbraco standard and nicer string comparison 2013-10-15 17:18:12 +01:00
Steve Temple 4236473b14 Tidied up tabs to match Umbraco standard 2013-10-15 17:15:53 +01:00
Steve Temple 3285e161c0 Fix issue with error http://our.umbraco.org/forum/developers/api-questions/41483-Umbraco-6-MVC-RenderRouteHandlerHandlePostedValues-Sequence-contains-more-than-one-matching-element when multiple routes share the same controller 2013-10-15 17:09:51 +01:00
Lars-Erik Aabech 607a52883a Change doctype - default suggestion none when no matching alias. 2013-10-15 13:21:30 +02:00
Sebastiaan Janssen 4651dfc763 Merge pull request #166 from stocksr/U4-3033
Fix U4-3033 - inserting extra blank line at end of CSS
2013-10-15 01:13:37 -07:00
Robert Stocks da74c0a163 Fix U4-3033 - inserting extra blank line at end of CSS 2013-10-15 09:09:03 +01:00
Shannon fbb7f18f23 fixes publish status when publishing child that doesn't have a parent published. 2013-10-15 14:12:10 +11:00
Shannon af43b35d17 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-10-14 10:46:06 +11:00
Shannon 72ea43758d Fixes - U4-3119 Non-Admin Users Cannot Create or Edit Users regardless of permission settings - 6.1.6 2013-10-14 10:45:51 +11:00
Stephan ee5af4998f Fix bug after merge 2013-10-11 12:30:17 +02:00
Stephan 565a020acf Merge remote-tracking branch 'origin/6.2.0' into 6.2.0-pubcontent 2013-10-11 11:14:36 +02:00
Shannon c459a893a5 adds new db indexes 2013-10-11 18:45:37 +11:00
wtct b5c3fb1728 FFROM to FROM 2013-10-11 09:16:18 +02:00
wtct e1caf3a470 U4-3091 2013-10-10 14:45:18 +02:00
wtct b6cf182341 Affect the order of domains 2013-10-09 17:52:05 +02:00
Sebastiaan Janssen 4935525591 Merge pull request #147 from AndyButland/u4-2958
Fix for issue U4-2958 Member can edit & Show on profile do not persist on Member Type editor
2013-10-05 10:04:08 -07:00
mortenbock c74cdb28d6 Testing the wrapping of view engines 2013-10-03 11:01:37 +02:00
Andy Butland 693778fe74 Fixed issue where member type properties would not persist after first save without reloading page 2013-10-02 21:20:05 +02:00
Marc Brooks b200cb463e Make CacheHelperExtensions public so we can call CachedPartialView and ClearPartialViewCache
In order to allow extensions to the logic and usage of the CachedPartial HtmlHelper, expose CachedPartialView and ClearPartialViewCache by making the wrapping static class public.
2013-09-30 18:28:45 -05:00
Marc Brooks cdf5ddf539 Added cacheKeyBuilder optional argument to allow the key used for caching to be contextual.
when building cached partials that work with many different instances of the same  partial view (e.g. using the same partial more than once on a page with different ViewDataDictionary or different model), it is necessary to either name each instance differently (ugh), or not cache.

By adding an optional argument to the CachedPartial Html helper method, we can vary the cache-key depending on the context of insertion. For maximum flexibility, pass the model and the viewData to the function so it can use that data to format a cacheKey suffix.

A typical use would be something like:

@Html.CachedPartial(
"EventListings"
, FeedRepository.getFeed(new CalendarEventsModel
  {
     StartingDate = DateTime.UtcNow.Date
     , Count = 10
  })
, 0
, contextualKeyBuilder: (model, viewData) =>
  {
     return (model as CalendarEventsModel).StartingDate.ToString();
  }
)
2013-09-30 18:23:56 -05:00
Sebastiaan Janssen 8eee7cae2f Merge branch '6.1.6' 2013-09-30 16:10:14 +02:00
Lars-Erik Aabech b6777e4635 Recursive PublishedContentExtensions IsDocumentType
Optional recursive parameter defaulted to false for backwards compatibility and no performance hit.
Settings recursive = true fetches content type for content and checks ancestor content types for the same alias.
2013-09-27 13:12:16 +02:00
Jeremy Pyne 5716edcf80 Added node type to quick search(as a toooltip).
Added node type to search results.
2013-09-23 16:19:05 -04:00
Mads Krohn 0fe33c120b Removing unwanted ToList() 2013-09-13 10:42:08 +02:00
Mads Krohn 10ea234dbf Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2013-09-13 10:29:12 +02:00
Mads Krohn 31f146fc6f Updates to the media trashed state handling
Tweaked the logic for determining when a media item is trashed or not.
Added unit tests. Removed unnecessary comments.
2013-09-13 10:29:03 +02:00
Shandem a353f6fb74 Merge pull request #135 from Myster/master
Fix multiple words in search U4-2509
2013-09-11 19:33:47 -07:00
Murray Roke a64efb93b3 Improved search with "and", partial match U4-2509
- added partial matching on each word.
- fixed bug so 'all' words match rather than 'any' words.
2013-09-12 14:30:42 +12:00
Murray Roke cf9f11ff45 Improved admin search splitting query U4-2509 2013-09-12 13:22:14 +12:00
Murray Roke d7481b5ca4 Fix multiple words in search U4-2509
When multiple words are entered in the search field no results are
returned.
This pull req. contains the fix suggested by Tony.
2013-09-12 10:22:59 +12:00
Mads Krohn 0af73b0290 Fixed U4-2842 Umb 6.1.5 - moving a media item from recycle bin / trash 2013-09-12 00:14:44 +02:00
dprothero 6675bac1dc Fix #U4-2796 - fixed copy/paste error (does not affect functionality) 2013-09-05 15:23:25 -07:00
dprothero 0d49a59cfe Fix #U4-2796 Possible to have duplicate Login Name (Member.LoginName) for Umbraco Members 2013-09-05 15:15:40 -07:00
Stefan Kip baa22301e9 Added Exception which tells you which datatype is unable to load 2013-09-05 11:31:06 +02:00
Niels Hartvig 2fb55cb831 Enhanced permission checking on views and snippets
Thanks to Richard Turnbull from NGS Secure Research who discovered a
minor issue that made it possible for authenticated Umbraco Users to
view files beyond their permissions
2013-09-02 14:23:27 +02:00
Sebastiaan Janssen 0e6a926a3f Merge branch '6.1.5' 2013-09-02 12:24:26 +02:00
Jeremy Pyne e65a71a05a Added code to pre-select the current node in content tree pickers based on the location of the document in the tree.
This is a HUGE time saver with an even moderately complex site hierarchy.
2013-08-29 11:14:51 -04:00
Jeremy Pyne 7a2a444579 Fix for select parent o move or copy in 6.1.3. 2013-08-29 11:14:35 -04:00
Jeremy Pyne e16ebecda4 Merge branch '6.1.3-clean' into select-parent-on-movecopy 2013-08-29 11:09:20 -04:00
DougMac 0218e39664 Fixes: U4-2060 Spell Checker Broke After Google Update 2013-08-26 22:50:53 +01:00
Sebastiaan Janssen 1e76cf67d3 Fix merge problem 2013-08-23 08:57:02 +02:00
Sebastiaan Janssen 61149f8112 Merge branch '6.1.4'
Conflicts:
	.gitignore
	src/Umbraco.Web.UI/install/steps/database.ascx
	src/Umbraco.Web/Umbraco.Web.csproj
	src/Umbraco.Web/umbraco.presentation/umbraco/controls/Images/ImageViewer.ascx.cs
	src/umbraco.editorControls/mediapicker/mediaChooser.cs
2013-08-22 14:46:11 +02:00
DougMac 7e645f9a6a Fixes: U4-2060 Spell Checker Broke After Google Update
The Google spell check at https://www.google.com/tbproxy/spell no longer
works. This updates to a newer Google Api (again undocumented)
2013-08-17 10:50:26 +01:00
Sebastiaan Janssen b5494546c7 defaultDocumentTypeProperty is no longer case-sensitive. Added to the Release config as well so it makes it into the umbraco downloadable package. 2013-07-19 15:40:12 +02:00
Sebastiaan Janssen 7bac1ef1cd Merge branch 'wip-u4-1949' of https://github.com/AndyButland/Umbraco-CMS into AndyButland-wip-u4-1949 2013-07-19 15:22:05 +02:00
Sebastiaan Janssen da15d40b04 Merge pull request #51 from kipusoep/master
Updated the download link
2013-07-19 06:18:13 -07:00
Sebastiaan Janssen 67bd303173 Merge pull request #46 from michielvoo/u4-2417
U4-2417 Could the preview thumbnail link to the full image
2013-07-19 06:02:51 -07:00
Sebastiaan Janssen 20e6843bf0 Merge pull request #32 from AndyButland/wip-u4-1285
Fix for U4-1285: Apostrophes in member groups cause exceptions
2013-07-19 05:39:38 -07:00
Sebastiaan Janssen 85c80b07f9 Merge pull request #42 from michielvoo/u4-232
Enabled support for integrated security for SQL Server to the installer.
2013-07-19 04:26:50 -07:00
Sebastiaan Janssen 557dccd88b Merge pull request #41 from michielvoo/u4-667
U4-667
2013-07-19 04:18:29 -07:00
Sebastiaan Janssen 334f0bfd2b Merge pull request #40 from michielvoo/u4-663
U4-663
2013-07-19 03:53:15 -07:00
AndyButland 986d37afd6 Removed debugging console.log reference 2013-07-18 21:23:05 +02:00
Stefan Kip 63ea79a4d6 Updated the download link 2013-07-11 10:03:25 +02:00
Michiel van Oosterhout e4df176a37 U4-2417: show media picker image as link to the original image.
Order of the views in the markup did not match the order of the Style enum.
ImageViewer control now selects the view by matching the ViewerStyle enum to a View ID. This way the order of the views in the markup is no longer important.

Also:
Removed user control from Umbraco.Web project, moved designer code and added code behind class for user control to Umbraco.Web.UI
Refactored code to use Umbraco.Core.IO
Removed some code that was commented out
2013-07-03 17:36:28 +02:00
Michiel van Oosterhout d926180e3a Added special overload for creating a connection string with integrated security.
Actually disable checkbox is the selected database type is not Microsoft SQL Server.
Refactored saveDBConfig for readability.
2013-06-28 16:40:23 +02:00
Michiel van Oosterhout 72bb1b3583 U4-667
Added a script to make the checkbox "Render content in editor" dependent on the "Use in editor" checkbox.
Also refactored the create.aspx code-behind so it's easier to see what control is loaded in the dialog when debugging.
2013-06-28 10:44:24 +02:00
Michiel van Oosterhout 240e58e061 U4-663
Do not overwrite existing files when creating a new template.
2013-06-28 10:42:51 +02:00
Michiel van Oosterhout e980296d6d Enabled support for integrated security for SQL Server to the installer. 2013-06-28 10:39:48 +02:00
AndyButland d23482b7a6 Moved setting for DefaultDocumentTypeProperty from GlobalSettings to UmbracoSettings 2013-06-27 16:00:49 +02:00
AndyButland 212800f706 Added config setting for default document type property; used setting to set default new property type 2013-06-26 17:25:44 +02:00
AndyButland d47ff4005c Support for deleting member groups with apostrophes 2013-06-26 06:16:39 +02:00
AndyButland dfeb1c7a0b Support for displaying and editing member groups with apostrophes 2013-06-26 06:16:23 +02:00
Jeremy Pyne fe23502e67 Added code to actually pre-select the parent node instead of just locating it in the tree. This seams keeps the Ui in a sane state.
Updated control code in Umbraco.Web.Ui from Umbraco.Web.
2013-06-25 15:48:16 -04:00
Jeremy Pyne ad2764e3ac Added code to select the parent node when doing Move/Copy operations. This will save lots of time for users.
This code can also be added to other places that use the TreeControl to pre-select the currently selected item(media pickers for example) so that changing content will be quicker.
2013-06-24 14:51:52 -04:00
1075 changed files with 49171 additions and 31538 deletions
+1
View File
@@ -85,3 +85,4 @@ NDependOut/*
*.ndproj
QueryResult.htm
*.ndproj
src/Umbraco.Tests/Views/web.config
+1 -1
View File
@@ -1,5 +1,5 @@
@ECHO OFF
SET release=6.2.0
SET release=6.2.4
SET comment=
SET version=%release%
+8
View File
@@ -299,6 +299,10 @@
</Target>
<Target Name="SetVersionNumber" Condition="'$(BUILD_RELEASE)'!=''">
<PropertyGroup>
<NewVersion>$(BUILD_RELEASE)</NewVersion>
<NewVersion Condition="'$(BUILD_COMMENT)'!=''">$(BUILD_RELEASE)-$(BUILD_COMMENT)</NewVersion>
</PropertyGroup>
<!-- Match & replace 3 and 4 digit version numbers and -beta (if it's there) -->
<FileUpdate
Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
@@ -308,5 +312,9 @@
<FileUpdate Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
Regex="CurrentComment { get { return &quot;([a-zA-Z]+)?&quot;"
ReplacementText="CurrentComment { get { return &quot;$(BUILD_COMMENT)&quot;"/>
<XmlPoke XmlInputPath=".\NuSpecs\build\UmbracoCms.targets"
Namespaces="&lt;Namespace Prefix='x' Uri='http://schemas.microsoft.com/developer/msbuild/2003' /&gt;"
Query="//x:UmbracoVersion"
Value="$(NewVersion)" />
</Target>
</Project>
+14 -8
View File
@@ -2,9 +2,9 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>UmbracoCms.Core</id>
<version>6.2.0</version>
<version>6.2.3</version>
<title>Umbraco Cms Core Binaries</title>
<authors>Morten Christensen</authors>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://umbraco.codeplex.com/license</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
@@ -15,17 +15,23 @@
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="Microsoft.AspNet.Mvc" version="4.0" />
<dependency id="Microsoft.AspNet.WebApi" version="4.0" />
<dependency id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.0" />
<dependency id="Microsoft.AspNet.Mvc" version="[4.0.30506.0,5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi" version="[4.0.30506,5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.WebHost" version="[4.0.30506, 5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.Core" version="[4.0.30506, 5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.Client" version="[4.0.30506, 5.0.0)" />
<dependency id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.1" />
<dependency id="Microsoft.Net.Http" version="[2.0.20710.0, 3.0.0)" />
<dependency id="MiniProfiler" version="[2.1.0, 3.0.0)" />
<dependency id="HtmlAgilityPack" version="[1.4.6, 2.0.0)" />
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
<dependency id="MySql.Data" version="[6.6.5]" />
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
<dependency id="ClientDependency" version="[1.7.0, 2.0.0)" />
<dependency id="ClientDependency-Mvc" version="[1.7.0, 2.0.0)" />
<dependency id="ClientDependency" version="[1.7.1.2, 2.0.0)" />
<dependency id="ClientDependency-Mvc" version="[1.7.0.4, 2.0.0)" />
<dependency id="Newtonsoft.Json" version="[4.5.11, 6.0.0)" />
<dependency id="Examine" version="[0.1.57, 1.0.0)" />
</dependencies>
</metadata>
<files>
@@ -35,7 +41,6 @@
<file src="..\_BuildOutput\WebApp\bin\cms.xml" target="lib\cms.xml" />
<file src="..\_BuildOutput\WebApp\bin\controls.dll" target="lib\controls.dll" />
<file src="..\_BuildOutput\WebApp\bin\controls.xml" target="lib\controls.xml" />
<file src="..\_BuildOutput\WebApp\bin\Examine.dll" target="lib\Examine.dll" />
<file src="..\_BuildOutput\WebApp\bin\interfaces.dll" target="lib\interfaces.dll" />
<file src="..\_BuildOutput\WebApp\bin\interfaces.xml" target="lib\interfaces.xml" />
<file src="..\_BuildOutput\WebApp\bin\log4net.dll" target="lib\log4net.dll" />
@@ -66,5 +71,6 @@
<file src="..\_BuildOutput\WebApp\bin\umbraco.XmlSerializers.dll" target="lib\umbraco.XmlSerializers.dll" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
<file src="..\_BuildOutput\WebApp\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
<file src="tools\install.core.ps1" target="tools\install.ps1" />
</files>
</package>
+7 -9
View File
@@ -2,9 +2,9 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>UmbracoCms</id>
<version>6.1.2</version>
<version>6.2.3</version>
<title>Umbraco Cms</title>
<authors>Morten Christensen</authors>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://umbraco.codeplex.com/license</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
@@ -19,11 +19,9 @@
</dependencies>
</metadata>
<files>
<file src="..\_BuildOutput\WebApp\bin\amd64\**" target="Content\bin\amd64" />
<file src="..\_BuildOutput\WebApp\bin\x86\**" target="Content\bin\x86" />
<file src="..\_BuildOutput\Configs\**" target="Content\config" exclude="..\_BuildOutput\Configs\Web.config.transform" />
<file src="..\_BuildOutput\WebApp\css\**" target="Content\css" />
<file src="..\_BuildOutput\WebApp\macroScripts\**" target="Content\macroScripts" />
<file src="..\_BuildOutput\WebApp\macroScripts\**" target="Content\macroScripts" exclude="..\_BuildOutput\WebApp\macroScripts\Web.config" />
<file src="..\_BuildOutput\WebApp\masterpages\**" target="Content\masterpages" />
<file src="..\_BuildOutput\WebApp\media\**" target="Content\media" />
<file src="..\_BuildOutput\WebApp\scripts\**" target="Content\scripts" />
@@ -32,15 +30,15 @@
<file src="..\_BuildOutput\WebApp\xslt\**" target="Content\xslt" />
<file src="..\_BuildOutput\WebApp\default.aspx" target="Content\default.aspx" />
<file src="..\_BuildOutput\WebApp\Web.config" target="Content\Web.config" />
<file src="..\_BuildOutput\WebApp\Global.asax" target="Content\Global.asax" />
<file src="..\_BuildOutput\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
<file src="..\_BuildOutput\WebApp\App_Code\**" target="UmbracoFiles\App_Code" />
<file src="..\_BuildOutput\WebApp\App_Data\**" target="UmbracoFiles\App_Data" />
<file src="..\_BuildOutput\WebApp\App_Plugins\**" target="UmbracoFiles\App_Plugins" />
<file src="..\_BuildOutput\WebApp\App_Plugins\**" target="UmbracoFiles\App_Plugins" />
<file src="..\_BuildOutput\WebApp\bin\amd64\**" target="UmbracoFiles\bin\amd64" />
<file src="..\_BuildOutput\WebApp\bin\x86\**" target="UmbracoFiles\bin\x86" />
<file src="..\_BuildOutput\WebApp\config\splashes\**" target="UmbracoFiles\config\splashes" />
<file src="..\_BuildOutput\WebApp\install\**" target="UmbracoFiles\install" />
<file src="..\_BuildOutput\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="..\_BuildOutput\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
<file src="..\_BuildOutput\WebApp\Global.asax" target="UmbracoFiles\Global.asax" />
<file src="..\_BuildOutput\WebApp\Web.config" target="UmbracoFiles\Web.config" />
<file src="tools\install.ps1" target="tools\install.ps1" />
<file src="tools\Readme.txt" target="tools\Readme.txt" />
+50
View File
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<UmbracoVersion>6.2.4</UmbracoVersion>
</PropertyGroup>
<Target Name="CopyUmbracoFilesToWebRoot" BeforeTargets="AfterBuild">
<PropertyGroup>
<UmbracoFilesFolder>..\packages\UmbracoCms.$(UmbracoVersion)\UmbracoFiles\</UmbracoFilesFolder>
</PropertyGroup>
<ItemGroup>
<UmbracoFiles Include="$(UmbracoFilesFolder)**\*" />
</ItemGroup>
<Copy SourceFiles="%(UmbracoFiles.FullPath)" DestinationFiles="%(RecursiveDir)%(Filename)%(Extension)" Condition="!Exists('%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<Target Name="AddUmbracoFilesToOutput">
<!-- With help from: http://blog.samstephens.co.nz/2010-10-18/msbuild-including-extra-files-multiple-builds/ -->
<ItemGroup>
<CustomFilesToInclude Include=".\App_Browsers\**\*">
<Dir>App_Browsers</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\App_Code\**\*">
<Dir>App_Code</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\App_Plugins\**\*">
<Dir>App_Plugins</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\bin\amd64\**\*">
<Dir>bin\amd64</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\bin\x86\**\*">
<Dir>bin\x86</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\Config\Splashes\**\*">
<Dir>Config\Splashes</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\umbraco\**\*">
<Dir>umbraco</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\umbraco_client\**\*">
<Dir>umbraco_client</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\Global.asax">
<Dir>.</Dir>
</CustomFilesToInclude>
<FilesForPackagingFromProject Include="@(CustomFilesToInclude)">
<DestinationRelativePath>%(CustomFilesToInclude.Dir)\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
</Project>
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="AddUmbracoFilesToOutput">
<ItemGroup>
<UmbracoFiles Include=".\umbraco\**\*;" />
<UmbracoClientFiles Include=".\umbraco_client\**\*;" />
<AppBrowsersFiles Include=".\App_Browsers\**\*" />
<FilesForPackagingFromProject Include="%(UmbracoFiles.Identity)">
<DestinationRelativePath>umbraco\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
<FilesForPackagingFromProject Include="%(UmbracoClientFiles.Identity)">
<DestinationRelativePath>umbraco_client\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
<FilesForPackagingFromProject Include="%(AppBrowsersFiles.Identity)">
<DestinationRelativePath>App_Browsers\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
</Project>
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
AddUmbracoFilesToOutput;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
AddUmbracoFilesToOutput;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>
</Project>
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="AddUmbracoFilesToOutput">
<ItemGroup>
<UmbracoFiles Include=".\umbraco\**\*;" />
<UmbracoClientFiles Include=".\umbraco_client\**\*;" />
<AppBrowsersFiles Include=".\App_Browsers\**\*" />
<FilesForPackagingFromProject Include="%(UmbracoFiles.Identity)">
<DestinationRelativePath>umbraco\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
<FilesForPackagingFromProject Include="%(UmbracoClientFiles.Identity)">
<DestinationRelativePath>umbraco_client\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
<FilesForPackagingFromProject Include="%(AppBrowsersFiles.Identity)">
<DestinationRelativePath>App_Browsers\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
</Project>
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
AddUmbracoFilesToOutput;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
AddUmbracoFilesToOutput;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>
</Project>
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="AddUmbracoFilesToOutput">
<ItemGroup>
<UmbracoFiles Include=".\umbraco\**\*;" />
<UmbracoClientFiles Include=".\umbraco_client\**\*;" />
<AppBrowsersFiles Include=".\App_Browsers\**\*" />
<FilesForPackagingFromProject Include="%(UmbracoFiles.Identity)">
<DestinationRelativePath>umbraco\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
<FilesForPackagingFromProject Include="%(UmbracoClientFiles.Identity)">
<DestinationRelativePath>umbraco_client\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
<FilesForPackagingFromProject Include="%(AppBrowsersFiles.Identity)">
<DestinationRelativePath>App_Browsers\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
</Project>
+14 -5
View File
@@ -1,8 +1,17 @@
A note about running Umbraco from Visual Studio.
When upgrading your website using nuget a backup of config files and web.config will be created. Only the web.config will
be overwritten by default to ensure that it has the necessary settings from the current release. This means that you'll
have to merge the files if you made any changes to the previous config files.
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
file (and config files in the config folder).
We will overwrite Web.config anyway but we keep a backup in the App_Data\NuGetBackup folder. There you'll
find a folder with the current date and time in which the backup has been placed. Make sure to merge the
new file with the old backup files before you proceed.
The web.config will be overwritten by default to ensure that it has the necessary settings from the current release.
We've also overwritten all the files in the Umbraco and Umbraco_Client folder, these have also been backed up in
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or a package
might have added. Only the existing files were overwritten. If you customized anything then make sure to do a compare
and merge with the NuGetBackup folder.
The config files found in the config folder will usually not be changed for patch releases, so they can usually be skipped,
but the web.config will have to have its previous "umbracoConfigurationStatus"-appsetting and "umbracoDbDSN" connection string
copied over (as a minimum).
@@ -10,8 +19,8 @@ copied over (as a minimum).
This nuget package includes build targets that extends the creation of a deploy package, which is generated by
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
Publish this won't affect you.
These folders will now be automatically included when creating a deploy package or publishing to the file system:
umbraco and umbraco_client.
These things will now be automatically included when creating a deploy package or publishing to the file system:
umbraco, umbraco_client, config\splashes and global.asax.
Please read the release notes on our.umbraco.org:
http://our.umbraco.org/contribute/releases
+24
View File
@@ -0,0 +1,24 @@
param($rootPath, $toolsPath, $package, $project)
if ($project) {
$dateTime = Get-Date -Format yyyyMMdd-HHmmss
$backupPath = Join-Path (Split-Path $project.FullName -Parent) "\App_Data\NuGetBackup\$dateTime"
$copyLogsPath = Join-Path $backupPath "CopyLogs"
$projectDestinationPath = Split-Path $project.FullName -Parent
# Create backup folder and logs folder if it doesn't exist yet
New-Item -ItemType Directory -Force -Path $backupPath
New-Item -ItemType Directory -Force -Path $copyLogsPath
# After backing up, remove all dlls from bin folder in case dll files are included in the VS project
# See: http://issues.umbraco.org/issue/U4-4930
$umbracoBinFolder = Join-Path $projectDestinationPath "bin"
if(Test-Path $umbracoBinFolder) {
$umbracoBinBackupPath = Join-Path $backupPath "bin"
New-Item -ItemType Directory -Force -Path $umbracoBinBackupPath
robocopy $umbracoBinFolder $umbracoBinBackupPath /e /LOG:$copyLogsPath\UmbracoBinBackup.log
Remove-Item $umbracoBinFolder\*.dll -Force -Confirm:$false
}
}
+38 -18
View File
@@ -1,27 +1,47 @@
param($rootPath, $toolsPath, $package, $project)
if ($project) {
# Create a backup of extisting umbraco config files
$configPath = Join-Path (Split-Path $project.FullName -Parent) "\config"
$backupPath = Join-Path $configPath "\backup"
Get-ChildItem -path $configPath |
Where -filterscript {($_.Name.EndsWith("config"))} | Foreach-Object {
$newFileName = Join-Path $backupPath $_.Name.replace(".config",".config.backup")
New-Item -ItemType File -Path $newFileName -Force
Copy-Item $_.FullName $newFileName -Force
}
$dateTime = Get-Date -Format yyyyMMdd-HHmmss
$backupPath = Join-Path (Split-Path $project.FullName -Parent) "\App_Data\NuGetBackup\$dateTime"
$copyLogsPath = Join-Path $backupPath "CopyLogs"
# Create backup folder and logs folder if it doesn't exist yet
New-Item -ItemType Directory -Force -Path $backupPath
New-Item -ItemType Directory -Force -Path $copyLogsPath
# Create a backup of original web.config
$projectDestinationPath = Split-Path $project.FullName -Parent
$webConfigSource = Join-Path $projectDestinationPath "web.config"
$webConfigDestination = Join-Path $projectDestinationPath "web.config.backup"
Copy-Item $webConfigSource $webConfigDestination
# Copy umbraco files from package to project folder
$projectDestinationPath = Split-Path $project.FullName -Parent
$umbracoFilesPath = Join-Path $rootPath "UmbracoFiles\*"
Copy-Item $umbracoFilesPath $projectDestinationPath -recurse -force
$webConfigSource = Join-Path $projectDestinationPath "Web.config"
Copy-Item $webConfigSource $backupPath -Force
# Copy Web.config from package to project folder
$umbracoFilesPath = Join-Path $rootPath "UmbracoFiles\Web.config"
Copy-Item $umbracoFilesPath $projectDestinationPath -Force
# Copy umbraco and umbraco_files from package to project folder
# This is only done when these folders already exist because we
# only want to do this for upgrades
$umbracoFolder = Join-Path $projectDestinationPath "Umbraco"
if(Test-Path $umbracoFolder) {
$umbracoFolderSource = Join-Path $rootPath "UmbracoFiles\Umbraco"
$umbracoBackupPath = Join-Path $backupPath "Umbraco"
New-Item -ItemType Directory -Force -Path $umbracoBackupPath
robocopy $umbracoFolder $umbracoBackupPath /e /LOG:$copyLogsPath\UmbracoBackup.log
robocopy $umbracoFolderSource $umbracoFolder /is /it /e /xf UI.xml /LOG:$copyLogsPath\UmbracoCopy.log
}
$umbracoClientFolder = Join-Path $projectDestinationPath "Umbraco_Client"
if(Test-Path $umbracoClientFolder) {
$umbracoClientFolderSource = Join-Path $rootPath "UmbracoFiles\Umbraco_Client"
$umbracoClientBackupPath = Join-Path $backupPath "Umbraco_Client"
New-Item -ItemType Directory -Force -Path $umbracoClientBackupPath
robocopy $umbracoClientFolder $umbracoClientBackupPath /e /LOG:$copyLogsPath\UmbracoClientBackup.log
robocopy $umbracoClientFolderSource $umbracoClientFolder /is /it /e /LOG:$copyLogsPath\UmbracoClientCopy.log
}
# Open readme.txt file
$DTE.ItemOperations.OpenFile($toolsPath + '\Readme.txt')
}
+1
View File
@@ -80,6 +80,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Sql\Total.sql" />
<None Include="app.config" />
<None Include="packages.config" />
<None Include="Sql\Version4_1_Upgrade.sql" />
</ItemGroup>
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+138 -154
View File
@@ -12,7 +12,7 @@ using Umbraco.Core.Services;
namespace Umbraco.Core
{
/// <summary>
/// <summary>
/// the Umbraco Application context
/// </summary>
/// <remarks>
@@ -20,61 +20,45 @@ namespace Umbraco.Core
/// </remarks>
public class ApplicationContext : IDisposable
{
/// <summary>
/// Constructor
/// </summary>
internal ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext)
: this(dbContext, serviceContext, true)
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <param name="enableCache"></param>
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, bool enableCache)
: this(enableCache)
/// <param name="cache"></param>
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache)
{
if (dbContext == null) throw new ArgumentNullException("dbContext");
if (serviceContext == null) throw new ArgumentNullException("serviceContext");
if (cache == null) throw new ArgumentNullException("cache");
_databaseContext = dbContext;
_services = serviceContext;
_services = serviceContext;
ApplicationCache = cache;
}
/// <summary>
/// Empty constructor normally reserved for unit tests when a DatabaseContext or a ServiceContext is not
/// necessarily required or needs to be set after construction.
/// </summary>
internal ApplicationContext() : this(true)
{
}
/// <summary>
/// Constructor used to specify if we will enable application cache or not
/// Creates a basic app context
/// </summary>
/// <param name="enableCache"></param>
public ApplicationContext(bool enableCache)
/// <param name="cache"></param>
public ApplicationContext(CacheHelper cache)
{
//create a new application cache from the HttpRuntime.Cache
ApplicationCache = HttpRuntime.Cache == null
? new CacheHelper(new System.Web.Caching.Cache(), enableCache)
: new CacheHelper(HttpRuntime.Cache, enableCache);
ApplicationCache = cache;
}
/// <summary>
/// A method used to set and/or ensure that a global ApplicationContext singleton is created.
/// </summary>
/// <param name="appContext">
/// The instance to set on the global application singleton
/// </param>
/// <param name="replaceContext">If set to true and the singleton is already set, it will be replaced</param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(ApplicationContext appContext, bool replaceContext)
{
/// <summary>
/// A method used to set and/or ensure that a global ApplicationContext singleton is created.
/// </summary>
/// <param name="appContext">
/// The instance to set on the global application singleton
/// </param>
/// <param name="replaceContext">If set to true and the singleton is already set, it will be replaced</param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(ApplicationContext appContext, bool replaceContext)
{
if (ApplicationContext.Current != null)
{
if (!replaceContext)
@@ -82,56 +66,56 @@ namespace Umbraco.Core
}
ApplicationContext.Current = appContext;
return ApplicationContext.Current;
}
}
/// <summary>
/// A method used to create and ensure that a global ApplicationContext singleton is created.
/// </summary>
/// <param name="enableCache"></param>
/// <param name="replaceContext">
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// startup if for some reason the boot manager is not the umbraco boot manager.
/// </param>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, bool enableCache, bool replaceContext)
/// <summary>
/// A method used to create and ensure that a global ApplicationContext singleton is created.
/// </summary>
/// <param name="cache"></param>
/// <param name="replaceContext">
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// startup if for some reason the boot manager is not the umbraco boot manager.
/// </param>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, bool replaceContext)
{
if (ApplicationContext.Current != null)
{
if (!replaceContext)
return ApplicationContext.Current;
}
var ctx = new ApplicationContext(dbContext, serviceContext, enableCache);
var ctx = new ApplicationContext(dbContext, serviceContext, cache);
ApplicationContext.Current = ctx;
return ApplicationContext.Current;
}
/// <summary>
/// Singleton accessor
/// </summary>
public static ApplicationContext Current { get; internal set; }
/// <summary>
/// Singleton accessor
/// </summary>
public static ApplicationContext Current { get; internal set; }
/// <summary>
/// Returns the application wide cache accessor
/// </summary>
/// <remarks>
/// Any caching that is done in the application (app wide) should be done through this property
/// </remarks>
public CacheHelper ApplicationCache { get; private set; }
/// <summary>
/// Returns the application wide cache accessor
/// </summary>
/// <remarks>
/// Any caching that is done in the application (app wide) should be done through this property
/// </remarks>
public CacheHelper ApplicationCache { get; private set; }
// IsReady is set to true by the boot manager once it has successfully booted
// IsReady is set to true by the boot manager once it has successfully booted
// note - the original umbraco module checks on content.Instance in umbraco.dll
// now, the boot task that setup the content store ensures that it is ready
bool _isReady = false;
readonly System.Threading.ManualResetEventSlim _isReadyEvent = new System.Threading.ManualResetEventSlim(false);
private DatabaseContext _databaseContext;
private ServiceContext _services;
readonly ManualResetEventSlim _isReadyEvent = new ManualResetEventSlim(false);
private DatabaseContext _databaseContext;
private ServiceContext _services;
public bool IsReady
public bool IsReady
{
get
{
@@ -141,14 +125,14 @@ namespace Umbraco.Core
{
AssertIsNotReady();
_isReady = value;
_isReadyEvent.Set();
_isReadyEvent.Set();
}
}
public bool WaitForReady(int timeout)
{
return _isReadyEvent.WaitHandle.WaitOne(timeout);
}
public bool WaitForReady(int timeout)
{
return _isReadyEvent.WaitHandle.WaitOne(timeout);
}
// notes
@@ -157,14 +141,14 @@ namespace Umbraco.Core
// the system is configured if they match
// if they don't, install runs, updates web.config (presumably) and updates GlobalSettings.ConfiguredStatus
//
// then there is Application["umbracoNeedConfiguration"] which makes no sense... getting rid of it...
// then there is Application["umbracoNeedConfiguration"] which makes no sense... getting rid of it... SD: I have actually remove that now!
//
public bool IsConfigured
{
// todo - we should not do this - ok for now
get
{
return Configured;
return Configured;
}
}
@@ -180,45 +164,45 @@ namespace Umbraco.Core
/// </remarks>
internal string OriginalRequestUrl { get; set; }
private bool Configured
{
get
{
try
{
string configStatus = ConfigurationStatus;
string currentVersion = UmbracoVersion.Current.ToString(3);
private bool Configured
{
get
{
try
{
string configStatus = ConfigurationStatus;
string currentVersion = UmbracoVersion.Current.ToString(3);
if (currentVersion != configStatus)
{
LogHelper.Info<ApplicationContext>("CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + "'");
}
if (currentVersion != configStatus)
{
LogHelper.Info<ApplicationContext>("CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + "'");
}
return (configStatus == currentVersion);
}
catch
{
return false;
}
}
}
private string ConfigurationStatus
{
get
{
try
{
return ConfigurationManager.AppSettings["umbracoConfigurationStatus"];
}
catch
{
return String.Empty;
}
}
}
return (configStatus == currentVersion);
}
catch
{
return false;
}
}
}
private string ConfigurationStatus
{
get
{
try
{
return ConfigurationManager.AppSettings["umbracoConfigurationStatus"];
}
catch
{
return String.Empty;
}
}
}
private void AssertIsReady()
{
@@ -232,39 +216,39 @@ namespace Umbraco.Core
throw new Exception("ApplicationContext has already been initialized.");
}
/// <summary>
/// Gets the current DatabaseContext
/// </summary>
/// <remarks>
/// Internal set is generally only used for unit tests
/// </remarks>
public DatabaseContext DatabaseContext
{
get
{
if (_databaseContext == null)
throw new InvalidOperationException("The DatabaseContext has not been set on the ApplicationContext");
return _databaseContext;
}
internal set { _databaseContext = value; }
}
/// <summary>
/// Gets the current ServiceContext
/// </summary>
/// <remarks>
/// Internal set is generally only used for unit tests
/// </remarks>
public ServiceContext Services
{
get
{
if (_services == null)
throw new InvalidOperationException("The ServiceContext has not been set on the ApplicationContext");
return _services;
}
internal set { _services = value; }
}
/// <summary>
/// Gets the current DatabaseContext
/// </summary>
/// <remarks>
/// Internal set is generally only used for unit tests
/// </remarks>
public DatabaseContext DatabaseContext
{
get
{
if (_databaseContext == null)
throw new InvalidOperationException("The DatabaseContext has not been set on the ApplicationContext");
return _databaseContext;
}
internal set { _databaseContext = value; }
}
/// <summary>
/// Gets the current ServiceContext
/// </summary>
/// <remarks>
/// Internal set is generally only used for unit tests
/// </remarks>
public ServiceContext Services
{
get
{
if (_services == null)
throw new InvalidOperationException("The ServiceContext has not been set on the ApplicationContext");
return _services;
}
internal set { _services = value; }
}
private volatile bool _disposed;
@@ -290,26 +274,26 @@ namespace Umbraco.Core
//clear the cache
if (ApplicationCache != null)
{
ApplicationCache.ClearAllCache();
ApplicationCache.ClearAllCache();
}
//reset all resolvers
ResolverCollection.ResetAll();
//reset resolution itself (though this should be taken care of by resetting any of the resolvers above)
Resolution.Reset();
//reset the instance objects
this.ApplicationCache = null;
if (_databaseContext != null) //need to check the internal field here
{
if (DatabaseContext.IsDatabaseConfigured)
{
DatabaseContext.Database.Dispose();
}
DatabaseContext.Database.Dispose();
}
}
this.DatabaseContext = null;
this.Services = null;
this._isReady = false; //set the internal field
// Indicate that the instance has been disposed.
_disposed = true;
}
+2
View File
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Umbraco.Core
+10
View File
@@ -160,5 +160,15 @@ namespace Umbraco.Core
{
return new Attempt<T>(condition, result, null);
}
/// <summary>
/// Implicity operator to check if the attempt was successful without having to access the 'success' property
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
public static implicit operator bool(Attempt<T> a)
{
return a.Success;
}
}
}
+8 -1
View File
@@ -1,3 +1,5 @@
using System;
namespace Umbraco.Core.Cache
{
@@ -9,6 +11,7 @@ namespace Umbraco.Core.Cache
public const string ApplicationTreeCacheKey = "ApplicationTreeCache";
public const string ApplicationsCacheKey = "ApplicationCache";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
public const string UserTypeCacheKey = "UserTypeCache";
public const string ContentItemCacheKey = "contentItem";
@@ -24,13 +27,16 @@ namespace Umbraco.Core.Cache
public const string MemberLibraryCacheKey = "UL_GetMember";
public const string MemberBusinessLogicCacheKey = "MemberCacheItem_";
public const string TemplateFrontEndCacheKey = "template";
public const string TemplateBusinessLogicCacheKey = "UmbracoTemplateCache";
public const string UserContextCacheKey = "UmbracoUserContext";
public const string UserContextTimeoutCacheKey = "UmbracoUserContextTimeout";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
public const string UserCacheKey = "UmbracoUser";
public const string UserPermissionsCacheKey = "UmbracoUserPermissions";
public const string ContentTypeCacheKey = "UmbracoContentType";
@@ -47,5 +53,6 @@ namespace Umbraco.Core.Cache
public const string StylesheetPropertyCacheKey = "UmbracoStylesheetProperty";
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
}
}
@@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Cache
{
/// <summary>
/// An abstract class for implementing a basic cache provider
/// </summary>
/// <remarks>
/// THIS MUST REMAIN INTERNAL UNTIL WE STREAMLINE HOW ALL CACHE IS HANDLED, WE NEED TO SUPPORT HTTP RUNTIME CACHE, IN MEMORY CACHE, ETC...
/// </remarks>
internal abstract class CacheProviderBase
{
public abstract void ClearAllCache();
public abstract void ClearCacheItem(string key);
public abstract void ClearCacheObjectTypes(string typeName);
public abstract void ClearCacheObjectTypes<T>();
public abstract void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate);
public abstract void ClearCacheByKeySearch(string keyStartsWith);
public abstract void ClearCacheByKeyExpression(string regexString);
public abstract IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith);
public abstract T GetCacheItem<T>(string cacheKey);
public abstract T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem);
}
}
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Caching;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Extensions for strongly typed access
/// </summary>
internal static class CacheProviderExtensions
{
public static T GetCacheItem<T>(this IRuntimeCacheProvider provider,
string cacheKey,
Func<T> getCacheItem,
TimeSpan? timeout,
bool isSliding = false,
CacheItemPriority priority = CacheItemPriority.Normal,
CacheItemRemovedCallback removedCallback = null,
string[] dependentFiles = null)
{
var result = provider.GetCacheItem(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles);
return result == null ? default(T) : result.TryConvertTo<T>().Result;
}
public static void InsertCacheItem<T>(this IRuntimeCacheProvider provider,
string cacheKey,
Func<T> getCacheItem,
TimeSpan? timeout = null,
bool isSliding = false,
CacheItemPriority priority = CacheItemPriority.Normal,
CacheItemRemovedCallback removedCallback = null,
string[] dependentFiles = null)
{
provider.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles);
}
public static IEnumerable<T> GetCacheItemsByKeySearch<T>(this ICacheProvider provider, string keyStartsWith)
{
var result = provider.GetCacheItemsByKeySearch(keyStartsWith);
return result.Select(x => x.TryConvertTo<T>().Result);
}
public static IEnumerable<T> GetCacheItemsByKeyExpression<T>(this ICacheProvider provider, string regexString)
{
var result = provider.GetCacheItemsByKeyExpression(regexString);
return result.Select(x => x.TryConvertTo<T>().Result);
}
public static T GetCacheItem<T>(this ICacheProvider provider, string cacheKey)
{
var result = provider.GetCacheItem(cacheKey);
if (result == null)
{
return default(T);
}
return result.TryConvertTo<T>().Result;
}
public static T GetCacheItem<T>(this ICacheProvider provider, string cacheKey, Func<T> getCacheItem)
{
var result = provider.GetCacheItem(cacheKey, () => getCacheItem());
if (result == null)
{
return default(T);
}
return result.TryConvertTo<T>().Result;
}
}
}
@@ -0,0 +1,204 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Umbraco.Core.Cache
{
internal abstract class DictionaryCacheProviderBase : ICacheProvider
{
// prefix cache keys so we know which one are ours
protected const string CacheItemPrefix = "umbrtmche";
// an object that represent a value that has not been created yet
protected readonly object ValueNotCreated = new object();
// manupulate the underlying cache entries
// these *must* be called from within the appropriate locks
// and use the full prefixed cache keys
protected abstract IEnumerable<DictionaryEntry> GetDictionaryEntries();
protected abstract void RemoveEntry(string key);
protected abstract object GetEntry(string key);
// read-write lock the underlying cache
protected abstract IDisposable ReadLock { get; }
protected abstract IDisposable WriteLock { get; }
protected string GetCacheKey(string key)
{
return string.Format("{0}-{1}", CacheItemPrefix, key);
}
protected object GetSafeLazyValue(Lazy<object> lazy, bool onlyIfValueIsCreated = false)
{
try
{
// if onlyIfValueIsCreated, do not trigger value creation
// must return something, though, to differenciate from null values
if (onlyIfValueIsCreated && lazy.IsValueCreated == false) return ValueNotCreated;
return lazy.Value;
}
catch
{
return null;
}
}
#region Clear
public virtual void ClearAllCache()
{
using (WriteLock)
{
foreach (var entry in GetDictionaryEntries()
.ToArray())
RemoveEntry((string) entry.Key);
}
}
public virtual void ClearCacheItem(string key)
{
var cacheKey = GetCacheKey(key);
using (WriteLock)
{
RemoveEntry(cacheKey);
}
}
public virtual void ClearCacheObjectTypes(string typeName)
{
using (WriteLock)
{
foreach (var entry in GetDictionaryEntries()
.Where(x =>
{
// entry.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
return value == null || value.GetType().ToString().InvariantEquals(typeName);
})
.ToArray())
RemoveEntry((string) entry.Key);
}
}
public virtual void ClearCacheObjectTypes<T>()
{
var typeOfT = typeof(T);
using (WriteLock)
{
foreach (var entry in GetDictionaryEntries()
.Where(x =>
{
// entry.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// compare on exact type, don't use "is"
// get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
return value == null || value.GetType() == typeOfT;
})
.ToArray())
RemoveEntry((string) entry.Key);
}
}
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
{
var typeOfT = typeof(T);
var plen = CacheItemPrefix.Length + 1;
using (WriteLock)
{
foreach (var entry in GetDictionaryEntries()
.Where(x =>
{
// entry.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// compare on exact type, don't use "is"
// get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
if (value == null) return true;
return value.GetType() == typeOfT
// run predicate on the 'public key' part only, ie without prefix
&& predicate(((string)x.Key).Substring(plen), (T)value);
}))
RemoveEntry((string) entry.Key);
}
}
public virtual void ClearCacheByKeySearch(string keyStartsWith)
{
var plen = CacheItemPrefix.Length + 1;
using (WriteLock)
{
foreach (var entry in GetDictionaryEntries()
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
.ToArray())
RemoveEntry((string) entry.Key);
}
}
public virtual void ClearCacheByKeyExpression(string regexString)
{
var plen = CacheItemPrefix.Length + 1;
using (WriteLock)
{
foreach (var entry in GetDictionaryEntries()
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
.ToArray())
RemoveEntry((string) entry.Key);
}
}
#endregion
#region Get
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
{
var plen = CacheItemPrefix.Length + 1;
IEnumerable<DictionaryEntry> entries;
using (ReadLock)
{
entries = GetDictionaryEntries()
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
.ToArray(); // evaluate while locked
}
return entries
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null); // backward compat, don't store null values in the cache
}
public virtual IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
{
const string prefix = CacheItemPrefix + "-";
var plen = prefix.Length;
IEnumerable<DictionaryEntry> entries;
using (ReadLock)
{
entries = GetDictionaryEntries()
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
.ToArray(); // evaluate while locked
}
return entries
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null); // backward compat, don't store null values in the cache
}
public virtual object GetCacheItem(string cacheKey)
{
cacheKey = GetCacheKey(cacheKey);
Lazy<object> result;
using (ReadLock)
{
result = GetEntry(cacheKey) as Lazy<object>; // null if key not found
}
return result == null ? null : GetSafeLazyValue(result); // return exceptions as null
}
public abstract object GetCacheItem(string cacheKey, Func<object> getCacheItem);
#endregion
}
}
@@ -0,0 +1,125 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Umbraco.Core.Cache
{
/// <summary>
/// A cache provider that caches items in the HttpContext.Items
/// </summary>
internal class HttpRequestCacheProvider : DictionaryCacheProviderBase
{
// context provider
// the idea is that there is only one, application-wide HttpRequestCacheProvider instance,
// that is initialized with a method that returns the "current" context.
// NOTE
// but then it is initialized with () => new HttpContextWrapper(HttpContent.Current)
// which is higly inefficient because it creates a new wrapper each time we refer to _context()
// so replace it with _context1 and _context2 below + a way to get context.Items.
//private readonly Func<HttpContextBase> _context;
// NOTE
// and then in almost 100% cases _context2 will be () => HttpContext.Current
// so why not bring that logic in here and fallback on to HttpContext.Current when
// _context1 is null?
//private readonly HttpContextBase _context1;
//private readonly Func<HttpContext> _context2;
private readonly HttpContextBase _context;
private IDictionary ContextItems
{
//get { return _context1 != null ? _context1.Items : _context2().Items; }
get { return _context != null ? _context.Items : HttpContext.Current.Items; }
}
// for unit tests
public HttpRequestCacheProvider(HttpContextBase context)
{
_context = context;
}
// main constructor
// will use HttpContext.Current
public HttpRequestCacheProvider(/*Func<HttpContext> context*/)
{
//_context2 = context;
}
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
{
const string prefix = CacheItemPrefix + "-";
return ContextItems.Cast<DictionaryEntry>()
.Where(x => x.Key is string && ((string)x.Key).StartsWith(prefix));
}
protected override void RemoveEntry(string key)
{
ContextItems.Remove(key);
}
protected override object GetEntry(string key)
{
return ContextItems[key];
}
#region Lock
protected override IDisposable ReadLock
{
// there's no difference between ReadLock and WriteLock here
get { return WriteLock; }
}
protected override IDisposable WriteLock
{
// NOTE
// could think about just overriding base.Locker to return a different
// object but then we'd create a ReaderWriterLockSlim per request,
// which is less efficient than just using a basic monitor lock.
get
{
return new MonitorLock(ContextItems.SyncRoot);
}
}
#endregion
#region Get
public override object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
cacheKey = GetCacheKey(cacheKey);
Lazy<object> result;
using (WriteLock)
{
result = ContextItems[cacheKey] as Lazy<object>; // null if key not found
// cannot create value within the lock, so if result.IsValueCreated is false, just
// do nothing here - means that if creation throws, a race condition could cause
// more than one thread to reach the return statement below and throw - accepted.
if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
{
result = new Lazy<object>(getCacheItem);
ContextItems[cacheKey] = result;
}
}
// this may throw if getCacheItem throws, but this is the only place where
// it would throw as everywhere else we use GetLazySaveValue() to hide exceptions
// and pretend exceptions were never inserted into cache to begin with.
return result.Value;
}
#endregion
#region Insert
#endregion
}
}
+136 -316
View File
@@ -2,382 +2,202 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web.Caching;
using Umbraco.Core.Logging;
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
namespace Umbraco.Core.Cache
{
/// <summary>
/// A CacheProvider that wraps the logic of the HttpRuntime.Cache
/// </summary>
internal class HttpRuntimeCacheProvider : RuntimeCacheProviderBase
internal class HttpRuntimeCacheProvider : DictionaryCacheProviderBase, IRuntimeCacheProvider
{
// locker object that supports upgradeable read locking
// does not need to support recursion if we implement the cache correctly and ensure
// that methods cannot be reentrant, ie we do NOT create values while holding a lock.
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
private readonly System.Web.Caching.Cache _cache;
private static readonly object Locker = new object();
public HttpRuntimeCacheProvider(System.Web.Caching.Cache cache)
{
_cache = cache;
}
/// <summary>
/// Clears everything in umbraco's runtime cache, which means that not only
/// umbraco content is removed, but also other cache items from pages running in
/// the same application / website. Use with care :-)
/// </summary>
public override void ClearAllCache()
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
{
var cacheEnumerator = _cache.GetEnumerator();
while (cacheEnumerator.MoveNext())
{
_cache.Remove(cacheEnumerator.Key.ToString());
}
const string prefix = CacheItemPrefix + "-";
return _cache.Cast<DictionaryEntry>()
.Where(x => x.Key is string && ((string) x.Key).StartsWith(prefix));
}
/// <summary>
/// Clears the item in umbraco's runtime cache with the given key
/// </summary>
/// <param name="key">Key</param>
public override void ClearCacheItem(string key)
protected override void RemoveEntry(string key)
{
// NH 10 jan 2012
// Patch by the always wonderful Stéphane Gay to avoid cache null refs
lock (Locker)
{
if (_cache[key] == null) return;
_cache.Remove(key); ;
}
_cache.Remove(key);
}
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type name as the
/// input parameter. (using [object].GetType())
/// </summary>
/// <param name="typeName">The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument"</param>
public override void ClearCacheObjectTypes(string typeName)
protected override object GetEntry(string key)
{
try
{
lock (Locker)
{
foreach (DictionaryEntry c in _cache)
{
if (_cache[c.Key.ToString()] != null
&& _cache[c.Key.ToString()].GetType().ToString().InvariantEquals(typeName))
{
_cache.Remove(c.Key.ToString());
}
}
}
}
catch (Exception e)
{
LogHelper.Error<CacheHelper>("Cache clearing error", e);
}
return _cache.Get(key);
}
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type specified
/// </summary>
public override void ClearCacheObjectTypes<T>()
#region Lock
protected override IDisposable ReadLock
{
try
{
lock (Locker)
{
foreach (DictionaryEntry c in _cache)
{
if (_cache[c.Key.ToString()] != null
&& _cache[c.Key.ToString()].GetType() == typeof(T))
{
_cache.Remove(c.Key.ToString());
}
}
}
}
catch (Exception e)
{
LogHelper.Error<CacheHelper>("Cache clearing error", e);
}
get { return new ReadLock(_locker); }
}
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type specified that satisfy the predicate
/// </summary>
public override void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
protected override IDisposable WriteLock
{
try
{
lock (Locker)
{
foreach (DictionaryEntry c in _cache)
{
var key = c.Key.ToString();
if (_cache[key] != null
&& _cache[key] is T
&& predicate(key, (T)_cache[key]))
{
_cache.Remove(c.Key.ToString());
}
}
}
}
catch (Exception e)
{
LogHelper.Error<CacheHelper>("Cache clearing error", e);
}
get { return new WriteLock(_locker); }
}
/// <summary>
/// Clears all cache items that starts with the key passed.
/// </summary>
/// <param name="keyStartsWith">The start of the key</param>
public override void ClearCacheByKeySearch(string keyStartsWith)
{
foreach (DictionaryEntry c in _cache)
{
if (c.Key is string && ((string)c.Key).InvariantStartsWith(keyStartsWith))
{
ClearCacheItem((string)c.Key);
}
}
}
#endregion
/// <summary>
/// Clears all cache items that have a key that matches the regular expression
/// </summary>
/// <param name="regexString"></param>
public override void ClearCacheByKeyExpression(string regexString)
{
foreach (DictionaryEntry c in _cache)
{
if (c.Key is string && Regex.IsMatch(((string)c.Key), regexString))
{
ClearCacheItem((string)c.Key);
}
}
}
public override IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
{
return (from DictionaryEntry c in _cache
where c.Key is string && ((string)c.Key).InvariantStartsWith(keyStartsWith)
select c.Value.TryConvertTo<T>()
into attempt
where attempt.Success
select attempt.Result).ToList();
}
/// <summary>
/// Returns a cache item by key, does not update the cache if it isn't there.
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <returns></returns>
public override TT GetCacheItem<TT>(string cacheKey)
{
var result = _cache.Get(cacheKey);
if (result == null)
{
return default(TT);
}
return result.TryConvertTo<TT>().Result;
}
#region Get
/// <summary>
/// Gets (and adds if necessary) an item from the cache with all of the default parameters
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
public override TT GetCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
public override object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
return GetCacheItem(cacheKey, CacheItemPriority.Normal, null, null, null, getCacheItem, Locker);
return GetCacheItem(cacheKey, getCacheItem, null, dependentFiles: null);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// This overload is here for legacy purposes
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
public override TT GetCacheItem<TT>(string cacheKey,
TimeSpan? timeout, Func<TT> getCacheItem)
{
return GetCacheItem(cacheKey, null, timeout, getCacheItem);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
public override TT GetCacheItem<TT>(string cacheKey,
CacheItemRemovedCallback refreshAction, TimeSpan? timeout,
Func<TT> getCacheItem)
{
return GetCacheItem(cacheKey, CacheItemPriority.Normal, refreshAction, timeout, getCacheItem);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="timeout"></param>
/// <param name="isSliding"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <param name="removedCallback"></param>
/// <param name="dependency"></param>
/// <returns></returns>
public override TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan? timeout,
Func<TT> getCacheItem)
internal object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
{
return GetCacheItem(cacheKey, priority, refreshAction, null, timeout, getCacheItem);
}
cacheKey = GetCacheKey(cacheKey);
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
public override TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan? timeout,
Func<TT> getCacheItem)
{
return GetCacheItem(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem, Locker);
}
// NOTE - because we don't know what getCacheItem does, how long it will take and whether it will hang,
// getCacheItem should run OUTSIDE of the global application lock else we run into lock contention and
// nasty performance issues.
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <param name="syncLock"></param>
/// <returns></returns>
private TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority, CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency, TimeSpan? timeout, Func<TT> getCacheItem, object syncLock)
{
var result = _cache.Get(cacheKey);
if (result == null)
// So.... we insert a Lazy<object> in the cache while holding the global application lock, and then rely
// on the Lazy lock to ensure that getCacheItem runs once and everybody waits on it, while the global
// application lock has been released.
// NOTE
// The Lazy value creation may produce a null value.
// Must make sure (for backward compatibility) that we pretend they are not in the cache.
// So if we find an entry in the cache that already has its value created and is null,
// pretend it was not there. If value is not already created, wait... and return null, that's
// what prior code did.
// NOTE
// The Lazy value creation may throw.
// So... the null value _will_ be in the cache but never returned
Lazy<object> result;
// Fast!
// Only one thread can enter an UpgradeableReadLock at a time, but it does not prevent other
// threads to enter a ReadLock in the meantime -- only upgrading to WriteLock will prevent all
// reads. We first try with a normal ReadLock for maximum concurrency and take the penalty of
// having to re-lock in case there's no value. Would need to benchmark to figure out whether
// it's worth it, though...
using (new ReadLock(_locker))
{
lock (syncLock)
result = _cache.Get(cacheKey) as Lazy<object>; // null if key not found
}
var value = result == null ? null : GetSafeLazyValue(result);
if (value != null) return value;
using (var lck = new UpgradeableReadLock(_locker))
{
result = _cache.Get(cacheKey) as Lazy<object>; // null if key not found
// cannot create value within the lock, so if result.IsValueCreated is false, just
// do nothing here - means that if creation throws, a race condition could cause
// more than one thread to reach the return statement below and throw - accepted.
if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
{
result = _cache.Get(cacheKey);
if (result == null)
{
result = getCacheItem();
if (result != null)
{
//we use Insert instead of add if for some crazy reason there is now a cache with the cache key in there, it will just overwrite it.
_cache.Insert(cacheKey, result, cacheDependency,
timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value),
TimeSpan.Zero, priority, refreshAction);
}
}
result = new Lazy<object>(getCacheItem);
var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
lck.UpgradeToWriteLock();
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
}
}
return result.TryConvertTo<TT>().Result;
// this may throw if getCacheItem throws, but this is the only place where
// it would throw as everywhere else we use GetLazySaveValue() to hide exceptions
// and pretend exceptions were never inserted into cache to begin with.
return result.Value;
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="getCacheItem"></param>
public override void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
Func<T> getCacheItem)
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
{
InsertCacheItem(cacheKey, priority, null, null, null, getCacheItem);
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
public override void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
TimeSpan? timeout,
Func<T> getCacheItem)
{
InsertCacheItem(cacheKey, priority, null, null, timeout, getCacheItem);
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
public override void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
TimeSpan? timeout,
Func<T> getCacheItem)
{
InsertCacheItem(cacheKey, priority, null, cacheDependency, timeout, getCacheItem);
}
/// <summary>
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
public override void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan? timeout,
Func<T> getCacheItem)
{
object result = getCacheItem();
if (result != null)
CacheDependency dependency = null;
if (dependentFiles != null && dependentFiles.Any())
{
//we use Insert instead of add if for some crazy reason there is now a cache with the cache key in there, it will just overwrite it.
_cache.Insert(cacheKey, result, cacheDependency,
timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value),
TimeSpan.Zero, priority, refreshAction);
dependency = new CacheDependency(dependentFiles);
}
return GetCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency);
}
#endregion
#region Insert
/// <summary>
/// This overload is here for legacy purposes
/// </summary>
/// <param name="cacheKey"></param>
/// <param name="getCacheItem"></param>
/// <param name="timeout"></param>
/// <param name="isSliding"></param>
/// <param name="priority"></param>
/// <param name="removedCallback"></param>
/// <param name="dependency"></param>
internal void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
{
// NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
// and make sure we don't store a null value.
var result = new Lazy<object>(getCacheItem);
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
if (value == null) return; // do not store null values (backward compat)
cacheKey = GetCacheKey(cacheKey);
var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
using (new WriteLock(_locker))
{
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
}
}
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
{
CacheDependency dependency = null;
if (dependentFiles != null && dependentFiles.Any())
{
dependency = new CacheDependency(dependentFiles);
}
InsertCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency);
}
#endregion
}
}
+30
View File
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Cache
{
/// <summary>
/// An abstract class for implementing a basic cache provider
/// </summary>
public interface ICacheProvider
{
void ClearAllCache();
void ClearCacheItem(string key);
void ClearCacheObjectTypes(string typeName);
void ClearCacheObjectTypes<T>();
void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate);
void ClearCacheByKeySearch(string keyStartsWith);
void ClearCacheByKeyExpression(string regexString);
IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith);
IEnumerable<object> GetCacheItemsByKeyExpression(string regexString);
/// <summary>
/// Returns an item with a given key
/// </summary>
/// <param name="cacheKey"></param>
/// <returns></returns>
object GetCacheItem(string cacheKey);
object GetCacheItem(string cacheKey, Func<object> getCacheItem);
}
}
@@ -0,0 +1,35 @@
using System;
using System.Runtime.Caching;
using System.Text;
using System.Web.Caching;
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
namespace Umbraco.Core.Cache
{
/// <summary>
/// An abstract class for implementing a runtime cache provider
/// </summary>
/// <remarks>
/// </remarks>
public interface IRuntimeCacheProvider : ICacheProvider
{
object GetCacheItem(
string cacheKey,
Func<object> getCacheItem,
TimeSpan? timeout,
bool isSliding = false,
CacheItemPriority priority = CacheItemPriority.Normal,
CacheItemRemovedCallback removedCallback = null,
string[] dependentFiles = null);
void InsertCacheItem(
string cacheKey,
Func<object> getCacheItem,
TimeSpan? timeout = null,
bool isSliding = false,
CacheItemPriority priority = CacheItemPriority.Normal,
CacheItemRemovedCallback removedCallback = null,
string[] dependentFiles = null);
}
}
+24 -42
View File
@@ -5,85 +5,67 @@ using System.Web.Caching;
namespace Umbraco.Core.Cache
{
internal class NullCacheProvider : RuntimeCacheProviderBase
internal class NullCacheProvider : IRuntimeCacheProvider
{
public override void ClearAllCache()
public virtual void ClearAllCache()
{
}
public override void ClearCacheItem(string key)
public virtual void ClearCacheItem(string key)
{
}
public override void ClearCacheObjectTypes(string typeName)
public virtual void ClearCacheObjectTypes(string typeName)
{
}
public override void ClearCacheObjectTypes<T>()
public virtual void ClearCacheObjectTypes<T>()
{
}
public override void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
{
}
public override void ClearCacheByKeySearch(string keyStartsWith)
public virtual void ClearCacheByKeySearch(string keyStartsWith)
{
}
public override void ClearCacheByKeyExpression(string regexString)
public virtual void ClearCacheByKeyExpression(string regexString)
{
}
public override IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
{
return Enumerable.Empty<T>();
return Enumerable.Empty<object>();
}
public override T GetCacheItem<T>(string cacheKey)
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
{
return default(T);
return Enumerable.Empty<object>();
}
public override T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem)
public virtual object GetCacheItem(string cacheKey)
{
return default(object);
}
public virtual object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
return getCacheItem();
}
public override T GetCacheItem<T>(string cacheKey, TimeSpan? timeout, Func<T> getCacheItem)
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
{
return getCacheItem();
}
public override T GetCacheItem<T>(string cacheKey, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem)
{
return getCacheItem();
}
public override T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem)
{
return getCacheItem();
}
public override T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem)
{
return getCacheItem();
}
public override void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, Func<T> getCacheItem)
{
}
public override void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, TimeSpan? timeout, Func<T> getCacheItem)
{
}
public override void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem)
{
}
public override void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem)
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
{
}
}
}
@@ -0,0 +1,288 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Caching;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web.Caching;
using Umbraco.Core.Logging;
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
namespace Umbraco.Core.Cache
{
/// <summary>
/// A cache provider that wraps the logic of a System.Runtime.Caching.ObjectCache
/// </summary>
internal class ObjectCacheRuntimeCacheProvider : IRuntimeCacheProvider
{
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
internal ObjectCache MemoryCache;
// an object that represent a value that has not been created yet
protected readonly object ValueNotCreated = new object();
public ObjectCacheRuntimeCacheProvider()
{
MemoryCache = new MemoryCache("in-memory");
}
protected object GetSafeLazyValue(Lazy<object> lazy, bool onlyIfValueIsCreated = false)
{
try
{
// if onlyIfValueIsCreated, do not trigger value creation
// must return something, though, to differenciate from null values
if (onlyIfValueIsCreated && lazy.IsValueCreated == false) return ValueNotCreated;
return lazy.Value;
}
catch
{
return null;
}
}
#region Clear
public virtual void ClearAllCache()
{
using (new WriteLock(_locker))
{
MemoryCache.DisposeIfDisposable();
MemoryCache = new MemoryCache("in-memory");
}
}
public virtual void ClearCacheItem(string key)
{
using (new WriteLock(_locker))
{
if (MemoryCache[key] == null) return;
MemoryCache.Remove(key);
}
}
public virtual void ClearCacheObjectTypes(string typeName)
{
using (new WriteLock(_locker))
{
foreach (var key in MemoryCache
.Where(x =>
{
// x.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
return value == null || value.GetType().ToString().InvariantEquals(typeName);
})
.Select(x => x.Key)
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
}
public virtual void ClearCacheObjectTypes<T>()
{
using (new WriteLock(_locker))
{
var typeOfT = typeof (T);
foreach (var key in MemoryCache
.Where(x =>
{
// x.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
return value == null || value.GetType() == typeOfT;
})
.Select(x => x.Key)
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
}
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
{
using (new WriteLock(_locker))
{
var typeOfT = typeof(T);
foreach (var key in MemoryCache
.Where(x =>
{
// x.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
if (value == null) return true;
return value.GetType() == typeOfT
&& predicate(x.Key, (T) value);
})
.Select(x => x.Key)
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
}
public virtual void ClearCacheByKeySearch(string keyStartsWith)
{
using (new WriteLock(_locker))
{
foreach (var key in MemoryCache
.Where(x => x.Key.InvariantStartsWith(keyStartsWith))
.Select(x => x.Key)
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
}
public virtual void ClearCacheByKeyExpression(string regexString)
{
using (new WriteLock(_locker))
{
foreach (var key in MemoryCache
.Where(x => Regex.IsMatch(x.Key, regexString))
.Select(x => x.Key)
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
}
#endregion
#region Get
public IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
{
KeyValuePair<string, object>[] entries;
using (new ReadLock(_locker))
{
entries = MemoryCache
.Where(x => x.Key.InvariantStartsWith(keyStartsWith))
.ToArray(); // evaluate while locked
}
return entries
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null) // backward compat, don't store null values in the cache
.ToList();
}
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
{
KeyValuePair<string, object>[] entries;
using (new ReadLock(_locker))
{
entries = MemoryCache
.Where(x => Regex.IsMatch(x.Key, regexString))
.ToArray(); // evaluate while locked
}
return entries
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null) // backward compat, don't store null values in the cache
.ToList();
}
public object GetCacheItem(string cacheKey)
{
Lazy<object> result;
using (new ReadLock(_locker))
{
result = MemoryCache.Get(cacheKey) as Lazy<object>; // null if key not found
}
return result == null ? null : GetSafeLazyValue(result); // return exceptions as null
}
public object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
return GetCacheItem(cacheKey, getCacheItem, null);
}
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal,CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
{
// see notes in HttpRuntimeCacheProvider
Lazy<object> result;
using (var lck = new UpgradeableReadLock(_locker))
{
result = MemoryCache.Get(cacheKey) as Lazy<object>;
if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
{
result = new Lazy<object>(getCacheItem);
var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
lck.UpgradeToWriteLock();
MemoryCache.Set(cacheKey, result, policy);
}
}
return result.Value;
}
#endregion
#region Insert
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
{
// NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
// and make sure we don't store a null value.
var result = new Lazy<object>(getCacheItem);
var value = result.Value; // force evaluation now
if (value == null) return; // do not store null values (backward compat)
var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
MemoryCache.Set(cacheKey, result, policy);
}
#endregion
private static CacheItemPolicy GetPolicy(TimeSpan? timeout = null, bool isSliding = false, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
{
var absolute = isSliding ? ObjectCache.InfiniteAbsoluteExpiration : (timeout == null ? ObjectCache.InfiniteAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
var sliding = isSliding == false ? ObjectCache.NoSlidingExpiration : (timeout ?? ObjectCache.NoSlidingExpiration);
var policy = new CacheItemPolicy
{
AbsoluteExpiration = absolute,
SlidingExpiration = sliding
};
if (dependentFiles != null && dependentFiles.Any())
{
policy.ChangeMonitors.Add(new HostFileChangeMonitor(dependentFiles.ToList()));
}
if (removedCallback != null)
{
policy.RemovedCallback = arguments =>
{
//convert the reason
var reason = CacheItemRemovedReason.Removed;
switch (arguments.RemovedReason)
{
case CacheEntryRemovedReason.Removed:
reason = CacheItemRemovedReason.Removed;
break;
case CacheEntryRemovedReason.Expired:
reason = CacheItemRemovedReason.Expired;
break;
case CacheEntryRemovedReason.Evicted:
reason = CacheItemRemovedReason.Underused;
break;
case CacheEntryRemovedReason.ChangeMonitorChanged:
reason = CacheItemRemovedReason.Expired;
break;
case CacheEntryRemovedReason.CacheSpecificEviction:
reason = CacheItemRemovedReason.Underused;
break;
}
//call the callback
removedCallback(arguments.CacheItem.Key, arguments.CacheItem.Value, reason);
};
}
return policy;
}
}
}
@@ -1,24 +0,0 @@
using System;
using System.Text;
using System.Web.Caching;
namespace Umbraco.Core.Cache
{
/// <summary>
/// An abstract class for implementing a runtime cache provider
/// </summary>
/// <remarks>
/// THIS MUST REMAIN INTERNAL UNTIL WE STREAMLINE HOW ALL CACHE IS HANDLED, WE NEED TO SUPPORT HTTP RUNTIME CACHE, IN MEMORY CACHE, REQUEST CACHE, ETC...
/// </remarks>
internal abstract class RuntimeCacheProviderBase : CacheProviderBase
{
public abstract T GetCacheItem<T>(string cacheKey, TimeSpan? timeout, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, TimeSpan? timeout, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
}
}
+35 -35
View File
@@ -10,71 +10,71 @@ namespace Umbraco.Core.Cache
/// <summary>
/// A cache provider that statically caches everything in an in memory dictionary
/// </summary>
internal class StaticCacheProvider : CacheProviderBase
internal class StaticCacheProvider : ICacheProvider
{
private readonly ConcurrentDictionary<string, object> _staticCache = new ConcurrentDictionary<string, object>();
internal readonly ConcurrentDictionary<string, object> StaticCache = new ConcurrentDictionary<string, object>();
public override void ClearAllCache()
public virtual void ClearAllCache()
{
_staticCache.Clear();
StaticCache.Clear();
}
public override void ClearCacheItem(string key)
public virtual void ClearCacheItem(string key)
{
object val;
_staticCache.TryRemove(key, out val);
StaticCache.TryRemove(key, out val);
}
public override void ClearCacheObjectTypes(string typeName)
public virtual void ClearCacheObjectTypes(string typeName)
{
_staticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType().ToString().InvariantEquals(typeName));
StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType().ToString().InvariantEquals(typeName));
}
public override void ClearCacheObjectTypes<T>()
{
var typeOfT = typeof (T);
_staticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT);
}
public override void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
public virtual void ClearCacheObjectTypes<T>()
{
var typeOfT = typeof(T);
_staticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT && predicate(kvp.Key, (T)kvp.Value));
StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT);
}
public override void ClearCacheByKeySearch(string keyStartsWith)
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
{
_staticCache.RemoveAll(kvp => kvp.Key.InvariantStartsWith(keyStartsWith));
var typeOfT = typeof(T);
StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT && predicate(kvp.Key, (T)kvp.Value));
}
public override void ClearCacheByKeyExpression(string regexString)
public virtual void ClearCacheByKeySearch(string keyStartsWith)
{
_staticCache.RemoveAll(kvp => Regex.IsMatch(kvp.Key, regexString));
StaticCache.RemoveAll(kvp => kvp.Key.InvariantStartsWith(keyStartsWith));
}
public override IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
public virtual void ClearCacheByKeyExpression(string regexString)
{
return (from KeyValuePair<string, object> c in _staticCache
StaticCache.RemoveAll(kvp => Regex.IsMatch(kvp.Key, regexString));
}
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
{
return (from KeyValuePair<string, object> c in StaticCache
where c.Key.InvariantStartsWith(keyStartsWith)
select c.Value.TryConvertTo<T>()
into attempt
where attempt.Success
select attempt.Result).ToList();
select c.Value).ToList();
}
public override T GetCacheItem<T>(string cacheKey)
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
{
var result = _staticCache[cacheKey];
if (result == null)
{
return default(T);
}
return result.TryConvertTo<T>().Result;
return (from KeyValuePair<string, object> c in StaticCache
where Regex.IsMatch(c.Key, regexString)
select c.Value).ToList();
}
public override T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem)
public virtual object GetCacheItem(string cacheKey)
{
return (T)_staticCache.GetOrAdd(cacheKey, key => getCacheItem());
var result = StaticCache[cacheKey];
return result;
}
public virtual object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
return StaticCache.GetOrAdd(cacheKey, key => getCacheItem());
}
}
+165 -201
View File
@@ -12,203 +12,130 @@ using Umbraco.Core.Logging;
namespace Umbraco.Core
{
/// <summary>
/// Class that is exposed by the ApplicationContext for application wide caching purposes
/// </summary>
/// <summary>
/// Class that is exposed by the ApplicationContext for application wide caching purposes
/// </summary>
public class CacheHelper
{
private readonly bool _enableCache;
private readonly CacheProviderBase _staticCache;
private readonly CacheProviderBase _nullStaticCache = new NullCacheProvider();
private readonly RuntimeCacheProviderBase _httpCache;
private readonly RuntimeCacheProviderBase _nullHttpCache = new NullCacheProvider();
{
private readonly bool _enableCache;
private readonly ICacheProvider _requestCache;
private readonly ICacheProvider _nullRequestCache = new NullCacheProvider();
private readonly ICacheProvider _staticCache;
private readonly ICacheProvider _nullStaticCache = new NullCacheProvider();
private readonly IRuntimeCacheProvider _httpCache;
private readonly IRuntimeCacheProvider _nullHttpCache = new NullCacheProvider();
public CacheHelper(System.Web.Caching.Cache cache)
: this(cache, true)
{
}
/// <summary>
/// Creates a cache helper with disabled caches
/// </summary>
/// <returns></returns>
/// <remarks>
/// Good for unit testing
/// </remarks>
public static CacheHelper CreateDisabledCacheHelper()
{
return new CacheHelper(null, null, null, false);
}
internal CacheHelper(System.Web.Caching.Cache cache, bool enableCache)
: this(new HttpRuntimeCacheProvider(cache), enableCache)
{
}
internal CacheHelper(RuntimeCacheProviderBase httpCacheProvider, bool enableCache)
: this(httpCacheProvider, new StaticCacheProvider(), enableCache)
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
public CacheHelper()
: this(
new HttpRuntimeCacheProvider(HttpRuntime.Cache),
new StaticCacheProvider(),
new HttpRequestCacheProvider())
{
}
internal CacheHelper(RuntimeCacheProviderBase httpCacheProvider, CacheProviderBase staticCacheProvider, bool enableCache)
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
/// <param name="cache"></param>
public CacheHelper(System.Web.Caching.Cache cache)
: this(
new HttpRuntimeCacheProvider(cache),
new StaticCacheProvider(),
new HttpRequestCacheProvider())
{
_httpCache = httpCacheProvider;
_staticCache = staticCacheProvider;
}
/// <summary>
/// Initializes a new instance based on the provided providers
/// </summary>
/// <param name="httpCacheProvider"></param>
/// <param name="staticCacheProvider"></param>
/// <param name="requestCacheProvider"></param>
public CacheHelper(
IRuntimeCacheProvider httpCacheProvider,
ICacheProvider staticCacheProvider,
ICacheProvider requestCacheProvider)
: this(httpCacheProvider, staticCacheProvider, requestCacheProvider, true)
{
}
/// <summary>
/// Private ctor used for creating a disabled cache helper
/// </summary>
/// <param name="httpCacheProvider"></param>
/// <param name="staticCacheProvider"></param>
/// <param name="requestCacheProvider"></param>
/// <param name="enableCache"></param>
private CacheHelper(
IRuntimeCacheProvider httpCacheProvider,
ICacheProvider staticCacheProvider,
ICacheProvider requestCacheProvider,
bool enableCache)
{
if (enableCache)
{
_httpCache = httpCacheProvider;
_staticCache = staticCacheProvider;
_requestCache = requestCacheProvider;
}
else
{
_httpCache = null;
_staticCache = null;
_requestCache = null;
}
_enableCache = enableCache;
}
#region Static cache
/// <summary>
/// Clears the item in umbraco's static cache
/// Returns the current Request cache
/// </summary>
internal void ClearAllStaticCache()
public ICacheProvider RequestCache
{
if (!_enableCache)
{
_nullStaticCache.ClearAllCache();
}
else
{
_staticCache.ClearAllCache();
}
get { return _enableCache ? _requestCache : _nullRequestCache; }
}
/// <summary>
/// Clears the item in umbraco's static cache with the given key
/// Returns the current Runtime cache
/// </summary>
/// <param name="key">Key</param>
internal void ClearStaticCacheItem(string key)
public ICacheProvider StaticCache
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheItem(key);
}
else
{
_staticCache.ClearCacheItem(key);
}
get { return _enableCache ? _staticCache : _nullStaticCache; }
}
/// <summary>
/// Clears all objects in the static cache with the System.Type name as the
/// input parameter. (using [object].GetType())
/// Returns the current Runtime cache
/// </summary>
/// <param name="typeName">The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument"</param>
internal void ClearStaticCacheObjectTypes(string typeName)
public IRuntimeCacheProvider RuntimeCache
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheObjectTypes(typeName);
}
else
{
_staticCache.ClearCacheObjectTypes(typeName);
}
get { return _enableCache ? _httpCache : _nullHttpCache; }
}
/// <summary>
/// Clears all objects in the static cache with the System.Type specified
/// </summary>
internal void ClearStaticCacheObjectTypes<T>()
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheObjectTypes<T>();
}
else
{
_staticCache.ClearCacheObjectTypes<T>();
}
}
#region Legacy Runtime/Http Cache accessors
internal void ClearStaticCacheObjectTypes<T>(Func<string, T, bool> predicate)
{
if (_enableCache)
_staticCache.ClearCacheObjectTypes(predicate);
else
_nullStaticCache.ClearCacheObjectTypes(predicate);
}
/// <summary>
/// Clears all static cache items that starts with the key passed.
/// </summary>
/// <param name="keyStartsWith">The start of the key</param>
internal void ClearStaticCacheByKeySearch(string keyStartsWith)
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheByKeySearch(keyStartsWith);
}
else
{
_staticCache.ClearCacheByKeySearch(keyStartsWith);
}
}
/// <summary>
/// Clears all cache items that have a key that matches the regular expression
/// </summary>
/// <param name="regexString"></param>
internal void ClearStaticCacheByKeyExpression(string regexString)
{
if (!_enableCache)
{
_nullStaticCache.ClearCacheByKeyExpression(regexString);
}
else
{
_staticCache.ClearCacheByKeyExpression(regexString);
}
}
internal IEnumerable<T> GetStaticCacheItemsByKeySearch<T>(string keyStartsWith)
{
if (!_enableCache)
{
return _nullStaticCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
else
{
return _staticCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
}
/// <summary>
/// Returns a static cache item by key, does not update the cache if it isn't there.
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <returns></returns>
internal TT GetStaticCacheItem<TT>(string cacheKey)
{
if (!_enableCache)
{
return _nullStaticCache.GetCacheItem<TT>(cacheKey);
}
else
{
return _staticCache.GetCacheItem<TT>(cacheKey);
}
}
/// <summary>
/// Gets (and adds if necessary) an item from the static cache with all of the default parameters
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
internal TT GetStaticCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
{
if (!_enableCache)
{
return _nullStaticCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
else
{
return _staticCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
}
#endregion
#region Runtime/Http Cache
/// <summary>
/// Clears the item in umbraco's runtime cache
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearAllCache()
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.ClearAllCache();
}
@@ -222,9 +149,10 @@ namespace Umbraco.Core
/// Clears the item in umbraco's runtime cache with the given key
/// </summary>
/// <param name="key">Key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheItem(string key)
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.ClearCacheItem(key);
}
@@ -240,9 +168,10 @@ namespace Umbraco.Core
/// input parameter. (using [object].GetType())
/// </summary>
/// <param name="typeName">The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument"</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheObjectTypes(string typeName)
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.ClearCacheObjectTypes(typeName);
}
@@ -255,9 +184,10 @@ namespace Umbraco.Core
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type specified
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheObjectTypes<T>()
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.ClearCacheObjectTypes<T>();
}
@@ -271,9 +201,10 @@ namespace Umbraco.Core
/// Clears all cache items that starts with the key passed.
/// </summary>
/// <param name="keyStartsWith">The start of the key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheByKeySearch(string keyStartsWith)
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.ClearCacheByKeySearch(keyStartsWith);
}
@@ -287,9 +218,10 @@ namespace Umbraco.Core
/// Clears all cache items that have a key that matches the regular expression
/// </summary>
/// <param name="regexString"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheByKeyExpression(string regexString)
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.ClearCacheByKeyExpression(regexString);
}
@@ -299,9 +231,10 @@ namespace Umbraco.Core
}
}
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
{
if (!_enableCache)
if (_enableCache == false)
{
return _nullHttpCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
@@ -317,9 +250,10 @@ namespace Umbraco.Core
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public TT GetCacheItem<TT>(string cacheKey)
{
if (!_enableCache)
if (_enableCache == false)
{
return _nullHttpCache.GetCacheItem<TT>(cacheKey);
}
@@ -336,9 +270,10 @@ namespace Umbraco.Core
/// <param name="cacheKey"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public TT GetCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
{
if (!_enableCache)
if (_enableCache == false)
{
return _nullHttpCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
@@ -356,16 +291,17 @@ namespace Umbraco.Core
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public TT GetCacheItem<TT>(string cacheKey,
TimeSpan timeout, Func<TT> getCacheItem)
{
if (!_enableCache)
if (_enableCache == false)
{
return _nullHttpCache.GetCacheItem<TT>(cacheKey, timeout, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout);
}
else
{
return _httpCache.GetCacheItem<TT>(cacheKey, timeout, getCacheItem);
return _httpCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout);
}
}
@@ -378,17 +314,18 @@ namespace Umbraco.Core
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
if (!_enableCache)
{
return _nullHttpCache.GetCacheItem<TT>(cacheKey, refreshAction, timeout, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, removedCallback: refreshAction);
}
else
{
return _httpCache.GetCacheItem<TT>(cacheKey, refreshAction, timeout, getCacheItem);
return _httpCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, removedCallback: refreshAction);
}
}
@@ -402,17 +339,18 @@ namespace Umbraco.Core
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
if (!_enableCache)
if (_enableCache == false)
{
return _nullHttpCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, timeout, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, false, priority, refreshAction);
}
else
{
return _httpCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, timeout, getCacheItem);
return _httpCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, false, priority, refreshAction);
}
}
@@ -427,6 +365,7 @@ namespace Umbraco.Core
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
@@ -434,13 +373,19 @@ namespace Umbraco.Core
TimeSpan timeout,
Func<TT> getCacheItem)
{
if (!_enableCache)
if (_enableCache == false)
{
return _nullHttpCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, false, priority, refreshAction, null);
}
else
{
return _httpCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
var cache = _httpCache as HttpRuntimeCacheProvider;
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
}
@@ -453,6 +398,7 @@ namespace Umbraco.Core
/// <param name="cacheDependency"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
@@ -460,11 +406,17 @@ namespace Umbraco.Core
{
if (!_enableCache)
{
return _nullHttpCache.GetCacheItem<TT>(cacheKey, priority, null, cacheDependency, null, getCacheItem);
return _nullHttpCache.GetCacheItem<TT>(cacheKey, getCacheItem, null, false, priority, null, null);
}
else
{
return _httpCache.GetCacheItem<TT>(cacheKey, priority, null, cacheDependency, null, getCacheItem);
var cache = _httpCache as HttpRuntimeCacheProvider;
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), null, false, priority, null, cacheDependency);
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
}
@@ -479,13 +431,13 @@ namespace Umbraco.Core
CacheItemPriority priority,
Func<T> getCacheItem)
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, getCacheItem);
_nullHttpCache.InsertCacheItem<T>(cacheKey, getCacheItem, priority: priority);
}
else
{
_httpCache.InsertCacheItem<T>(cacheKey, priority, getCacheItem);
_httpCache.InsertCacheItem<T>(cacheKey, getCacheItem, priority: priority);
}
}
@@ -502,13 +454,13 @@ namespace Umbraco.Core
TimeSpan timeout,
Func<T> getCacheItem)
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, timeout, getCacheItem);
_nullHttpCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, priority: priority);
}
else
{
_httpCache.InsertCacheItem<T>(cacheKey, priority, timeout, getCacheItem);
_httpCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, priority: priority);
}
}
@@ -521,19 +473,25 @@ namespace Umbraco.Core
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<T> getCacheItem)
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, cacheDependency, timeout, getCacheItem);
_nullHttpCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, priority: priority, dependentFiles: null);
}
else
{
_httpCache.InsertCacheItem<T>(cacheKey, priority, cacheDependency, timeout, getCacheItem);
var cache = _httpCache as HttpRuntimeCacheProvider;
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, null, cacheDependency);
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
}
@@ -547,6 +505,7 @@ namespace Umbraco.Core
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
@@ -554,17 +513,22 @@ namespace Umbraco.Core
TimeSpan? timeout,
Func<T> getCacheItem)
{
if (!_enableCache)
if (_enableCache == false)
{
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
_nullHttpCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, false, priority, refreshAction, null);
}
else
{
_httpCache.InsertCacheItem<T>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
var cache = _httpCache as HttpRuntimeCacheProvider;
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
}
}
#endregion
}
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ namespace Umbraco.Core
/// <summary>
/// Gets the <see cref="ICacheRefresher"/> implementations.
/// </summary>
public IEnumerable<ICacheRefresher> CacheResolvers
public IEnumerable<ICacheRefresher> CacheRefreshers
{
get
{
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Configuration
}
/// <summary>
/// Increases the version number in ClientDependency.config by 1
/// Changes the version number in ClientDependency.config to a random value to avoid stale caches
/// </summary>
internal bool IncreaseVersionNumber()
{
@@ -28,9 +28,9 @@ namespace Umbraco.Core.Configuration
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
int oldVersion;
int.TryParse(versionAttribute.Value, out oldVersion);
var newVersion = oldVersion + 1;
//Set the new version to the hashcode of now
var oldVersion = versionAttribute.Value;
var newVersion = Math.Abs(DateTime.UtcNow.GetHashCode());
versionAttribute.SetValue(newVersion);
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
@@ -5,10 +5,13 @@ using System.Linq;
using System.Web;
using System.Web.Configuration;
using System.Web.Routing;
using System.Web.Security;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Security;
namespace Umbraco.Core.Configuration
{
@@ -175,7 +178,10 @@ namespace Umbraco.Core.Configuration
{
throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified");
}
return Path.TrimStart(SystemDirectories.Root).TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
var path = Path;
if (path.StartsWith(SystemDirectories.Root)) // beware of TrimStart, see U4-2518
path = path.Substring(SystemDirectories.Root.Length);
return path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
}
}
@@ -252,7 +258,38 @@ namespace Umbraco.Core.Configuration
SaveSetting("umbracoConfigurationStatus", value);
}
}
/// <summary>
/// Gets or sets the Umbraco members membership providers' useLegacyEncoding state. This will return a boolean
/// </summary>
/// <value>The useLegacyEncoding status.</value>
public static bool UmbracoMembershipProviderLegacyEncoding
{
get
{
return IsConfiguredMembershipProviderUsingLegacyEncoding(Constants.Conventions.Member.UmbracoMemberProviderName);
}
set
{
SetMembershipProvidersLegacyEncoding(Constants.Conventions.Member.UmbracoMemberProviderName, value);
}
}
/// <summary>
/// Gets or sets the Umbraco users membership providers' useLegacyEncoding state. This will return a boolean
/// </summary>
/// <value>The useLegacyEncoding status.</value>
public static bool UmbracoUsersMembershipProviderLegacyEncoding
{
get
{
return IsConfiguredMembershipProviderUsingLegacyEncoding(UmbracoSettings.DefaultBackofficeProvider);
}
set
{
SetMembershipProvidersLegacyEncoding(UmbracoSettings.DefaultBackofficeProvider, value);
}
}
/// <summary>
/// Saves a setting into the configuration file.
@@ -312,6 +349,38 @@ namespace Umbraco.Core.Configuration
return fileName;
}
private static void SetMembershipProvidersLegacyEncoding(string providerName, bool useLegacyEncoding)
{
var webConfigFilename = GetFullWebConfigFileName();
var webConfigXml = XDocument.Load(webConfigFilename, LoadOptions.PreserveWhitespace);
var membershipConfigs = webConfigXml.XPathSelectElements("configuration/system.web/membership/providers/add").ToList();
if (membershipConfigs.Any() == false)
return;
var provider = membershipConfigs.SingleOrDefault(c => c.Attribute("name") != null && c.Attribute("name").Value == providerName);
if (provider == null)
return;
provider.SetAttributeValue("useLegacyEncoding", useLegacyEncoding);
webConfigXml.Save(webConfigFilename, SaveOptions.DisableFormatting);
}
private static bool IsConfiguredMembershipProviderUsingLegacyEncoding(string providerName)
{
//check if this can even be configured.
var membershipProvider = Membership.Providers[providerName] as MembershipProviderBase;
if (membershipProvider == null)
{
return false;
}
return membershipProvider.UseLegacyEncoding;
}
/// <summary>
/// Gets the full path to root.
/// </summary>
@@ -701,8 +770,12 @@ namespace Umbraco.Core.Configuration
StartsWithContainer _newReservedList = new StartsWithContainer();
foreach (string reservedUrl in _reservedUrlsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
if (string.IsNullOrWhiteSpace(reservedUrl))
continue;
//resolves the url to support tilde chars
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl).Trim().ToLower();
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl.Trim()).Trim().ToLower();
if (reservedUrlTrimmed.Length > 0)
_newReservedList.Add(reservedUrlTrimmed);
}
@@ -710,8 +783,11 @@ namespace Umbraco.Core.Configuration
foreach (string reservedPath in _reservedPathsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
bool trimEnd = !reservedPath.EndsWith("/");
if (string.IsNullOrWhiteSpace(reservedPath))
continue;
//resolves the url to support tilde chars
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath).Trim().ToLower();
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath.Trim()).Trim().ToLower();
if (reservedPathTrimmed.Length > 0)
_newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/"));
@@ -309,7 +309,7 @@ namespace Umbraco.Core.Configuration
{
return value;
}
return "UMB_UCONTEXT";
return Constants.Web.AuthCookieName;
}
}
@@ -658,7 +658,7 @@ namespace Umbraco.Core.Configuration
{
string defaultProvider = GetKey("/settings/providers/users/DefaultBackofficeProvider");
if (String.IsNullOrEmpty(defaultProvider))
defaultProvider = "UsersMembershipProvider";
defaultProvider = "UsersMembershipProvider";
return defaultProvider;
}
@@ -855,6 +855,8 @@ namespace Umbraco.Core.Configuration
/// <summary>
/// Whether to replace double dashes from url (ie my--story----from--dash.aspx caused by multiple url replacement chars
/// </summary>
// was used by the legacy short string helper, is not used anymore by the new default short string helper
// should update documentation
internal static bool RemoveDoubleDashesFromUrlReplacing
{
get
@@ -1081,7 +1083,7 @@ namespace Umbraco.Core.Configuration
bool globalPreviewEnabled = false;
string value = GetKey("/settings/content/GlobalPreviewStorageEnabled");
if (bool.TryParse(value, out globalPreviewEnabled))
return !globalPreviewEnabled;
return globalPreviewEnabled;
// Return default
return false;
}
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("6.2.0");
private static readonly Version Version = new Version("6.2.4");
/// <summary>
/// Gets the current version of Umbraco.
+101 -150
View File
@@ -85,7 +85,7 @@ namespace Umbraco.Core
/// <summary>
/// MediaType alias for a folder.
/// </summary>
/// </summary>
public const string Folder = "Folder";
/// <summary>
@@ -93,10 +93,10 @@ namespace Umbraco.Core
/// </summary>
public const string Image = "Image";
}
/// <summary>
/// Constants for Umbraco Member property aliases.
/// </summary>
/// </summary>
public static class Member
{
public static readonly string UmbracoMemberProviderName = "UmbracoMembershipProvider";
@@ -106,200 +106,149 @@ namespace Umbraco.Core
/// <summary>
/// Property alias for a Members Password Question
/// </summary>
public const string PasswordQuestion = "umbracoPasswordRetrievalQuestionPropertyTypeAlias";
public const string PasswordQuestion = "umbracoMemberPasswordRetrievalQuestion";
public const string PasswordQuestionLabel = "Password Question";
/// <summary>
/// Property alias for Members Password Answer
/// </summary>
public const string PasswordAnswer = "umbracoPasswordRetrievalAnswerPropertyTypeAlias";
public const string PasswordAnswer = "umbracoMemberPasswordRetrievalAnswer";
public const string PasswordAnswerLabel = "Password Answer";
/// <summary>
/// Property alias for the Comments on a Member
/// </summary>
public const string Comments = "umbracoCommentPropertyTypeAlias";
public const string Comments = "umbracoMemberComments";
public const string CommentsLabel = "Comments";
public const string CommentsLabel = "Comments";
/// <summary>
/// Property alias for the Approved boolean of a Member
/// </summary>
public const string IsApproved = "umbracoApprovePropertyTypeAlias";
public const string IsApproved = "umbracoMemberApproved";
public const string IsApprovedLabel = "Is Approved";
public const string IsApprovedLabel = "Is Approved";
/// <summary>
/// Property alias for the Locked out boolean of a Member
/// </summary>
public const string IsLockedOut = "umbracoLockPropertyTypeAlias";
public const string IsLockedOut = "umbracoMemberLockedOut";
public const string IsLockedOutLabel = "Is Locked Out";
public const string IsLockedOutLabel = "Is Locked Out";
/// <summary>
/// Property alias for the last date the Member logged in
/// </summary>
public const string LastLoginDate = "umbracoLastLoginPropertyTypeAlias";
public const string LastLoginDate = "umbracoMemberLastLogin";
public const string LastLoginDateLabel = "Last Login Date";
public const string LastLoginDateLabel = "Last Login Date";
/// <summary>
/// Property alias for the last date a Member changed its password
/// </summary>
public const string LastPasswordChangeDate = "umbracoMemberLastPasswordChange";
public const string LastPasswordChangeDate = "umbracoMemberLastPasswordChangeDate";
public const string LastPasswordChangeDateLabel = "Last Password Change Date";
/// <summary>
/// Property alias for the last date a Member was locked out
/// </summary>
public const string LastLockoutDate = "umbracoMemberLastLockout";
public const string LastLockoutDate = "umbracoMemberLastLockoutDate";
public const string LastLockoutDateLabel = "Last Lockout Date";
/// <summary>
/// Property alias for the number of failed login attemps
/// </summary>
public const string FailedPasswordAttempts = "umbracoFailedPasswordAttemptsPropertyTypeAlias";
public const string FailedPasswordAttempts = "umbracoMemberFailedPasswordAttempts";
public const string FailedPasswordAttemptsLabel = "Failed Password Attempts";
internal static Dictionary<string, PropertyType>
StandardPropertyTypeStubs = new Dictionary<string, PropertyType>
{
{
Comments,
new PropertyType(
new Guid(
PropertyEditors
.TextboxMultiple),
DataTypeDatabaseType
.Ntext)
{
Alias = Comments,
Name =
CommentsLabel
}
},
{
FailedPasswordAttempts,
new PropertyType(
new Guid(
PropertyEditors
.Integer),
DataTypeDatabaseType
.Integer)
{
Alias =
FailedPasswordAttempts,
Name =
FailedPasswordAttemptsLabel
}
},
{
IsApproved,
new PropertyType(
new Guid(
PropertyEditors
.TrueFalse),
DataTypeDatabaseType
.Integer)
{
Alias = IsApproved,
Name =
IsApprovedLabel
}
},
{
IsLockedOut,
new PropertyType(
new Guid(
PropertyEditors
.TrueFalse),
DataTypeDatabaseType
.Integer)
{
Alias =
IsLockedOut,
Name =
IsLockedOutLabel
}
},
{
LastLockoutDate,
new PropertyType(
new Guid(
PropertyEditors.Date),
DataTypeDatabaseType
.Date)
{
Alias =
LastLockoutDate,
Name =
LastLockoutDateLabel
}
},
{
LastLoginDate,
new PropertyType(
new Guid(
PropertyEditors.Date),
DataTypeDatabaseType
.Date)
{
Alias =
LastLoginDate,
Name =
LastLoginDateLabel
}
},
{
LastPasswordChangeDate,
new PropertyType(
new Guid(
PropertyEditors.Date),
DataTypeDatabaseType
.Date)
{
Alias =
LastPasswordChangeDate,
Name =
LastPasswordChangeDateLabel
}
},
{
PasswordAnswer,
new PropertyType(
new Guid(
PropertyEditors
.Textbox),
DataTypeDatabaseType
.Nvarchar)
{
Alias =
PasswordAnswer,
Name =
PasswordAnswerLabel
}
},
{
PasswordQuestion,
new PropertyType(
new Guid(
PropertyEditors
.Textbox),
DataTypeDatabaseType
.Nvarchar)
{
Alias =
PasswordQuestion,
Name =
PasswordQuestionLabel
}
}
};
/// <summary>
/// Group name to put the membership properties on
/// </summary>
internal const string StandardPropertiesGroupName = "Membership";
internal static Dictionary<string, PropertyType> GetStandardPropertyTypeStubs()
{
return new Dictionary<string, PropertyType>
{
{
Comments,
new PropertyType(new Guid(PropertyEditors.TextboxMultiple), DataTypeDatabaseType.Ntext, true)
{
Alias = Comments,
Name = CommentsLabel
}
},
{
FailedPasswordAttempts,
new PropertyType(new Guid(PropertyEditors.NoEdit), DataTypeDatabaseType.Integer, true)
{
Alias = FailedPasswordAttempts,
Name = FailedPasswordAttemptsLabel
}
},
{
IsApproved,
new PropertyType(new Guid(PropertyEditors.TrueFalse), DataTypeDatabaseType.Integer, true)
{
Alias = IsApproved,
Name = IsApprovedLabel
}
},
{
IsLockedOut,
new PropertyType(new Guid(PropertyEditors.TrueFalse), DataTypeDatabaseType.Integer, true)
{
Alias = IsLockedOut,
Name = IsLockedOutLabel
}
},
{
LastLockoutDate,
new PropertyType(new Guid(PropertyEditors.NoEdit), DataTypeDatabaseType.Date, true)
{
Alias = LastLockoutDate,
Name = LastLockoutDateLabel
}
},
{
LastLoginDate,
new PropertyType(new Guid(PropertyEditors.NoEdit), DataTypeDatabaseType.Date, true)
{
Alias = LastLoginDate,
Name = LastLoginDateLabel
}
},
{
LastPasswordChangeDate,
new PropertyType(new Guid(PropertyEditors.NoEdit), DataTypeDatabaseType.Date, true)
{
Alias = LastPasswordChangeDate,
Name = LastPasswordChangeDateLabel
}
},
{
PasswordAnswer,
new PropertyType(new Guid(PropertyEditors.NoEdit), DataTypeDatabaseType.Nvarchar, true)
{
Alias = PasswordAnswer,
Name = PasswordAnswerLabel
}
},
{
PasswordQuestion,
new PropertyType(new Guid(PropertyEditors.NoEdit), DataTypeDatabaseType.Nvarchar, true)
{
Alias = PasswordQuestion,
Name = PasswordQuestionLabel
}
}
};
}
}
/// <summary>
@@ -311,6 +260,8 @@ namespace Umbraco.Core
/// MemberType alias for default member type.
/// </summary>
public const string Member = "Member";
public const string SystemDefaultProtectType = "_umbracoSystemDefaultProtectType";
}
/// <summary>
+51
View File
@@ -0,0 +1,51 @@
namespace Umbraco.Core
{
public static partial class Constants
{
/// <summary>
/// Defines the constants used for Umbraco packages in the package.config xml
/// </summary>
public static class Packaging
{
public const string UmbPackageNodeName = "umbPackage";
public const string DataTypesNodeName = "DataTypes";
public const string PackageXmlFileName = "package.xml";
public const string UmbracoPackageExtention = ".umb";
public const string DataTypeNodeName = "DataType";
public const string LanguagesNodeName = "Languages";
public const string FilesNodeName = "Files";
public const string StylesheetsNodeName = "Stylesheets";
public const string TemplatesNodeName = "Templates";
public const string OrgnameNodeName = "orgName";
public const string NameNodeName = "Name";
public const string TemplateNodeName = "Template";
public const string AliasNodeName = "Alias";
public const string DictionaryitemsNodeName = "DictionaryItems";
public const string MacrosNodeName = "macros";
public const string DocumentSetNodeName = "DocumentSet";
public const string DocumentTypesNodeName = "DocumentTypes";
public const string DocumentTypeNodeName = "DocumentType";
public const string FileNodeName = "file";
public const string OrgPathNodeName = "orgPath";
public const string GuidNodeName = "guid";
public const string StylesheetNodeName = "styleSheet";
public const string MacroNodeName = "macro";
public const string InfoNodeName = "info";
public const string PackageRequirementsMajorXpath = "/package/requirements/major";
public const string PackageRequirementsMinorXpath = "/package/requirements/minor";
public const string PackageRequirementsPatchXpath = "/package/requirements/patch";
public const string PackageNameXpath = "/package/name";
public const string PackageVersionXpath = "/package/version";
public const string PackageUrlXpath = "/package/url";
public const string PackageLicenseXpath = "/package/license";
public const string AuthorNameXpath = "/author/name";
public const string AuthorWebsiteXpath = "/author/website";
public const string ReadmeXpath = "/readme";
public const string ControlNodeName = "control";
public const string ActionNodeName = "Action";
public const string ActionsNodeName = "Actions";
public const string UndoNodeAttribute = "undo";
public const string RunatNodeAttribute = "runat";
}
}
}
+22
View File
@@ -0,0 +1,22 @@
namespace Umbraco.Core
{
public static partial class Constants
{
/// <summary>
/// Defines the identifiers for Umbraco system nodes.
/// </summary>
public static class Web
{
/// <summary>
/// The preview cookie name
/// </summary>
public const string PreviewCookieName = "UMB_PREVIEW";
/// <summary>
/// The auth cookie name
/// </summary>
public const string AuthCookieName = "UMB_UCONTEXT";
}
}
}
+46
View File
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
namespace Umbraco.Core
{
internal static class ControlExtensions
{
/// <summary>
/// Recursively finds a control with the specified identifier.
/// </summary>
/// <typeparam name="T">
/// The type of control to be found.
/// </typeparam>
/// <param name="parent">
/// The parent control from which the search will start.
/// </param>
/// <param name="id">
/// The identifier of the control to be found.
/// </param>
/// <returns>
/// The control with the specified identifier, otherwise <see langword="null"/> if the control
/// is not found.
/// </returns>
public static T FindControlRecursive<T>(this Control parent, string id) where T : Control
{
if ((parent is T) && (parent.ID == id))
{
return (T)parent;
}
foreach (Control control in parent.Controls)
{
var foundControl = FindControlRecursive<T>(control, id);
if (foundControl != null)
{
return foundControl;
}
}
return default(T);
}
}
}
+31 -19
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
@@ -38,6 +39,7 @@ namespace Umbraco.Core
private bool _isComplete = false;
private readonly UmbracoApplicationBase _umbracoApplication;
protected ApplicationContext ApplicationContext { get; private set; }
protected CacheHelper ApplicationCache { get; set; }
protected UmbracoApplicationBase UmbracoApplication
{
@@ -57,16 +59,19 @@ namespace Umbraco.Core
InitializeProfilerResolver();
CreateApplicationCache();
_timer = DisposableTimer.DebugDuration<CoreBootManager>("Umbraco application starting", "Umbraco application startup complete");
//create database and service contexts for the app context
var dbFactory = new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName);
Database.Mapper = new PetaPocoMapper();
var dbContext = new DatabaseContext(dbFactory);
var serviceContext = new ServiceContext(
new PetaPocoUnitOfWorkProvider(dbFactory),
new FileUnitOfWorkProvider(),
new PublishingStrategy());
var serviceContext = new ServiceContext(
new PetaPocoUnitOfWorkProvider(dbFactory),
new FileUnitOfWorkProvider(),
new PublishingStrategy(),
ApplicationCache);
CreateApplicationContext(dbContext, serviceContext);
@@ -94,7 +99,21 @@ namespace Umbraco.Core
protected virtual void CreateApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext)
{
//create the ApplicationContext
ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext);
ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext, ApplicationCache);
}
/// <summary>
/// Creates and assigns the ApplicationCache based on a new instance of System.Web.Caching.Cache
/// </summary>
protected virtual void CreateApplicationCache()
{
var cacheHelper = new CacheHelper(
new ObjectCacheRuntimeCacheProvider(),
new StaticCacheProvider(),
//we have no request based cache when not running in web-based context
new NullCacheProvider());
ApplicationCache = cacheHelper;
}
/// <summary>
@@ -231,7 +250,7 @@ namespace Umbraco.Core
() => PluginManager.Current.ResolveAssignedMapperTypes());
RepositoryResolver.Current = new RepositoryResolver(
new RepositoryFactory());
new RepositoryFactory(ApplicationCache));
SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver(
new[] { typeof(MySqlSyntaxProvider), typeof(SqlCeSyntaxProvider), typeof(SqlServerSyntaxProvider) })
@@ -256,7 +275,7 @@ namespace Umbraco.Core
//the database migration objects
MigrationResolver.Current = new MigrationResolver(
() => PluginManager.Current.ResolveMigrationTypes());
() => PluginManager.Current.ResolveTypes<IMigration>());
// todo: remove once we drop IPropertyEditorValueConverter support.
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
@@ -266,24 +285,17 @@ namespace Umbraco.Core
PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver(
PluginManager.Current.ResolveTypes<IPropertyValueConverter>());
// use the new DefaultShortStringHelper but sort-of remain compatible
// - use UmbracoSettings UrlReplaceCharacters
// - allow underscores in terms, allow leading digits
// use the new DefaultShortStringHelper
ShortStringHelperResolver.Current = new ShortStringHelperResolver(
new DefaultShortStringHelper()
.WithConfig(CleanStringType.Url, DefaultShortStringHelper.ApplyUrlReplaceCharacters,
allowUnderscoreInTerm: true, allowLeadingDigits: true));
// that was the old one
//ShortStringHelperResolver.Current = new ShortStringHelperResolver(
// new LegacyShortStringHelper());
//new LegacyShortStringHelper());
new DefaultShortStringHelper().WithDefaultConfig());
UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver(
typeof (DefaultUrlSegmentProvider));
// keep it internal for now
//PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver(
// new PublishedContentModelFactoryImpl());
PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver();
// new PublishedContentModelFactoryImpl());
}
}
}
@@ -22,8 +22,8 @@ namespace Umbraco.Core
if (value is string)
{
var str = (string)value;
if (str == null || str.Length == 0 || str == "0") return false;
if (str == "1") return true;
if (str == "0" || str == "") return false;
}
return base.ConvertFrom(context, culture, value);
+162 -60
View File
@@ -3,6 +3,7 @@ using System.Configuration;
using System.Data.SqlServerCe;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Configuration;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
@@ -426,6 +427,13 @@ namespace Umbraco.Core
if (_result == null)
{
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted
&& ProviderName == "MySql.Data.MySqlClient")
{
throw new InvalidOperationException("Cannot use MySql in Medium Trust configuration");
}
var database = new UmbracoDatabase(_connectionString, ProviderName);
var dbSchema = new DatabaseSchemaCreation(database);
_result = dbSchema.ValidateSchema();
@@ -433,26 +441,26 @@ namespace Umbraco.Core
return _result;
}
internal Result CreateDatabaseSchemaAndDataOrUpgrade()
{
if (_configured == false || (string.IsNullOrEmpty(_connectionString) || string.IsNullOrEmpty(ProviderName)))
{
return new Result
{
Message =
"Database configuration is invalid. Please check that the entered database exists and that the provided username and password has write access to the database.",
Success = false,
Percentage = "10"
};
}
internal Result CreateDatabaseSchemaAndData()
{
try
{
var readyForInstall = CheckReadyForInstall();
if (readyForInstall.Success == false)
{
return readyForInstall.Result;
}
LogHelper.Info<DatabaseContext>("Database configuration status: Started");
var message = string.Empty;
string message;
var database = new UmbracoDatabase(_connectionString, ProviderName);
// If MySQL, we're going to ensure that database calls are maintaining proper casing as to remove the necessity for checks
// for case insensitive queries. In an ideal situation (which is what we're striving for), all calls would be case sensitive.
/*
var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
if (supportsCaseInsensitiveQueries == false)
{
@@ -465,50 +473,75 @@ namespace Umbraco.Core
return new Result { Message = message, Success = false, Percentage = "15" };
}
else if (supportsCaseInsensitiveQueries == null)
{
message = "<p>&nbsp;</p><p>Warning! Could not check if your database type supports case insensitive queries. <br />We currently do not support these databases that do not support case insensitive queries.</p>" +
"<p>You can check this by looking for the following setting in your my.ini file in your MySQL installation directory:</p>" +
"<pre>lower_case_table_names=1</pre><br />" +
"<p>Note: Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
}
else
{
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>" +
"<p>However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries</p>" +
"<p>Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
"<p>They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:</p>" +
"<pre>lower_case_table_names=1</pre><br />" +
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
}
}
*/
message = GetResultMessageForMySql();
var schemaResult = ValidateDatabaseSchema();
var installedVersion = schemaResult.DetermineInstalledVersion();
//If Configuration Status is empty and the determined version is "empty" its a new install - otherwise upgrade the existing
if (string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) && installedVersion.Equals(new Version(0, 0, 0)))
{
database.CreateDatabaseSchema();
message = message + "<p>Installation completed!</p>";
//now that everything is done, we need to determine the version of SQL server that is executing
LogHelper.Info<DatabaseContext>("Database configuration status: " + message);
return new Result { Message = message, Success = true, Percentage = "100" };
}
else
//we need to do an upgrade so return a new status message and it will need to be done during the next step
LogHelper.Info<DatabaseContext>("Database requires upgrade");
message = "<p>Upgrading database, this may take some time...</p>";
return new Result
{
RequiresUpgrade = true,
Message = message,
Success = true,
Percentage = "30"
};
}
catch (Exception ex)
{
return HandleInstallException(ex);
}
}
/// <summary>
/// This assumes all of the previous checks are done!
/// </summary>
/// <returns></returns>
internal Result UpgradeSchemaAndData()
{
try
{
var readyForInstall = CheckReadyForInstall();
if (readyForInstall.Success == false)
{
var configuredVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus)
return readyForInstall.Result;
}
LogHelper.Info<DatabaseContext>("Database upgrade started");
var database = new UmbracoDatabase(_connectionString, ProviderName);
//var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
var message = GetResultMessageForMySql();
var schemaResult = ValidateDatabaseSchema();
var installedVersion = schemaResult.DetermineInstalledVersion();
//DO the upgrade!
var configuredVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus)
? installedVersion
: new Version(GlobalSettings.ConfigurationStatus);
var targetVersion = UmbracoVersion.Current;
var runner = new MigrationRunner(configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName);
var upgraded = runner.Execute(database, true);
message = message + "<p>Upgrade completed!</p>";
}
var targetVersion = UmbracoVersion.Current;
var runner = new MigrationRunner(configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName);
var upgraded = runner.Execute(database, true);
message = message + "<p>Upgrade completed!</p>";
//now that everything is done, we need to determine the version of SQL server that is executing
@@ -518,26 +551,95 @@ namespace Umbraco.Core
}
catch (Exception ex)
{
LogHelper.Info<DatabaseContext>("Database configuration failed with the following error and stack trace: " + ex.Message + "\n" + ex.StackTrace);
if (_result != null)
{
LogHelper.Info<DatabaseContext>("The database schema validation produced the following summary: \n" + _result.GetSummary());
}
return new Result
{
Message =
"The database configuration failed with the following message: " + ex.Message +
"\n Please check log file for additional information (can be found in '/App_Data/Logs/UmbracoTraceLog.txt')",
Success = false,
Percentage = "90"
};
return HandleInstallException(ex);
}
}
private string GetResultMessageForMySql()
{
if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider))
{
return "<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>" +
"<p>However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries</p>" +
"<p>Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
"<p>They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:</p>" +
"<pre>lower_case_table_names=1</pre><br />" +
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
}
return string.Empty;
}
/*
private string GetResultMessageForMySql(bool? supportsCaseInsensitiveQueries)
{
if (supportsCaseInsensitiveQueries == null)
{
return "<p>&nbsp;</p><p>Warning! Could not check if your database type supports case insensitive queries. <br />We currently do not support these databases that do not support case insensitive queries.</p>" +
"<p>You can check this by looking for the following setting in your my.ini file in your MySQL installation directory:</p>" +
"<pre>lower_case_table_names=1</pre><br />" +
"<p>Note: Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
}
if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider))
{
return "<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>" +
"<p>However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries</p>" +
"<p>Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
"<p>They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:</p>" +
"<pre>lower_case_table_names=1</pre><br />" +
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
}
return string.Empty;
}*/
private Attempt<Result> CheckReadyForInstall()
{
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted
&& ProviderName == "MySql.Data.MySqlClient")
{
throw new InvalidOperationException("Cannot use MySql in Medium Trust configuration");
}
if (_configured == false || (string.IsNullOrEmpty(_connectionString) || string.IsNullOrEmpty(ProviderName)))
{
return Attempt.Fail(new Result
{
Message =
"Database configuration is invalid. Please check that the entered database exists and that the provided username and password has write access to the database.",
Success = false,
Percentage = "10"
});
}
return Attempt<Result>.Succeed();
}
private Result HandleInstallException(Exception ex)
{
LogHelper.Info<DatabaseContext>("Database configuration failed with the following error and stack trace: " + ex.Message + "\n" + ex.StackTrace);
if (_result != null)
{
LogHelper.Info<DatabaseContext>("The database schema validation produced the following summary: \n" + _result.GetSummary());
}
return new Result
{
Message =
"The database configuration failed with the following message: " + ex.Message +
"\n Please check log file for additional information (can be found in '/App_Data/Logs/UmbracoTraceLog.txt')",
Success = false,
Percentage = "90"
};
}
internal class Result
{
public bool RequiresUpgrade { get; set; }
public string Message { get; set; }
public bool Success { get; set; }
public string Percentage { get; set; }
+25
View File
@@ -18,5 +18,30 @@ namespace Umbraco.Core
return dt.ToString("yyyy-MM-dd HH:mm:ss");
}
public static DateTime TruncateTo(this DateTime dt, DateTruncate truncateTo)
{
if (truncateTo == DateTruncate.Year)
return new DateTime(dt.Year, 0, 0);
if (truncateTo == DateTruncate.Month)
return new DateTime(dt.Year, dt.Month, 0);
if (truncateTo == DateTruncate.Day)
return new DateTime(dt.Year, dt.Month, dt.Day);
if (truncateTo == DateTruncate.Hour)
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0);
if (truncateTo == DateTruncate.Minute)
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0);
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
}
public enum DateTruncate
{
Year,
Month,
Day,
Hour,
Minute,
Second
}
}
}
+4 -24
View File
@@ -36,42 +36,22 @@ namespace Umbraco.Core.Dynamics
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsAny(this string haystack, IEnumerable<string> needles)
{
if (haystack == null) throw new ArgumentNullException("haystack");
if (!string.IsNullOrEmpty(haystack) || needles.Any())
{
return needles.Any(haystack.Contains);
}
return false;
return StringExtensions.ContainsAny(haystack, needles);
}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsAny(this string haystack, params string[] needles)
{
if (haystack == null) throw new ArgumentNullException("haystack");
if (!string.IsNullOrEmpty(haystack) || needles.Length > 0)
{
return needles.Any(haystack.Contains);
}
return false;
return StringExtensions.ContainsAny(haystack, needles);
}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsAny(this string haystack, StringComparison comparison, IEnumerable<string> needles)
{
if (haystack == null) throw new ArgumentNullException("haystack");
if (!string.IsNullOrEmpty(haystack) || needles.Any())
{
return needles.Any(value => haystack.IndexOf(value, comparison) >= 0);
}
return false;
return StringExtensions.ContainsAny(haystack, needles, comparison);
}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsAny(this string haystack, StringComparison comparison, params string[] needles)
{
if (haystack == null) throw new ArgumentNullException("haystack");
if (!string.IsNullOrEmpty(haystack) || needles.Length > 0)
{
return needles.Any(value => haystack.IndexOf(value, comparison) >= 0);
}
return false;
return StringExtensions.ContainsAny(haystack, needles, comparison);
}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsInsensitive(this string haystack, string needle)
+6 -3
View File
@@ -4,14 +4,14 @@ using System.Web;
namespace Umbraco.Core.Dynamics
{
internal class PropertyResult : IPublishedProperty, IHtmlString
internal class PropertyResult : IPublishedContentProperty, IHtmlString
{
private readonly IPublishedProperty _source;
private readonly IPublishedContentProperty _source;
private readonly string _alias;
private readonly object _value;
private readonly PropertyResultType _type;
internal PropertyResult(IPublishedProperty source, PropertyResultType type)
internal PropertyResult(IPublishedContentProperty source, PropertyResultType type)
{
if (source == null) throw new ArgumentNullException("source");
@@ -37,6 +37,9 @@ namespace Umbraco.Core.Dynamics
public object Value { get { return _source == null ? _value : _source.Value; } }
public object XPathValue { get { return Value == null ? null : Value.ToString(); } }
public string Alias { get { return PropertyTypeAlias; }}
public Guid Version { get { return Guid.Empty; }}
// implements IHtmlString.ToHtmlString
public string ToHtmlString()
{
+12 -51
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Umbraco.Core.Logging;
namespace Umbraco.Core
{
@@ -14,43 +15,13 @@ namespace Umbraco.Core
public static IEnumerable<IEnumerable<T>> InGroupsOf<T>(this IEnumerable<T> source, int groupSize)
{
if (source == null)
throw new NullReferenceException("source");
throw new ArgumentNullException("source");
if (groupSize <= 0)
throw new ArgumentException("Must be greater than zero.", "groupSize");
// enumerate the source only once!
return new InGroupsEnumerator<T>(source, groupSize).Groups();
}
// this class makes sure that the source is enumerated only ONCE
// which means that when it is enumerated, the actual groups content
// has to be evaluated at the same time, and stored in an array.
private class InGroupsEnumerator<T>
{
private readonly IEnumerator<T> _source;
private readonly int _count;
private bool _mightHaveNext;
public InGroupsEnumerator(IEnumerable<T> source, int count)
{
_source = source.GetEnumerator();
_count = count;
_mightHaveNext = true;
}
public IEnumerable<IEnumerable<T>> Groups()
{
while (_mightHaveNext && _source.MoveNext())
yield return Group().ToArray(); // see note above
}
private IEnumerable<T> Group()
{
var c = 0;
do
{
yield return _source.Current;
} while (++c < _count && _source.MoveNext());
_mightHaveNext = c == _count;
}
return source
.Select((x, i) => Tuple.Create(i / groupSize, x))
.GroupBy(t => t.Item1, t => t.Item2);
}
/// <summary>The distinct by.</summary>
@@ -125,23 +96,13 @@ namespace Umbraco.Core
}
/// <summary>The flatten list.</summary>
/// <param name="items">The items.</param>
/// <param name="selectChild">The select child.</param>
/// <typeparam name="TItem">Item type</typeparam>
/// <param name="e">The items.</param>
/// <param name="f">The select child.</param>
/// <typeparam name="T">Item type</typeparam>
/// <returns>list of TItem</returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "By design")]
public static IEnumerable<TItem> FlattenList<TItem>(this IEnumerable<TItem> items, Func<TItem, IEnumerable<TItem>> selectChild)
public static IEnumerable<T> FlattenList<T>(this IEnumerable<T> e, Func<T, IEnumerable<T>> f)
{
IEnumerable<TItem> children = items != null && items.Any()
? items.SelectMany(selectChild).FlattenList(selectChild)
: Enumerable.Empty<TItem>();
if (items != null)
{
return items.Concat(children);
}
return null;
return e.SelectMany(c => f(c).FlattenList(f)).Concat(e);
}
/// <summary>
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Events
/// <remarks>
/// This is protected so that inheritors can expose it with their own name
/// </remarks>
protected T EventObject { get; private set; }
protected T EventObject { get; set; }
}
}
+92 -22
View File
@@ -1,28 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Events
{
public class MoveEventArgs<TEntity> : CancellableObjectEventArgs<TEntity>
{
public MoveEventArgs(TEntity eventObject, bool canCancel, int parentId) : base(eventObject, canCancel)
{
ParentId = parentId;
}
public class MoveEventInfo<TEntity>
{
public MoveEventInfo(TEntity entity, string originalPath, int newParentId)
{
Entity = entity;
OriginalPath = originalPath;
NewParentId = newParentId;
}
public MoveEventArgs(TEntity eventObject, int parentId) : base(eventObject)
{
ParentId = parentId;
}
public TEntity Entity { get; set; }
public string OriginalPath { get; set; }
public int NewParentId { get; set; }
}
/// <summary>
/// The entity being moved
/// </summary>
public TEntity Entity
{
get { return EventObject; }
}
public class MoveEventArgs<TEntity> : CancellableObjectEventArgs<TEntity>
{
/// <summary>
/// Constructor accepting a collection of MoveEventInfo objects
/// </summary>
/// <param name="canCancel"></param>
/// <param name="moveInfo">
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
/// </param>
public MoveEventArgs(bool canCancel, params MoveEventInfo<TEntity>[] moveInfo)
: base(default(TEntity), canCancel)
{
if (moveInfo.FirstOrDefault() == null)
{
throw new ArgumentException("moveInfo argument must contain at least one item");
}
/// <summary>
/// Gets or Sets the Id of the objects new parent.
/// </summary>
public int ParentId { get; private set; }
}
MoveInfoCollection = moveInfo;
//assign the legacy props
EventObject = moveInfo.First().Entity;
ParentId = moveInfo.First().NewParentId;
}
/// <summary>
/// Constructor accepting a collection of MoveEventInfo objects
/// </summary>
/// <param name="moveInfo">
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
/// </param>
public MoveEventArgs(params MoveEventInfo<TEntity>[] moveInfo)
: base(default(TEntity))
{
if (moveInfo.FirstOrDefault() == null)
{
throw new ArgumentException("moveInfo argument must contain at least one item");
}
MoveInfoCollection = moveInfo;
//assign the legacy props
EventObject = moveInfo.First().Entity;
ParentId = moveInfo.First().NewParentId;
}
[Obsolete("Use the overload that specifies the MoveEventInfo object")]
public MoveEventArgs(TEntity eventObject, bool canCancel, int parentId)
: base(eventObject, canCancel)
{
ParentId = parentId;
}
[Obsolete("Use the overload that specifies the MoveEventInfo object")]
public MoveEventArgs(TEntity eventObject, int parentId)
: base(eventObject)
{
ParentId = parentId;
}
/// <summary>
/// Gets all MoveEventInfo objects used to create the object
/// </summary>
public IEnumerable<MoveEventInfo<TEntity>> MoveInfoCollection { get; private set; }
/// <summary>
/// The entity being moved
/// </summary>
[Obsolete("Retrieve the entity object from the MoveInfoCollection property instead")]
public TEntity Entity
{
get { return EventObject; }
}
/// <summary>
/// Gets the Id of the object's new parent
/// </summary>
[Obsolete("Retrieve the ParentId from the MoveInfoCollection property instead")]
public int ParentId { get; private set; }
}
}
+6
View File
@@ -34,6 +34,12 @@ namespace Umbraco.Core
AddInt(d.GetHashCode());
}
internal void AddString(string s)
{
if (s != null)
AddInt((StringComparer.InvariantCulture).GetHashCode(s));
}
internal void AddCaseInsensitiveString(string s)
{
if (s != null)
+18 -2
View File
@@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.IO
@@ -18,7 +19,10 @@ namespace Umbraco.Core.IO
public static void CopyFile(this IFileSystem fs, string path, string newPath)
{
fs.AddFile(newPath, fs.OpenFile(path));
using (var stream = fs.OpenFile(path))
{
fs.AddFile(newPath, stream);
}
}
public static string GetExtension(this IFileSystem fs, string path)
@@ -30,5 +34,17 @@ namespace Umbraco.Core.IO
{
return Path.GetFileName(fs.GetFullPath(path));
}
//TODO: Currently this is the only way to do this
internal static void CreateFolder(this IFileSystem fs, string folderPath)
{
var path = fs.GetRelativePath(folderPath);
var tempFile = Path.Combine(path, Guid.NewGuid().ToString("N") + ".tmp");
using (var s = new MemoryStream())
{
fs.AddFile(tempFile, s);
}
fs.DeleteFile(tempFile);
}
}
}
+2
View File
@@ -5,6 +5,8 @@ using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.IO
{
//TODO: There is no way to create a directory here without creating a file in a directory and then deleting it
public interface IFileSystem
{
IEnumerable<string> GetDirectories(string path);
+1 -1
View File
@@ -43,7 +43,7 @@ namespace Umbraco.Core.IO
//Replaces tildes with the root dir
public static string ResolveUrl(string virtualPath)
{
if (virtualPath.StartsWith("~"))
if (virtualPath.StartsWith("~"))
return virtualPath.Replace("~", SystemDirectories.Root).Replace("//", "/");
else if (Uri.IsWellFormedUriString(virtualPath, UriKind.Absolute))
return virtualPath;
+3 -2
View File
@@ -93,8 +93,9 @@ namespace Umbraco.Core.IO
public void AddFile(string path, Stream stream, bool overrideIfExists)
{
if (FileExists(path) && !overrideIfExists) throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
var exists = FileExists(path);
if (exists && overrideIfExists == false) throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
EnsureDirectory(Path.GetDirectoryName(path));
if (stream.CanSeek)
+15 -8
View File
@@ -133,16 +133,23 @@ namespace Umbraco.Core.IO
{
if (_size == null)
{
EnsureFileSupportsResizing();
if (_fs.FileExists(Path))
{
EnsureFileSupportsResizing();
var fs = _fs.OpenFile(Path);
var image = Image.FromStream(fs);
var fileWidth = image.Width;
var fileHeight = image.Height;
fs.Close();
image.Dispose();
using (var fs = _fs.OpenFile(Path))
using (var image = Image.FromStream(fs))
{
_size = new Size(fileWidth, fileHeight);
var fileWidth = image.Width;
var fileHeight = image.Height;
_size = new Size(fileWidth, fileHeight);
}
}
else
{
_size = new Size(-1, -1);
}
}
return _size.Value;
}
+45 -20
View File
@@ -232,6 +232,7 @@ namespace Umbraco.Core.Models
/// <remarks>
/// This Property is kept internal until localization is introduced.
/// </remarks>
[DataMember]
internal string NodeName
{
get { return _nodeName; }
@@ -248,6 +249,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Used internally to track if permissions have been changed during the saving process for this entity
/// </summary>
[IgnoreDataMember]
internal bool PermissionsChanged
{
get { return _permissionsChanged; }
@@ -314,6 +316,7 @@ namespace Umbraco.Core.Models
PublishedState = state;
}
[DataMember]
internal PublishedState PublishedState { get; set; }
/// <summary>
@@ -333,26 +336,6 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Creates a clone of the current entity
/// </summary>
/// <returns></returns>
public IContent Clone()
{
var clone = (Content)this.MemberwiseClone();
clone.Key = Guid.Empty;
clone.Version = Guid.NewGuid();
clone.ResetIdentity();
foreach (var property in clone.Properties)
{
property.ResetIdentity();
property.Version = clone.Version;
}
return clone;
}
/// <summary>
/// Indicates whether a specific property on the current <see cref="IContent"/> entity is dirty.
/// </summary>
@@ -432,5 +415,47 @@ namespace Umbraco.Core.Models
base.UpdatingEntity();
Version = Guid.NewGuid();
}
/// <summary>
/// Creates a deep clone of the current entity with its identity and it's property identities reset
/// </summary>
/// <returns></returns>
[Obsolete("Use DeepCloneWithResetIdentities instead")]
public IContent Clone()
{
return DeepCloneWithResetIdentities();
}
/// <summary>
/// Creates a deep clone of the current entity with its identity and it's property identities reset
/// </summary>
/// <returns></returns>
public IContent DeepCloneWithResetIdentities()
{
var clone = (Content)DeepClone();
clone.Key = Guid.Empty;
clone.Version = Guid.NewGuid();
clone.ResetIdentity();
foreach (var property in clone.Properties)
{
property.ResetIdentity();
property.Version = clone.Version;
}
return clone;
}
public override object DeepClone()
{
var clone = (Content)base.DeepClone();
//need to manually clone this since it's not settable
clone._contentType = (IContentType)ContentType.DeepClone();
clone.ResetDirtyProperties(false);
return clone;
}
}
}
+8 -4
View File
@@ -15,10 +15,13 @@ namespace Umbraco.Core.Models
/// <summary>
/// Represents an abstract class for base Content properties and methods
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")]
public abstract class ContentBase : Entity, IContentBase
{
protected IContentTypeComposition ContentTypeBase;
private Lazy<int> _parentId;
private string _name;//NOTE Once localization is introduced this will be the localized Name of the Content/Media.
private int _sortOrder;
@@ -257,6 +260,7 @@ namespace Umbraco.Core.Models
}
private readonly IDictionary<string, object> _additionalData;
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
@@ -306,10 +310,8 @@ namespace Umbraco.Core.Models
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
public virtual TPassType GetValue<TPassType>(string propertyTypeAlias)
{
if (Properties[propertyTypeAlias].Value is TPassType)
return (TPassType)Properties[propertyTypeAlias].Value;
return (TPassType)Convert.ChangeType(Properties[propertyTypeAlias].Value, typeof(TPassType));
var convertAttempt = Properties[propertyTypeAlias].Value.TryConvertTo<TPassType>();
return convertAttempt.Success ? convertAttempt.Result : default(TPassType);
}
/// <summary>
@@ -446,6 +448,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Returns a collection of the result of the last validation process, this collection contains all invalid properties.
/// </summary>
[IgnoreDataMember]
internal IEnumerable<Property> LastInvalidProperties
{
get { return _lastInvalidProperties; }
@@ -467,5 +470,6 @@ namespace Umbraco.Core.Models
prop.ResetDirtyProperties(rememberPreviouslyChangedProperties);
}
}
}
}
+52 -1
View File
@@ -25,6 +25,20 @@ namespace Umbraco.Core.Models
{
#region IContent
/// <summary>
/// Returns true if this entity was just published as part of a recent save operation (i.e. it wasn't previously published)
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
/// <remarks>
/// This is helpful for determining if the published event will execute during the saved event for a content item.
/// </remarks>
internal static bool JustPublished(this IContent entity)
{
var dirty = (IRememberBeingDirty)entity;
return dirty.WasPropertyDirty("Published") && entity.Published;
}
/// <summary>
/// Determines if a new version should be created
/// </summary>
@@ -208,6 +222,28 @@ namespace Umbraco.Core.Models
}
#endregion
/// <summary>
/// Removes characters that are not valide XML characters from all entity properties
/// of type string. See: http://stackoverflow.com/a/961504/5018
/// </summary>
/// <returns></returns>
/// <remarks>
/// If this is not done then the xml cache can get corrupt and it will throw YSODs upon reading it.
/// </remarks>
/// <param name="entity"></param>
public static void SanitizeEntityPropertiesForXmlStorage(this IContentBase entity)
{
entity.Name = entity.Name.ToValidXmlString();
foreach (var property in entity.Properties)
{
if (property.Value is string)
{
var value = (string)property.Value;
property.Value = value.ToValidXmlString();
}
}
}
/// <summary>
/// Checks if the IContentBase has children
/// </summary>
@@ -613,11 +649,16 @@ namespace Umbraco.Core.Models
return ApplicationContext.Current.Services.PackagingService.Export(media);
}
/// <summary>
/// Creates the full xml representation for the <see cref="IMedia"/> object and all of it's descendants
/// </summary>
/// <param name="media"><see cref="IMedia"/> to generate xml for</param>
/// <returns>Xml representation of the passed in <see cref="IMedia"/></returns>
internal static XElement ToDeepXml(this IMedia media)
{
return ApplicationContext.Current.Services.PackagingService.Export(media, true);
}
/// <summary>
/// Creates the xml representation for the <see cref="IContent"/> object
/// </summary>
@@ -630,5 +671,15 @@ namespace Umbraco.Core.Models
//If current IContent is published we should get latest unpublished version
return content.ToXml();
}
/// <summary>
/// Creates the xml representation for the <see cref="IMember"/> object
/// </summary>
/// <param name="member"><see cref="IMember"/> to generate xml for</param>
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
public static XElement ToXml(this IMember member)
{
return ApplicationContext.Current.Services.PackagingService.Export(member);
}
}
}
@@ -0,0 +1,21 @@
using System;
using System.Xml.Linq;
namespace Umbraco.Core.Models
{
/// <summary>
/// Used content repository in order to add an entity to the persisted collection to be saved
/// in a single transaction during saving an entity
/// </summary>
internal class ContentPreviewEntity<TContent> : ContentXmlEntity<TContent>
where TContent : IContentBase
{
public ContentPreviewEntity(bool previewExists, TContent content, Func<TContent, XElement> xml)
: base(previewExists, content, xml)
{
Version = content.Version;
}
public Guid Version { get; private set; }
}
}
+33 -37
View File
@@ -120,38 +120,6 @@ namespace Umbraco.Core.Models
return result;
}
/// <summary>
/// Creates a clone of the current entity
/// </summary>
/// <returns></returns>
public IContentType Clone(string alias)
{
var clone = (ContentType)this.MemberwiseClone();
clone.Alias = alias;
clone.Key = Guid.Empty;
var propertyGroups = this.PropertyGroups.Select(x => x.Clone()).ToList();
clone.PropertyGroups = new PropertyGroupCollection(propertyGroups);
clone.PropertyTypes = this.PropertyTypeCollection.Select(x => x.Clone()).ToList();
clone.ResetIdentity();
clone.ResetDirtyProperties(false);
foreach (var propertyGroup in clone.PropertyGroups)
{
propertyGroup.ResetIdentity();
foreach (var propertyType in propertyGroup.PropertyTypes)
{
propertyType.ResetIdentity();
}
}
foreach (var propertyType in clone.PropertyTypes.Where(x => x.HasIdentity))
{
propertyType.ResetIdentity();
}
return clone;
}
/// <summary>
/// Method to call when Entity is being saved
@@ -165,13 +133,41 @@ namespace Umbraco.Core.Models
Key = Guid.NewGuid();
}
/// <summary>
/// Method to call when Entity is being updated
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
/// <remarks>Modified Date is set and a new Version guid is set</remarks>
internal override void UpdatingEntity()
{
base.UpdatingEntity();
/// <returns></returns>
[Obsolete("Use DeepCloneWithResetIdentities instead")]
public IContentType Clone(string alias)
{
return DeepCloneWithResetIdentities(alias);
}
/// <summary>
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
/// <returns></returns>
public IContentType DeepCloneWithResetIdentities(string alias)
{
var clone = (ContentType)DeepClone();
clone.Alias = alias;
clone.Key = Guid.Empty;
foreach (var propertyGroup in clone.PropertyGroups)
{
propertyGroup.ResetIdentity();
propertyGroup.ResetDirtyProperties(false);
}
foreach (var propertyType in clone.PropertyTypes)
{
propertyType.ResetIdentity();
propertyType.ResetDirtyProperties(false);
}
clone.ResetIdentity();
clone.ResetDirtyProperties(false);
return clone;
}
}
}
+38 -5
View File
@@ -6,6 +6,7 @@ using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Models
{
@@ -43,6 +44,7 @@ namespace Umbraco.Core.Models
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
_propertyTypes = new PropertyTypeCollection();
_propertyTypes.CollectionChanged += PropertyTypesChanged;
_additionalData = new Dictionary<string, object>();
}
@@ -54,6 +56,7 @@ namespace Umbraco.Core.Models
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
_propertyTypes = new PropertyTypeCollection();
_propertyTypes.CollectionChanged += PropertyTypesChanged;
_additionalData = new Dictionary<string, object>();
}
@@ -171,7 +174,8 @@ namespace Umbraco.Core.Models
{
SetPropertyValueAndDetectChanges(o =>
{
_alias = value.ToSafeAlias();
//_alias = value.ToSafeAlias();
_alias = value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase);
return _alias;
}, _alias, AliasSelector);
}
@@ -317,7 +321,7 @@ namespace Umbraco.Core.Models
}
}
private readonly IDictionary<string, object> _additionalData;
private IDictionary<string, object> _additionalData;
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
@@ -347,7 +351,9 @@ namespace Umbraco.Core.Models
/// <summary>
/// List of PropertyGroups available on this ContentType
/// </summary>
/// <remarks>A PropertyGroup corresponds to a Tab in the UI</remarks>
/// <remarks>
/// A PropertyGroup corresponds to a Tab in the UI
/// </remarks>
[DataMember]
public virtual PropertyGroupCollection PropertyGroups
{
@@ -363,7 +369,13 @@ namespace Umbraco.Core.Models
/// List of PropertyTypes available on this ContentType.
/// This list aggregates PropertyTypes across the PropertyGroups.
/// </summary>
/// <remarks>
/// Marked as DoNotClone because the result of this property is not the natural result of the data, it is
/// a union of data so when auto-cloning if the setter is used it will be setting the unnatural result of the
/// data. We manually clone this instead.
/// </remarks>
[IgnoreDataMember]
[DoNotClone]
public virtual IEnumerable<PropertyType> PropertyTypes
{
get
@@ -379,6 +391,14 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Returns the property type collection containing types that are non-groups - used for tests
/// </summary>
internal IEnumerable<PropertyType> NonGroupedPropertyTypes
{
get { return _propertyTypes; }
}
/// <summary>
/// A boolean flag indicating if a property type has been removed from this instance.
/// </summary>
/// <remarks>
@@ -428,8 +448,7 @@ namespace Umbraco.Core.Models
{
if (PropertyTypeExists(propertyType.Alias) == false)
{
_propertyTypes.Add(propertyType);
_propertyTypes.CollectionChanged += PropertyTypesChanged;
_propertyTypes.Add(propertyType);
return true;
}
@@ -576,5 +595,19 @@ namespace Umbraco.Core.Models
propertyType.ResetDirtyProperties();
}
}
public override object DeepClone()
{
var clone = (ContentTypeBase)base.DeepClone();
//need to manually wire up the event handlers for the property type collections - we've ensured
// its ignored from the auto-clone process because its return values are unions, not raw and
// we end up with duplicates, see: http://issues.umbraco.org/issue/U4-4842
clone._propertyTypes = (PropertyTypeCollection)_propertyTypes.DeepClone();
clone._propertyTypes.CollectionChanged += clone.PropertyTypesChanged;
return clone;
}
}
}
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
public abstract class ContentTypeCompositionBase : ContentTypeBase, IContentTypeComposition
{
private readonly List<IContentTypeComposition> _contentTypeComposition = new List<IContentTypeComposition>();
private List<IContentTypeComposition> _contentTypeComposition = new List<IContentTypeComposition>();
internal List<int> RemovedContentTypeKeyTracker = new List<int>();
protected ContentTypeCompositionBase(int parentId) : base(parentId)
@@ -217,5 +217,17 @@ namespace Umbraco.Core.Models
.Select(x => x.Id)
.Union(ContentTypeComposition.SelectMany(x => x.CompositionIds()));
}
public override object DeepClone()
{
var clone = (ContentTypeCompositionBase)base.DeepClone();
//need to manually assign since this is an internal field and will not be automatically mapped
clone.RemovedContentTypeKeyTracker = new List<int>();
clone._contentTypeComposition = ContentTypeComposition.Select(x => (IContentTypeComposition)x.DeepClone()).ToList();
clone.ResetDirtyProperties(false);
return clone;
}
}
}
+32 -1
View File
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Represents a POCO for setting sort order on a ContentType reference
/// </summary>
public class ContentTypeSort : IValueObject
public class ContentTypeSort : IValueObject, IDeepCloneable
{
public ContentTypeSort()
{
@@ -33,5 +33,36 @@ namespace Umbraco.Core.Models
/// Gets or sets the Alias of the ContentType
/// </summary>
public string Alias { get; set; }
public object DeepClone()
{
var clone = (ContentTypeSort)MemberwiseClone();
var id = Id.Value;
clone.Id = new Lazy<int>(() => id);
return clone;
}
protected bool Equals(ContentTypeSort other)
{
return Id.Value.Equals(other.Id.Value) && string.Equals(Alias, other.Alias);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ContentTypeSort) obj);
}
public override int GetHashCode()
{
unchecked
{
return (Id.GetHashCode()*397) ^ Alias.GetHashCode();
}
}
}
}
@@ -0,0 +1,60 @@
using System;
using System.Xml.Linq;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Used in content/media/member repositories in order to add this type of entity to the persisted collection to be saved
/// in a single transaction during saving an entity
/// </summary>
internal class ContentXmlEntity<TContent> : IAggregateRoot
where TContent : IContentBase
{
private readonly bool _entityExists;
private readonly Func<TContent, XElement> _xml;
public ContentXmlEntity(bool entityExists, TContent content, Func<TContent, XElement> xml)
{
if (content == null) throw new ArgumentNullException("content");
_entityExists = entityExists;
_xml = xml;
Content = content;
}
public ContentXmlEntity(TContent content)
{
if (content == null) throw new ArgumentNullException("content");
Content = content;
}
public XElement Xml
{
get { return _xml(Content); }
}
public TContent Content { get; private set; }
public int Id
{
get { return Content.Id; }
set { throw new NotSupportedException(); }
}
public Guid Key { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
public bool HasIdentity
{
get { return _entityExists; }
}
public object DeepClone()
{
var clone = (ContentXmlEntity<TContent>)MemberwiseClone();
//Automatically deep clone ref properties that are IDeepCloneable
DeepCloneHelper.DeepCloneRefProperties(this, clone);
return clone;
}
}
}
+174
View File
@@ -0,0 +1,174 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Umbraco.Core.Models
{
/// <summary>
/// Used to attribute properties that have a setter and are a reference type
/// that should be ignored for cloning when using the DeepCloneHelper
/// </summary>
/// <remarks>
///
/// This attribute must be used:
/// * when the property is backed by a field but the result of the property is the un-natural data stored in the field
///
/// This attribute should not be used:
/// * when the property is virtual
/// * when the setter performs additional required logic other than just setting the underlying field
///
/// </remarks>
internal class DoNotCloneAttribute : Attribute
{
}
public static class DeepCloneHelper
{
/// <summary>
/// Used to avoid constant reflection (perf)
/// </summary>
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropCache = new ConcurrentDictionary<Type, PropertyInfo[]>();
/// <summary>
/// Used to deep clone any reference properties on the object (should be done after a MemberwiseClone for which the outcome is 'output')
/// </summary>
/// <param name="input"></param>
/// <param name="output"></param>
/// <returns></returns>
public static void DeepCloneRefProperties(IDeepCloneable input, IDeepCloneable output)
{
var inputType = input.GetType();
var outputType = output.GetType();
if (inputType != outputType)
{
throw new InvalidOperationException("Both the input and output types must be the same");
}
var refProperties = PropCache.GetOrAdd(inputType, type =>
inputType.GetProperties()
.Where(x =>
//is not attributed with the ignore clone attribute
Attribute.GetCustomAttribute(x, typeof(DoNotCloneAttribute)) == null
//reference type but not string
&& x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
//settable
&& x.CanWrite
//non-indexed
&& x.GetIndexParameters().Any() == false)
.ToArray());
foreach (var propertyInfo in refProperties)
{
if (TypeHelper.IsTypeAssignableFrom<IDeepCloneable>(propertyInfo.PropertyType))
{
//this ref property is also deep cloneable so clone it
var result = (IDeepCloneable)propertyInfo.GetValue(input, null);
if (result != null)
{
//set the cloned value to the property
propertyInfo.SetValue(output, result.DeepClone(), null);
}
}
else if (TypeHelper.IsTypeAssignableFrom<IEnumerable>(propertyInfo.PropertyType)
&& TypeHelper.IsTypeAssignableFrom<string>(propertyInfo.PropertyType) == false)
{
IList newList;
if (propertyInfo.PropertyType.IsGenericType
&& (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
{
//if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<>
var genericType = typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GetGenericArguments());
newList = (IList)Activator.CreateInstance(genericType);
}
else if (propertyInfo.PropertyType.IsArray
|| (propertyInfo.PropertyType.IsInterface && propertyInfo.PropertyType.IsGenericType == false))
{
//if its an array, we'll create a list to work with first and then convert to array later
//otherwise if its just a regular derivitave of IEnumerable, we can use a list too
newList = new List<object>();
}
else
{
//its a custom IEnumerable, we'll try to create it
try
{
var custom = Activator.CreateInstance(propertyInfo.PropertyType);
//if it's an IList we can work with it, otherwise we cannot
newList = custom as IList;
if (newList == null)
{
continue;
}
}
catch (Exception)
{
//could not create this type so we'll skip it
continue;
}
}
var enumerable = (IEnumerable)propertyInfo.GetValue(input, null);
if (enumerable == null) continue;
var isUsableType = true;
//now clone each item
foreach (var o in enumerable)
{
//first check if the item is deep cloneable and copy that way
var dc = o as IDeepCloneable;
if (dc != null)
{
newList.Add(dc.DeepClone());
}
else if (o is string || o.GetType().IsValueType)
{
//check if the item is a value type or a string, then we can just use it
newList.Add(o);
}
else
{
//this will occur if the item is not a string or value type or IDeepCloneable, in this case we cannot
// clone each element, we'll need to skip this property, people will have to manually clone this list
isUsableType = false;
break;
}
}
//if this was not usable, skip this property
if (isUsableType == false)
{
continue;
}
if (propertyInfo.PropertyType.IsArray)
{
//need to convert to array
var arr = (object[])Activator.CreateInstance(propertyInfo.PropertyType, newList.Count);
for (int i = 0; i < newList.Count; i++)
{
arr[i] = newList[i];
}
//set the cloned collection
propertyInfo.SetValue(output, arr, null);
}
else
{
//set the cloned collection
propertyInfo.SetValue(output, newList, null);
}
}
}
}
}
}
+2 -1
View File
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Models
{
@@ -97,5 +97,6 @@ namespace Umbraco.Core.Models
if(ParentId == Guid.Empty)
_parentId = new Guid("41c7638d-f529-4bff-853e-59a0c2fb1bde");
}
}
}
@@ -65,5 +65,6 @@ namespace Umbraco.Core.Models
}, _value, ValueSelector);
}
}
}
}
+62 -1
View File
@@ -1,7 +1,10 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
namespace Umbraco.Core.Models.EntityBase
{
@@ -93,7 +96,7 @@ namespace Umbraco.Core.Models.EntityBase
}
/// <summary>
/// /// Gets or sets the WasCancelled flag, which is used to track
/// 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.
@@ -155,6 +158,7 @@ namespace Umbraco.Core.Models.EntityBase
/// <summary>
/// Indicates whether the current entity has an identity, eg. Id.
/// </summary>
[DataMember]
public virtual bool HasIdentity
{
get
@@ -226,5 +230,62 @@ namespace Umbraco.Core.Models.EntityBase
_hash = !HasIdentity ? new int?(base.GetHashCode()) : new int?(Id.GetHashCode() * 397 ^ GetType().GetHashCode());
return _hash.Value;
}
public virtual object DeepClone()
{
//Memberwise clone on Entity will work since it doesn't have any deep elements
// for any sub class this will work for standard properties as well that aren't complex object's themselves.
var clone = (Entity)MemberwiseClone();
//Automatically deep clone ref properties that are IDeepCloneable
DeepCloneHelper.DeepCloneRefProperties(this, clone);
clone.ResetDirtyProperties(false);
return clone;
//Using data contract serializer - has issues
//var s = Serialize(this);
//var d = Deserialize(s, this.GetType());
//return d;
//Using binary serializer - has issues
//using (var memoryStream = new MemoryStream(10))
//{
//IFormatter formatter = new BinaryFormatter();
//formatter.Serialize(memoryStream, this);
//memoryStream.Seek(0, SeekOrigin.Begin);
//return formatter.Deserialize(memoryStream);
//}
}
// serialize/deserialize with data contracts:
//public static string Serialize(object obj)
//{
// using (var memoryStream = new MemoryStream())
// using (var reader = new StreamReader(memoryStream))
// {
// var serializer = new DataContractSerializer(obj.GetType());
// serializer.WriteObject(memoryStream, obj);
// memoryStream.Position = 0;
// return reader.ReadToEnd();
// }
//}
//public static object Deserialize(string xml, Type toType)
//{
// using (Stream stream = new MemoryStream())
// {
// using (var writer = new StreamWriter(stream, Encoding.UTF8))
// {
// writer.Write(xml);
// //byte[] data = Encoding.UTF8.GetBytes(xml);
// //stream.Write(data, 0, data.Length);
// stream.Position = 0;
// var deserializer = new DataContractSerializer(toType);
// return deserializer.ReadObject(stream);
// }
// }
//}
}
}
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Models.EntityBase
/// </summary>
/// <remarks>The current database schema doesn't provide a modified date
/// for all entities, so this will have to be changed at a later stage.</remarks>
public interface IEntity
public interface IEntity : IDeepCloneable
{
/// <summary>
/// The Id of the entity
@@ -3,18 +3,21 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models.EntityBase
{
/// <summary>
/// A base class for use to implement IRememberBeingDirty/ICanBeDirty
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public abstract class TracksChangesEntityBase : IRememberBeingDirty
{
/// <summary>
/// Tracks the properties that have changed
/// </summary>
private readonly IDictionary<string, bool> _propertyChangedInfo = new Dictionary<string, bool>();
private IDictionary<string, bool> _propertyChangedInfo = new Dictionary<string, bool>();
/// <summary>
/// Tracks the properties that we're changed before the last commit (or last call to ResetDirtyProperties)
@@ -83,7 +86,9 @@ namespace Umbraco.Core.Models.EntityBase
/// </summary>
public void ForgetPreviouslyDirtyProperties()
{
_lastPropertyChangedInfo.Clear();
//NOTE: We cannot .Clear() because when we memberwise clone this will be the SAME
// instance as the one on the clone, so we need to create a new instance.
_lastPropertyChangedInfo = new Dictionary<string, bool>();
}
/// <summary>
@@ -116,7 +121,9 @@ namespace Umbraco.Core.Models.EntityBase
_lastPropertyChangedInfo = _propertyChangedInfo.ToDictionary(v => v.Key, v => v.Value);
}
_propertyChangedInfo.Clear();
//NOTE: We cannot .Clear() because when we memberwise clone this will be the SAME
// instance as the one on the clone, so we need to create a new instance.
_propertyChangedInfo = new Dictionary<string, bool>();
}
/// <summary>
@@ -0,0 +1,24 @@
using System.Linq;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
public static class EntityExtensions
{
/// <summary>
/// Returns true if this entity has just been created and persisted to the data store
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
/// <remarks>
/// This is useful when handling events to determine if an entity is a brand new entity or was
/// already existing.
/// </remarks>
public static bool IsNewEntity(this IEntity entity)
{
var dirty = (IRememberBeingDirty)entity;
return dirty.WasPropertyDirty("Id");
}
}
}
+32 -5
View File
@@ -23,6 +23,8 @@ namespace Umbraco.Core.Models
private static readonly PropertyInfo ContentSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Content);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Path);
private string _alias;
private string _name;
/// <summary>
/// Gets or sets the Name of the File including extension
@@ -32,7 +34,11 @@ namespace Umbraco.Core.Models
{
get
{
return new FileInfo(Path).Name;
if (_name == null)
{
_name = System.IO.Path.GetFileName(Path);
}
return _name;
}
}
@@ -44,10 +50,14 @@ namespace Umbraco.Core.Models
{
get
{
var fileInfo = new FileInfo(Path);
var name = fileInfo.Name;
int lastIndexOf = name.LastIndexOf(".", StringComparison.InvariantCultureIgnoreCase);
return name.Substring(0, lastIndexOf);
if (_alias == null)
{
var name = System.IO.Path.GetFileName(Path);
if (name == null) return string.Empty;
var lastIndexOf = name.LastIndexOf(".", StringComparison.InvariantCultureIgnoreCase);
_alias = name.Substring(0, lastIndexOf);
}
return _alias;
}
}
@@ -60,6 +70,10 @@ namespace Umbraco.Core.Models
get { return _path; }
set
{
//reset
_alias = null;
_name = null;
SetPropertyValueAndDetectChanges(o =>
{
_path = value;
@@ -90,5 +104,18 @@ namespace Umbraco.Core.Models
/// </summary>
/// <returns>True if file is valid, otherwise false</returns>
public abstract bool IsValid();
public override object DeepClone()
{
var clone = (File)base.DeepClone();
//need to manually assign since they are readonly properties
clone._alias = Alias;
clone._name = Name;
clone.ResetDirtyProperties(false);
return clone;
}
}
}
+14
View File
@@ -0,0 +1,14 @@
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
internal sealed class Folder : Entity
{
public Folder(string folderPath)
{
Path = folderPath;
}
public string Path { get; set; }
}
}
+6
View File
@@ -72,5 +72,11 @@ namespace Umbraco.Core.Models
/// Changes the Published state of the content object
/// </summary>
void ChangePublishedState(PublishedState state);
/// <summary>
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
/// <returns></returns>
IContent DeepCloneWithResetIdentities();
}
}
+7
View File
@@ -29,5 +29,12 @@ namespace Umbraco.Core.Models
/// <param name="template"><see cref="ITemplate"/> to remove</param>
/// <returns>True if template was removed, otherwise False</returns>
bool RemoveTemplate(ITemplate template);
/// <summary>
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
/// <param name="newAlias"></param>
/// <returns></returns>
IContentType DeepCloneWithResetIdentities(string newAlias);
}
}
@@ -0,0 +1,9 @@
using System.Reflection;
namespace Umbraco.Core.Models
{
public interface IDeepCloneable
{
object DeepClone();
}
}
+2 -98
View File
@@ -1,106 +1,10 @@
using System;
using Umbraco.Core.Models.Membership;
namespace Umbraco.Core.Models
{
public interface IMember : IContentBase
public interface IMember : IContentBase, IMembershipUser
{
/// <summary>
/// Gets or sets the Username
/// </summary>
string Username { get; set; }
/// <summary>
/// Gets or sets the Email
/// </summary>
string Email { get; set; }
/// <summary>
/// Gets or sets the Password
/// </summary>
string Password { get; set; }
/// <summary>
/// Gets or sets the Password Question
/// </summary>
/// <remarks>
/// Alias: umbracoPasswordRetrievalQuestionPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
string PasswordQuestion { get; set; }
/// <summary>
/// Gets or sets the Password Answer
/// </summary>
/// <remarks>
/// Alias: umbracoPasswordRetrievalAnswerPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
string PasswordAnswer { get; set; }
/// <summary>
/// Gets or set the comments for the member
/// </summary>
/// <remarks>
/// Alias: umbracoCommentPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
string Comments { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the Member is approved
/// </summary>
/// <remarks>
/// Alias: umbracoApprovePropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
bool IsApproved { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the Member is locked out
/// </summary>
/// <remarks>
/// Alias: umbracoLockPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
bool IsLockedOut { get; set; }
/// <summary>
/// Gets or sets the date for last login
/// </summary>
/// <remarks>
/// Alias: umbracoLastLoginPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
DateTime LastLoginDate { get; set; }
/// <summary>
/// Gest or sets the date for last password change
/// </summary>
/// <remarks>
/// Alias: umbracoMemberLastPasswordChange
/// Part of the standard properties collection.
/// </remarks>
DateTime LastPasswordChangeDate { get; set; }
/// <summary>
/// Gets or sets the date for when Member was locked out
/// </summary>
/// <remarks>
/// Alias: umbracoMemberLastLockout
/// Part of the standard properties collection.
/// </remarks>
DateTime LastLockoutDate { get; set; }
/// <summary>
/// Gets or sets the number of failed password attempts.
/// This is the number of times the password was entered incorrectly upon login.
/// </summary>
/// <remarks>
/// Alias: umbracoFailedPasswordAttemptsPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
int FailedPasswordAttempts { get; set; }
/// <summary>
/// String alias of the default ContentType
/// </summary>
+26
View File
@@ -0,0 +1,26 @@
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a member type
/// </summary>
public interface IMemberGroup : IAggregateRoot
{
/// <summary>
/// The name of the member group
/// </summary>
string Name { get; set; }
/// <summary>
/// Profile of the user who created this Entity
/// </summary>
int CreatorId { get; set; }
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
IDictionary<string, object> AdditionalData { get; }
}
}
+3 -3
View File
@@ -107,7 +107,7 @@ namespace Umbraco.Core.Models
/// <para>The properties collection of an IPublishedContent instance should be read-only ie it is illegal
/// to add properties to the collection.</para>
/// </remarks>
ICollection<IPublishedProperty> Properties { get; }
ICollection<IPublishedContentProperty> Properties { get; }
/// <summary>
/// Gets a property identified by its alias.
@@ -119,7 +119,7 @@ namespace Umbraco.Core.Models
/// <para>otherwise return a property -- that may have no value (ie <c>HasValue</c> is <c>false</c>).</para>
/// <para>The alias is case-insensitive.</para>
/// </remarks>
IPublishedProperty GetProperty(string alias);
IPublishedContentProperty GetProperty(string alias);
/// <summary>
/// Gets a property identified by its alias.
@@ -133,7 +133,7 @@ namespace Umbraco.Core.Models
/// return the first property that was found with the alias but had no value (ie <c>HasValue</c> is <c>false</c>).</para>
/// <para>The alias is case-insensitive.</para>
/// </remarks>
IPublishedProperty GetProperty(string alias, bool recurse);
IPublishedContentProperty GetProperty(string alias, bool recurse);
/// <summary>
/// Gets the value of a property identified by its alias.
@@ -1,9 +1,11 @@
using System;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a property of an <c>IPublishedContent</c>.
/// </summary>
public interface IPublishedProperty
public interface IPublishedContentProperty
{
/// <summary>
/// Gets the alias of the property.
@@ -56,5 +58,8 @@ namespace Umbraco.Core.Models
/// <para>It has been fully prepared and processed by the appropriate converter.</para>
/// </remarks>
object XPathValue { get; }
string Alias { get; }
Guid Version { get; }
}
}
+38
View File
@@ -0,0 +1,38 @@
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
public interface IRelation : IAggregateRoot
{
/// <summary>
/// Gets or sets the Parent Id of the Relation (Source)
/// </summary>
[DataMember]
int ParentId { get; set; }
/// <summary>
/// Gets or sets the Child Id of the Relation (Destination)
/// </summary>
[DataMember]
int ChildId { get; set; }
/// <summary>
/// Gets or sets the <see cref="RelationType"/> for the Relation
/// </summary>
[DataMember]
IRelationType RelationType { get; set; }
/// <summary>
/// Gets or sets a comment for the Relation
/// </summary>
[DataMember]
string Comment { get; set; }
/// <summary>
/// Gets the Id of the <see cref="RelationType"/> that this Relation is based on.
/// </summary>
[IgnoreDataMember]
int RelationTypeId { get; }
}
}
+41
View File
@@ -0,0 +1,41 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
public interface IRelationType : IAggregateRoot
{
/// <summary>
/// Gets or sets the Name of the RelationType
/// </summary>
[DataMember]
string Name { get; set; }
/// <summary>
/// Gets or sets the Alias of the RelationType
/// </summary>
[DataMember]
string Alias { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the RelationType is Bidirectional (true) or Parent to Child (false)
/// </summary>
[DataMember]
bool IsBidirectional { get; set; }
/// <summary>
/// Gets or sets the Parents object type id
/// </summary>
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
[DataMember]
Guid ParentObjectType { get; set; }
/// <summary>
/// Gets or sets the Childs object type id
/// </summary>
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
[DataMember]
Guid ChildObjectType { get; set; }
}
}
+6
View File
@@ -10,5 +10,11 @@
/// </summary>
/// <returns><see cref="RenderingEngine"/></returns>
RenderingEngine GetTypeOfRenderingEngine();
/// <summary>
/// Set the mastertemplate
/// </summary>
/// <param name="masterTemplate"></param>
void SetMasterTemplate(ITemplate masterTemplate);
}
}
-1
View File
@@ -3,7 +3,6 @@ using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Models
{
+285 -78
View File
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Models
{
@@ -12,40 +14,105 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
public class Member : ContentBase, IMember
{
private readonly IMemberType _contentType;
private string _contentTypeAlias;
private IMemberType _contentType;
private readonly string _contentTypeAlias;
private string _username;
private string _email;
private string _password;
private string _rawPasswordValue;
private object _providerUserKey;
private Type _userTypeKey;
public Member(string name, string email, string username, string password, int parentId, IMemberType contentType)
: base(name, parentId, contentType, new PropertyCollection())
/// <summary>
/// Constructor for creating an empty Member object
/// </summary>
/// <param name="contentType">ContentType for the current Content object</param>
public Member(IMemberType contentType)
: base("", -1, contentType, new PropertyCollection())
{
Mandate.ParameterNotNull(contentType, "contentType");
_contentTypeAlias = contentType.Alias;
_contentType = contentType;
IsApproved = true;
//this cannot be null but can be empty
_rawPasswordValue = "";
_email = "";
_username = "";
}
/// <summary>
/// Constructor for creating a Member object
/// </summary>
/// <param name="name">Name of the content</param>
/// <param name="contentType">ContentType for the current Content object</param>
public Member(string name, IMemberType contentType)
: this(contentType)
{
Mandate.ParameterNotNull(contentType, "contentType");
Mandate.ParameterNotNullOrEmpty(name, "name");
_contentTypeAlias = contentType.Alias;
_contentType = contentType;
IsApproved = true;
//this cannot be null but can be empty
_rawPasswordValue = "";
_email = "";
_username = "";
}
/// <summary>
/// Constructor for creating a Member object
/// </summary>
/// <param name="name"></param>
/// <param name="email"></param>
/// <param name="username"></param>
/// <param name="contentType"></param>
public Member(string name, string email, string username, IMemberType contentType)
: base(name, -1, contentType, new PropertyCollection())
{
Mandate.ParameterNotNull(contentType, "contentType");
Mandate.ParameterNotNullOrEmpty(name, "name");
Mandate.ParameterNotNullOrEmpty(email, "email");
Mandate.ParameterNotNullOrEmpty(username, "username");
_contentTypeAlias = contentType.Alias;
_contentType = contentType;
_email = email;
_username = username;
_password = password;
IsApproved = true;
//this cannot be null but can be empty
_rawPasswordValue = "";
}
public Member(string name, string email, string username, string password, IContentBase parent, IMemberType contentType)
: base(name, parent, contentType, new PropertyCollection())
/// <summary>
/// Constructor for creating a Member object
/// </summary>
/// <param name="name"></param>
/// <param name="email"></param>
/// <param name="username"></param>
/// <param name="rawPasswordValue">
/// The password value passed in to this parameter should be the encoded/encrypted/hashed format of the member's password
/// </param>
/// <param name="contentType"></param>
public Member(string name, string email, string username, string rawPasswordValue, IMemberType contentType)
: base(name, -1, contentType, new PropertyCollection())
{
Mandate.ParameterNotNull(contentType, "contentType");
_contentTypeAlias = contentType.Alias;
_contentType = contentType;
_email = email;
_username = username;
_password = password;
_rawPasswordValue = rawPasswordValue;
IsApproved = true;
}
private static readonly PropertyInfo DefaultContentTypeAliasSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.ContentTypeAlias);
private static readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Username);
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Email);
private static readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Password);
private static readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.RawPasswordValue);
private static readonly PropertyInfo ProviderUserKeySelector = ExpressionHelper.GetPropertyInfo<Member, object>(x => x.ProviderUserKey);
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<Member, Type>(x => x.ProviderUserKeyType);
@@ -84,19 +151,19 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Gets or sets the Password
/// Gets or sets the raw password value
/// </summary>
[DataMember]
public string Password
[IgnoreDataMember]
public string RawPasswordValue
{
get { return _password; }
get { return _rawPasswordValue; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_password = value;
return _password;
}, _password, PasswordSelector);
_rawPasswordValue = value;
return _rawPasswordValue;
}, _rawPasswordValue, PasswordSelector);
}
}
@@ -113,39 +180,55 @@ namespace Umbraco.Core.Models
/// Alias: umbracoPasswordRetrievalQuestionPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
[DataMember]
public string PasswordQuestion
{
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.PasswordQuestion, "PasswordQuestion", default(string));
if (a.Success == false) return a.Result;
return Properties[Constants.Conventions.Member.PasswordQuestion].Value == null
? string.Empty
: Properties[Constants.Conventions.Member.PasswordQuestion].Value.ToString();
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.PasswordQuestion,
"PasswordQuestion") == false) return;
Properties[Constants.Conventions.Member.PasswordQuestion].Value = value;
}
}
/// <summary>
/// Gets or sets the Password Answer
/// Gets or sets the raw password answer value
/// </summary>
/// <remarks>
/// For security reasons this value should be encrypted, the encryption process is handled by the memberhip provider
///
/// Alias: umbracoPasswordRetrievalAnswerPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
public string PasswordAnswer
public string RawPasswordAnswerValue
{
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.PasswordAnswer, "PasswordAnswer", default(string));
if (a.Success == false) return a.Result;
return Properties[Constants.Conventions.Member.PasswordAnswer].Value == null
? string.Empty
: Properties[Constants.Conventions.Member.PasswordAnswer].Value.ToString();
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.PasswordAnswer,
"PasswordAnswer") == false) return;
Properties[Constants.Conventions.Member.PasswordAnswer].Value = value;
}
}
@@ -157,17 +240,24 @@ namespace Umbraco.Core.Models
/// Alias: umbracoCommentPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
[DataMember]
public string Comments
{
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.Comments, "Comments", default(string));
if (a.Success == false) return a.Result;
return Properties[Constants.Conventions.Member.Comments].Value == null
? string.Empty
: Properties[Constants.Conventions.Member.Comments].Value.ToString();
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.Comments,
"Comments") == false) return;
Properties[Constants.Conventions.Member.Comments].Value = value;
}
}
@@ -179,21 +269,30 @@ namespace Umbraco.Core.Models
/// Alias: umbracoApprovePropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
[DataMember]
public bool IsApproved
{
get
{
if (Properties[Constants.Conventions.Member.IsApproved].Value == null)
return default(bool);
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.IsApproved, "IsApproved",
//This is the default value if the prop is not found
true);
if (a.Success == false) return a.Result;
if (Properties[Constants.Conventions.Member.IsApproved].Value is bool)
return (bool)Properties[Constants.Conventions.Member.IsApproved].Value;
return (bool)Convert.ChangeType(Properties[Constants.Conventions.Member.IsApproved].Value, typeof(bool));
var tryConvert = Properties[Constants.Conventions.Member.IsApproved].Value.TryConvertTo<bool>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
//if the property exists but it cannot be converted, we will assume true
return true;
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.IsApproved,
"IsApproved") == false) return;
Properties[Constants.Conventions.Member.IsApproved].Value = value;
}
}
@@ -205,21 +304,27 @@ namespace Umbraco.Core.Models
/// Alias: umbracoLockPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
[DataMember]
public bool IsLockedOut
{
get
{
if (Properties[Constants.Conventions.Member.IsLockedOut].Value == null)
return default(bool);
if (Properties[Constants.Conventions.Member.IsLockedOut].Value is bool)
return (bool)Properties[Constants.Conventions.Member.IsLockedOut].Value;
return (bool)Convert.ChangeType(Properties[Constants.Conventions.Member.IsLockedOut].Value, typeof(bool));
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.IsLockedOut, "IsLockedOut", false);
if (a.Success == false) return a.Result;
var tryConvert = Properties[Constants.Conventions.Member.IsLockedOut].Value.TryConvertTo<bool>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return false;
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.IsLockedOut,
"IsLockedOut") == false) return;
Properties[Constants.Conventions.Member.IsLockedOut].Value = value;
}
}
@@ -231,21 +336,27 @@ namespace Umbraco.Core.Models
/// Alias: umbracoLastLoginPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
[DataMember]
public DateTime LastLoginDate
{
get
{
if (Properties[Constants.Conventions.Member.LastLoginDate].Value == null)
return default(DateTime);
if (Properties[Constants.Conventions.Member.LastLoginDate].Value is DateTime)
return (DateTime)Properties[Constants.Conventions.Member.LastLoginDate].Value;
return (DateTime)Convert.ChangeType(Properties[Constants.Conventions.Member.LastLoginDate].Value, typeof(DateTime));
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastLoginDate, "LastLoginDate", default(DateTime));
if (a.Success == false) return a.Result;
var tryConvert = Properties[Constants.Conventions.Member.LastLoginDate].Value.TryConvertTo<DateTime>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return default(DateTime);
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.LastLoginDate,
"LastLoginDate") == false) return;
Properties[Constants.Conventions.Member.LastLoginDate].Value = value;
}
}
@@ -257,21 +368,27 @@ namespace Umbraco.Core.Models
/// Alias: umbracoMemberLastPasswordChange
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
[DataMember]
public DateTime LastPasswordChangeDate
{
get
{
if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value == null)
return default(DateTime);
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastPasswordChangeDate, "LastPasswordChangeDate", default(DateTime));
if (a.Success == false) return a.Result;
if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value is DateTime)
return (DateTime)Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value;
return (DateTime)Convert.ChangeType(Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value, typeof(DateTime));
var tryConvert = Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value.TryConvertTo<DateTime>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return default(DateTime);
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.LastPasswordChangeDate,
"LastPasswordChangeDate") == false) return;
Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value = value;
}
}
@@ -283,21 +400,27 @@ namespace Umbraco.Core.Models
/// Alias: umbracoMemberLastLockout
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
[DataMember]
public DateTime LastLockoutDate
{
get
{
if (Properties[Constants.Conventions.Member.LastLockoutDate].Value == null)
return default(DateTime);
if (Properties[Constants.Conventions.Member.LastLockoutDate].Value is DateTime)
return (DateTime)Properties[Constants.Conventions.Member.LastLockoutDate].Value;
return (DateTime)Convert.ChangeType(Properties[Constants.Conventions.Member.LastLockoutDate].Value, typeof(DateTime));
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastLockoutDate, "LastLockoutDate", default(DateTime));
if (a.Success == false) return a.Result;
var tryConvert = Properties[Constants.Conventions.Member.LastLockoutDate].Value.TryConvertTo<DateTime>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return default(DateTime);
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.LastLockoutDate,
"LastLockoutDate") == false) return;
Properties[Constants.Conventions.Member.LastLockoutDate].Value = value;
}
}
@@ -310,22 +433,28 @@ namespace Umbraco.Core.Models
/// Alias: umbracoFailedPasswordAttemptsPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
[DataMember]
public int FailedPasswordAttempts
{
get
{
if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value == null)
return default(int);
if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value is int)
return (int)Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value;
return (int)Convert.ChangeType(Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value, typeof(int));
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.FailedPasswordAttempts, "FailedPasswordAttempts", 0);
if (a.Success == false) return a.Result;
var tryConvert = Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value.TryConvertTo<int>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return default(int);
}
set
{
Properties[Constants.Conventions.Member.LastLockoutDate].Value = value;
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.FailedPasswordAttempts,
"FailedPasswordAttempts") == false) return;
Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value = value;
}
}
@@ -336,14 +465,6 @@ namespace Umbraco.Core.Models
public virtual string ContentTypeAlias
{
get { return _contentTypeAlias; }
internal set
{
SetPropertyValueAndDetectChanges(o =>
{
_contentTypeAlias = value;
return _contentTypeAlias;
}, _contentTypeAlias, DefaultContentTypeAliasSelector);
}
}
/// <summary>
@@ -356,7 +477,7 @@ namespace Umbraco.Core.Models
/// membership provider.
/// </remarks>
[DataMember]
internal virtual object ProviderUserKey
public virtual object ProviderUserKey
{
get
{
@@ -433,11 +554,97 @@ namespace Umbraco.Core.Models
/* Internal experiment - only used for mapping queries.
* Adding these to have first level properties instead of the Properties collection.
*/
[IgnoreDataMember]
internal string LongStringPropertyValue { get; set; }
[IgnoreDataMember]
internal string ShortStringPropertyValue { get; set; }
[IgnoreDataMember]
internal int IntegerropertyValue { get; set; }
[IgnoreDataMember]
internal bool BoolPropertyValue { get; set; }
[IgnoreDataMember]
internal DateTime DateTimePropertyValue { get; set; }
[IgnoreDataMember]
internal string PropertyTypeAlias { get; set; }
private Attempt<T> WarnIfPropertyTypeNotFoundOnGet<T>(string propertyAlias, string propertyName, T defaultVal)
{
Action doLog = () => LogHelper.Warn<Member>(
"Trying to access the '"
+ propertyName
+ "' property on "
+ typeof(Member)
+ " but the "
+ propertyAlias
+ " property does not exist on the member type so a default value is returned. Ensure that you have a property type with alias: "
+ propertyAlias
+ " configured on your member type in order to use the '"
+ propertyName
+ "' property on the model correctly.");
//if the property doesn't exist, then do the logging and return a failure
if (Properties.Contains(propertyAlias) == false)
{
//we'll put a warn in the log if this entity has been persisted
if (HasIdentity)
{
doLog();
}
return Attempt<T>.Fail(defaultVal);
}
//if the property doesn't have an identity but we do, then do logging and return failure
var prop = Properties.Single(x => x.Alias == propertyAlias);
if (prop.HasIdentity == false && HasIdentity)
{
doLog();
return Attempt<T>.Fail(defaultVal);
}
return Attempt<T>.Succeed();
}
private bool WarnIfPropertyTypeNotFoundOnSet(string propertyAlias, string propertyname)
{
Action doLog = () => LogHelper.Warn<Member>("An attempt was made to set a value on the property '"
+ propertyname
+ "' on type "
+ typeof(Member)
+ " but the property type "
+ propertyAlias
+ " does not exist on the member type, ensure that this property type exists so that setting this property works correctly.");
//if the property doesn't exist, then do the logging and return a failure
if (Properties.Contains(propertyAlias) == false)
{
if (HasIdentity)
{
doLog();
}
return false;
}
//if the property doesn't have an identity but we do, then do logging and return failure
var prop = Properties.Single(x => x.Alias == propertyAlias);
if (prop.HasIdentity == false && HasIdentity)
{
doLog();
return false;
}
return true;
}
public override object DeepClone()
{
var clone = (Member)base.DeepClone();
//need to manually clone this since it's not settable
clone._contentType = (IMemberType)ContentType.DeepClone();
clone.ResetDirtyProperties(false);
return clone;
}
}
}
+76
View File
@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a member type
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class MemberGroup : Entity, IMemberGroup
{
public MemberGroup()
{
AdditionalData = new Dictionary<string, object>();
}
private string _name;
private int _creatorId;
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<MemberGroup, string>(x => x.Name);
private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<MemberGroup, int>(x => x.CreatorId);
[DataMember]
public string Name
{
get { return _name; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
if (_name != value)
{
//if the name has changed, add the value to the additional data,
//this is required purely for event handlers to know the previous name of the group
//so we can keep the public access up to date.
AdditionalData["previousName"] = _name;
}
_name = value;
return _name;
}, _name, NameSelector);
}
}
public int CreatorId
{
get { return _creatorId; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_creatorId = value;
return _creatorId;
}, _creatorId, CreatorIdSelector);
}
}
public IDictionary<string, object> AdditionalData { get; private set; }
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
}
}
+29 -20
View File
@@ -14,37 +14,50 @@ namespace Umbraco.Core.Models
public class MemberType : ContentTypeCompositionBase, IMemberType
{
//Dictionary is divided into string: PropertyTypeAlias, Tuple: MemberCanEdit, VisibleOnProfile, PropertyTypeId
private IDictionary<string, Tuple<bool, bool, int>> _memberTypePropertyTypes;
private string _alias;
public MemberType(int parentId) : base(parentId)
{
_memberTypePropertyTypes = new Dictionary<string, Tuple<bool, bool, int>>();
MemberTypePropertyTypes = new Dictionary<string, MemberTypePropertyProfileAccess>();
}
public MemberType(IContentTypeComposition parent) : base(parent)
{
_memberTypePropertyTypes = new Dictionary<string, Tuple<bool, bool, int>>();
MemberTypePropertyTypes = new Dictionary<string, MemberTypePropertyProfileAccess>();
}
private static readonly PropertyInfo MemberTypePropertyTypesSelector = ExpressionHelper.GetPropertyInfo<MemberType, IDictionary<string, Tuple<bool, bool, int>>>(x => x.MemberTypePropertyTypes);
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MemberType, string>(x => x.Alias);
/// <summary>
/// Gets or Sets a Dictionary of Tuples (MemberCanEdit, VisibleOnProfile, PropertyTypeId) by the PropertyTypes' alias.
/// The Alias of the ContentType
/// </summary>
[DataMember]
internal IDictionary<string, Tuple<bool, bool, int>> MemberTypePropertyTypes
public override string Alias
{
get { return _memberTypePropertyTypes; }
get { return _alias; }
set
{
//NOTE: WE are overriding this because we don't want to do a ToSafeAlias when the alias is the special case of
// "_umbracoSystemDefaultProtectType" which is used internally, currently there is an issue with the safe alias as it strips
// leading underscores which we don't want in this case.
// see : http://issues.umbraco.org/issue/U4-3968
SetPropertyValueAndDetectChanges(o =>
{
_memberTypePropertyTypes = value;
return _memberTypePropertyTypes;
}, _memberTypePropertyTypes, MemberTypePropertyTypesSelector);
_alias = value == "_umbracoSystemDefaultProtectType"
? value
: (value == null ? string.Empty : value.ToSafeAlias() );
return _alias;
}, _alias, AliasSelector);
}
}
/// <summary>
/// Gets or Sets a Dictionary of Tuples (MemberCanEdit, VisibleOnProfile) by the PropertyTypes' alias.
/// </summary>
[DataMember]
internal IDictionary<string, MemberTypePropertyProfileAccess> MemberTypePropertyTypes { get; private set; }
/// <summary>
/// Gets a boolean indicating whether a Property is editable by the Member.
/// </summary>
@@ -54,7 +67,7 @@ namespace Umbraco.Core.Models
{
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
return MemberTypePropertyTypes[propertyTypeAlias].Item1;
return MemberTypePropertyTypes[propertyTypeAlias].IsEditable;
}
return false;
@@ -69,7 +82,7 @@ namespace Umbraco.Core.Models
{
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
return MemberTypePropertyTypes[propertyTypeAlias].Item2;
return MemberTypePropertyTypes[propertyTypeAlias].IsVisible;
}
return false;
@@ -84,13 +97,11 @@ namespace Umbraco.Core.Models
{
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
var tuple = MemberTypePropertyTypes[propertyTypeAlias];
MemberTypePropertyTypes[propertyTypeAlias] = new Tuple<bool, bool, int>(value, tuple.Item2, tuple.Item3);
MemberTypePropertyTypes[propertyTypeAlias].IsEditable = value;
}
else
{
var propertyType = PropertyTypes.First(x => x.Alias.Equals(propertyTypeAlias));
var tuple = new Tuple<bool, bool, int>(value, false, propertyType.Id);
var tuple = new MemberTypePropertyProfileAccess(false, value);
MemberTypePropertyTypes.Add(propertyTypeAlias, tuple);
}
}
@@ -104,13 +115,11 @@ namespace Umbraco.Core.Models
{
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
var tuple = MemberTypePropertyTypes[propertyTypeAlias];
MemberTypePropertyTypes[propertyTypeAlias] = new Tuple<bool, bool, int>(tuple.Item1, value, tuple.Item3);
MemberTypePropertyTypes[propertyTypeAlias].IsVisible = value;
}
else
{
var propertyType = PropertyTypes.First(x => x.Alias.Equals(propertyTypeAlias));
var tuple = new Tuple<bool, bool, int>(false, value, propertyType.Id);
var tuple = new MemberTypePropertyProfileAccess(value, false);
MemberTypePropertyTypes.Add(propertyTypeAlias, tuple);
}
}
@@ -0,0 +1,17 @@
namespace Umbraco.Core.Models
{
/// <summary>
/// Used to track the property types that are visible/editable on member profiles
/// </summary>
internal class MemberTypePropertyProfileAccess
{
public MemberTypePropertyProfileAccess(bool isVisible, bool isEditable)
{
IsVisible = isVisible;
IsEditable = isEditable;
}
public bool IsVisible { get; set; }
public bool IsEditable { get; set; }
}
}
@@ -0,0 +1,24 @@
namespace Umbraco.Core.Models.Membership
{
/// <summary>
/// Represents a user -> entity permission
/// </summary>
public class EntityPermission
{
public EntityPermission(int userId, int entityId, string[] assignedPermissions)
{
UserId = userId;
EntityId = entityId;
AssignedPermissions = assignedPermissions;
}
public int UserId { get; private set; }
public int EntityId { get; private set; }
/// <summary>
/// The assigned permissions for the user/entity combo
/// </summary>
public string[] AssignedPermissions { get; private set; }
}
}
@@ -4,23 +4,42 @@ using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models.Membership
{
internal interface IMembershipUser : IMembershipUserId, IAggregateRoot
{
/*new object Id { get; set; }*/
public interface IMembershipUser : IAggregateRoot
{
object ProviderUserKey { get; set; }
string Username { get; set; }
string Email { get; set; }
string Password { get; set; }
/// <summary>
/// Gets or sets the raw password value
/// </summary>
string RawPasswordValue { get; set; }
string PasswordQuestion { get; set; }
string PasswordAnswer { get; set; }
/// <summary>
/// Gets or sets the raw password answer value
/// </summary>
string RawPasswordAnswerValue { get; set; }
string Comments { get; set; }
bool IsApproved { get; set; }
bool IsOnline { get; set; }
bool IsLockedOut { get; set; }
DateTime LastLoginDate { get; set; }
DateTime LastPasswordChangeDate { get; set; }
DateTime LastLockoutDate { get; set; }
object ProfileId { get; set; }
IEnumerable<object> Groups { get; set; }
/// <summary>
/// Gets or sets the number of failed password attempts.
/// This is the number of times the password was entered incorrectly upon login.
/// </summary>
/// <remarks>
/// Alias: umbracoFailedPasswordAttemptsPropertyTypeAlias
/// Part of the standard properties collection.
/// </remarks>
int FailedPasswordAttempts { get; set; }
//object ProfileId { get; set; }
//IEnumerable<object> Groups { get; set; }
}
}
@@ -1,7 +0,0 @@
namespace Umbraco.Core.Models.Membership
{
internal interface IMembershipUserId
{
object ProviderUserKey { get; set; }
}
}
@@ -3,6 +3,10 @@
/// <summary>
/// Defines the the Profile interface
/// </summary>
/// <remarks>
/// This interface is pretty useless but has been exposed publicly from 6.x so we're stuck with it. It would make more sense
/// if the Id was an int but since it's not people have to cast it to int all of the time!
/// </remarks>
public interface IProfile
{
object Id { get; set; }
+19 -10
View File
@@ -7,25 +7,34 @@ namespace Umbraco.Core.Models.Membership
/// Defines the interface for a <see cref="User"/>
/// </summary>
/// <remarks>Will be left internal until a proper Membership implementation is part of the roadmap</remarks>
internal interface IUser : IMembershipUser, IUserProfile
public interface IUser : IMembershipUser
{
new object Id { get; set; }
//string Name { get; set; }
string Name { get; set; }
int SessionTimeout { get; set; }
int StartContentId { get; set; }
int StartMediaId { get; set; }
string Language { get; set; }
bool DefaultToLiveEditing { get; set; }
/// <summary>
/// Gets/sets the user type for the user
/// </summary>
IUserType UserType { get; set; }
bool NoConsole { get; set; }
IUserType UserType { get; }
string DefaultPermissions { get; set; }
}
/// <summary>
/// The default permission set for the user
/// </summary>
/// <remarks>
/// Currently in umbraco each permission is a single char but with an Enumerable{string} collection this allows for flexible changes to this in the future
/// </remarks>
IEnumerable<string> DefaultPermissions { get; set; }
internal interface IUserProfile : IProfile
{
IEnumerable<string> AllowedSections { get; }
void RemoveAllowedSection(string sectionAlias);
void AddAllowedSection(string sectionAlias);
/// <summary>
/// Exposes the basic profile data
/// </summary>
IProfile ProfileData { get; }
}
}
@@ -1,13 +1,28 @@
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Models.Membership
{
internal interface IUserType : IAggregateRoot
public interface IUserType : IAggregateRoot
{
/// <summary>
/// The user type alias
/// </summary>
string Alias { get; set; }
/// <summary>
/// The user type name
/// </summary>
string Name { get; set; }
string Permissions { get; set; }
/// <summary>
/// The set of default permissions for the user type
/// </summary>
/// <remarks>
/// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
/// </remarks>
IEnumerable<string> Permissions { get; set; }
}
}
@@ -0,0 +1,13 @@
namespace Umbraco.Core.Models.Membership
{
/// <summary>
/// The types of members to count
/// </summary>
public enum MemberCountType
{
All,
Online,
LockedOut,
Approved
}
}
@@ -3,17 +3,17 @@ using System.Web.Security;
namespace Umbraco.Core.Models.Membership
{
internal static class MembershipExtensions
internal static class MembershipUserExtensions
{
internal static MembershipUser AsConcreteMembershipUser(this IMember member)
internal static UmbracoMembershipMember AsConcreteMembershipUser(this IMembershipUser member, string providerName)
{
var membershipMember = new UmbracoMembershipMember(member);
var membershipMember = new UmbracoMembershipMember(member, providerName);
return membershipMember;
}
internal static IMember AsIMember(this MembershipUser membershipMember)
internal static IMembershipUser AsIMember(this UmbracoMembershipMember membershipMember)
{
var member = membershipMember as UmbracoMembershipMember;
var member = membershipMember;
if (member != null)
{
return member.Member;
@@ -1,123 +0,0 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models.Membership
{
/// <summary>
/// Represents a Profile which is shared between Members and Users
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
internal class Profile : TracksChangesEntityBase, IProfile, IRememberBeingDirty
{
/// <summary>
/// Initializes a new instance of the <see cref="Profile"/> class.
/// </summary>
protected Profile()
{
ProviderUserKeyType = typeof(int);
}
public Profile(object id, string name)
{
ProviderUserKeyType = typeof(int);
Id = id;
Name = name;
}
private object _id;
private string _name;
private object _providerUserKey;
private Type _userTypeKey;
private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<Profile, object>(x => x.Id);
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<Profile, string>(x => x.Name);
private static readonly PropertyInfo ProviderUserKeySelector = ExpressionHelper.GetPropertyInfo<Profile, object>(x => x.ProviderUserKey);
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<Profile, Type>(x => x.ProviderUserKeyType);
[DataMember]
public virtual object Id
{
get
{
return _id;
}
set
{
SetPropertyValueAndDetectChanges(o =>
{
_id = value;
return _id;
}, _id, IdSelector);
}
}
[DataMember]
public virtual string Name
{
get
{
return _name;
}
set
{
SetPropertyValueAndDetectChanges(o =>
{
_name = value;
return _name;
}, _name, NameSelector);
}
}
[IgnoreDataMember]
public virtual object ProviderUserKey
{
get
{
return _providerUserKey;
}
set
{
SetPropertyValueAndDetectChanges(o =>
{
_providerUserKey = value;
return _id;
}, _providerUserKey, ProviderUserKeySelector);
}
}
/// <summary>
/// Gets or sets the type of the provider user key.
/// </summary>
/// <value>
/// The type of the provider user key.
/// </value>
[IgnoreDataMember]
internal Type ProviderUserKeyType
{
get
{
return _userTypeKey;
}
private set
{
SetPropertyValueAndDetectChanges(o =>
{
_userTypeKey = value;
return _userTypeKey;
}, _userTypeKey, UserTypeKeySelector);
}
}
/// <summary>
/// Sets the type of the provider user key.
/// </summary>
/// <param name="type">The type.</param>
internal void SetProviderUserKeyType(Type type)
{
ProviderUserKeyType = type;
}
}
}
@@ -1,66 +1,127 @@
using System.Web.Security;
using System;
using System.Web.Security;
namespace Umbraco.Core.Models.Membership
{
//TODO: THere's still a bunch of properties that don't exist in this use that need to be mapped somehow.
internal class UmbracoMembershipMember : MembershipUser
{
private readonly IMember _member;
private readonly IMembershipUser _member;
private readonly string _userName;
private readonly object _providerUserKey;
private readonly string _passwordQuestion;
private readonly bool _isLockedOut;
private readonly DateTime _lastLockoutDate;
private readonly DateTime _creationDate;
private DateTime _lastLoginDate;
private readonly DateTime _lastPasswordChangedDate;
private readonly string _providerName;
private string _email;
private string _comment;
private bool _isApproved;
private DateTime _lastActivityDate;
public UmbracoMembershipMember(IMember member)
//NOTE: We are only overriding the properties that matter, we don't override things like IsOnline since that is handled with the sub-class and the membership providers.
//NOTE: We are not calling the base constructor which will validate that a provider with the specified name exists which causes issues with unit tests. The ctor
// validation for that doesn't need to be there anyways (have checked the source).
public UmbracoMembershipMember(IMembershipUser member, string providerName)
{
_member = member;
//NOTE: We are copying the values here so that everything is consistent with how the underlying built-in ASP.Net membership user
// handles data! We don't want to do anything differently there but since we cannot use their ctor we'll need to handle this logic ourselves.
if (member.Username != null)
_userName = member.Username.Trim();
if (member.Email != null)
_email = member.Email.Trim();
if (member.PasswordQuestion != null)
_passwordQuestion = member.PasswordQuestion.Trim();
_providerName = providerName;
_providerUserKey = member.ProviderUserKey;
_comment = member.Comments;
_isApproved = member.IsApproved;
_isLockedOut = member.IsLockedOut;
_creationDate = member.CreateDate.ToUniversalTime();
_lastLoginDate = member.LastLoginDate.ToUniversalTime();
//TODO: We currently don't really have any place to store this data!!
_lastActivityDate = member.LastLoginDate.ToUniversalTime();
_lastPasswordChangedDate = member.LastPasswordChangeDate.ToUniversalTime();
_lastLockoutDate = member.LastLockoutDate.ToUniversalTime();
}
internal IMember Member
internal IMembershipUser Member
{
get { return _member; }
}
public override string Email
public override string UserName
{
get { return _member.Email; }
set { _member.Email = value; }
get { return _userName; }
}
public override object ProviderUserKey
{
get { return _member.Key; }
get { return _providerUserKey; }
}
public override System.DateTime CreationDate
public override string Email
{
get { return _member.CreateDate; }
get { return _email; }
set { _email = value; }
}
public override string UserName
public override string PasswordQuestion
{
get { return _member.Username; }
get { return _passwordQuestion; }
}
public override string Comment
{
get { return _member.Comments; }
set { _member.Comments = value; }
get { return _comment; }
set { _comment = value; }
}
public override bool IsApproved
{
get { return _member.IsApproved; }
set { _member.IsApproved = value; }
get { return _isApproved; }
set { _isApproved = value; }
}
public override bool IsLockedOut
{
get { return _member.IsLockedOut; }
get { return _isLockedOut; }
}
public override System.DateTime LastLoginDate
public override DateTime LastLockoutDate
{
get { return _member.LastLoginDate; }
set { _member.LastLoginDate = value; }
get { return _lastLockoutDate; }
}
public override DateTime CreationDate
{
get { return _creationDate; }
}
public override DateTime LastLoginDate
{
get { return _lastLoginDate; }
set { _lastLoginDate = value; }
}
public override DateTime LastActivityDate
{
get { return _lastActivityDate; }
set { _lastActivityDate = value; }
}
public override DateTime LastPasswordChangedDate
{
get { return _lastPasswordChangedDate; }
}
public override string ProviderName
{
get { return _providerName; }
}
}
}

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