Compare commits

..

228 Commits

Author SHA1 Message Date
Sebastiaan Janssen 92f609ff71 Merge pull request #1969 from umbraco/temp-U4-9974
U4-9974 EnablePropertyValueConverter does the opposite
2017-06-01 13:32:51 +02:00
Sebastiaan Janssen 7e6f7f8a2b Bumps version 2017-06-01 13:04:31 +02:00
Claus c5419e700b the legacy converter should not be associated to RelatedLinks2Alias and should only be enabled if EnablePropertyValueConverters is false, otherwise the other converter should be used. 2017-06-01 13:03:56 +02:00
Sebastiaan Janssen cb09094632 U4-9974 EnablePropertyValueConverter does the opposite 2017-06-01 10:57:15 +02:00
Sebastiaan Janssen 72404e68a0 Merge pull request #1968 from umbraco/temp-u4-9927
U4-9927 - fix migration
2017-05-31 16:36:42 +02:00
Sebastiaan Janssen 2c451c5cfe Remove debug tracing 2017-05-31 16:29:26 +02:00
Stephan af7f83f0f6 U4-9927 - fix migration 2017-05-31 15:49:15 +02:00
Shannon 5b3c2178a2 Revert "Merge pull request #1729 from marcemarc/marcemarc-U4-9480"
This reverts commit 145f789631, reversing
changes made to 78bc38fe1b.
2017-05-31 15:26:22 +02:00
Shannon Deminick 145f789631 Merge pull request #1729 from marcemarc/marcemarc-U4-9480
U4-9489 - dictonaryToQueryString only returns first dictionary item
2017-05-31 15:17:11 +02:00
Sebastiaan Janssen e27e95cb1a U4-9952 Can not save XSLT files in 7.6 2017-05-31 11:11:56 +02:00
Mikkel Holck Madsen cdbc3fa8cd Merge pull request #1967 from umbraco/temp-U4-9971
U4-9971 Special "square bracket" notation in Umbraco.Field not working
2017-05-31 10:55:17 +02:00
Sebastiaan Janssen 6feb7b222f U4-9971 Special "square bracket" notation in Umbraco.Field not working 2017-05-31 10:18:10 +02:00
mikkelhm b0a739b4ac Bump version to 7.6.2 2017-05-29 15:07:37 +02:00
Sebastiaan Janssen 728dee070f Merge pull request #1965 from umbraco/temp-U4-9894-2
U4-9894 UDI Pickers and all 'v2' property editors shouldn't observe t…
2017-05-29 14:27:18 +02:00
Claus 4a735770e2 Merge pull request #1961 from umbraco/temp-U4-9937
fixes: U4-9937 RTE Media Picker - Cannot add image to RTE after searching
2017-05-29 11:42:05 +02:00
Shannon d54b3a0cc3 U4-9894 UDI Pickers and all 'v2' property editors shouldn't observe the EnablePropertyValueConverters setting 2017-05-29 09:38:16 +02:00
Claus f962a3db20 Merge pull request #1953 from umbraco/temp-U4-9935
U4-9935 UmbracoHelper doesn't have querying methods for handling UDI
2017-05-29 09:34:29 +02:00
mikkelhm 39851d2475 Ignoring the StringEncodingTest2 as AppVeyors framework settings is doing weird things, that makes it fail 2017-05-26 13:31:29 +02:00
Mikkel Holck Madsen 28adbc17ef Merge pull request #1963 from umbraco/temp-deploy-324
deploy-324 - fix udi encoding
2017-05-26 13:14:29 +02:00
Shannon Deminick 4b9a13078e Merge pull request #1957 from umbraco/temp-U4-9940
U4-9940 Make it easy to get the integer Id of an item from it's Udi
2017-05-25 23:58:23 +10:00
Sebastiaan Janssen 17cce9a666 Make EntityService private 2017-05-25 15:40:26 +02:00
Sebastiaan Janssen 39da34e1c7 Attempt to force .NET 4.5 for tests 2017-05-25 13:14:56 +02:00
Sebastiaan Janssen 55dc927c8b Does this help get the StringEncodingTest2 to run? Doubt it. 2017-05-25 12:07:20 +02:00
Sebastiaan Janssen 6e3ff59dfb Adds GetIdForUdi to UmbracoHelper 2017-05-25 11:04:40 +02:00
Sebastiaan Janssen 08eab00627 Adds GetIdForUdi method to IEntityService 2017-05-25 10:48:28 +02:00
Sebastiaan Janssen c4fae9b272 Remove extension method 2017-05-25 10:47:15 +02:00
Stephan 51186bea24 deploy-324 - fix udi encoding 2017-05-24 11:20:01 +02:00
Shannon Deminick 5c5bacaab4 Merge pull request #1962 from bjarnef/dev-v7-U4-9571
Fix overwriting background repeat and position on legacy tree icons
2017-05-24 18:00:18 +10:00
Bjarne Fyrstenborg 5a4e6df99c Merge remote-tracking branch 'upstream/dev-v7' into dev-v7-U4-9571
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/less/tree.less
2017-05-24 09:40:14 +02:00
Bjarne Fyrstenborg 22f8a4c5dd Fix overwriting background repeat and position on legacy tree icons 2017-05-24 09:24:26 +02:00
Shannon Deminick aaf7ae0331 Merge pull request #1960 from umbraco/temp-u4-9936
U4-9936 - fix xml cache refresh in lb
2017-05-24 16:15:03 +10:00
Shannon Deminick 8459a058c6 Merge pull request #1956 from umbraco/temp-U4-9898
U4-9898 Reset password should unlock a locked account
2017-05-24 15:36:33 +10:00
Mads Rasmussen dc5089a9d6 fix svg preview 2017-05-23 14:38:52 +02:00
Mads Rasmussen 45a246d8b6 handle entity and full media objects in media grid 2017-05-23 14:38:34 +02:00
Mads Rasmussen 65bcd78872 add helper to get file extension 2017-05-23 14:37:51 +02:00
Mads Rasmussen a0fd7001e9 fixes image select in details overlay 2017-05-23 14:37:26 +02:00
Stephan 09ceb15d08 U4-9936 - fix xml cache refresh 2017-05-23 14:19:32 +02:00
Sebastiaan Janssen 25335446d0 Merge pull request #1959 from umbraco/temp-U4-9907
U4-9907 Translations Section : Getting "open datareader" Issue : Rela…
2017-05-23 14:11:23 +02:00
Stephan 63d8ef7560 U4-9936 - fix xml cache refresh in lb 2017-05-23 11:21:18 +02:00
Shannon 27428bf545 U4-9907 Translations Section : Getting "open datareader" Issue : Relates to (U4-9201) 2017-05-23 16:23:40 +10:00
Sebastiaan Janssen b9c418e458 Fix updating the actual lockout 2017-05-22 08:36:02 +02:00
Sebastiaan Janssen c843e634ba Merge pull request #1954 from aburok/dev-v7.6-ScheduledPublishing_RequestLogging
add log if request to ScheduledPublishController fails without exception
2017-05-21 13:40:29 +02:00
Sebastiaan Janssen 8eb0d254da U4-9940 Make it easy to get the integer Id of an item from it's Udi 2017-05-21 13:35:29 +02:00
Sebastiaan Janssen 70921e88f6 Okay, I give up.. disabling failing tests 2017-05-21 12:59:53 +02:00
Sebastiaan Janssen d9b71995e1 Try to make sure TestingDefaults is set to false else IsFileAllowedForUpload_WithWhitelist fails 2017-05-21 12:42:54 +02:00
Sebastiaan Janssen f517e750b9 Some more debugging to see if we are actually testing the correct config 2017-05-21 12:16:45 +02:00
Sebastiaan Janssen 07d91ce9ac Removes some code duplication by using parameterized test
Add some debugging to unit test to figure out what's wrong with it
2017-05-21 11:34:21 +02:00
dkoruba ac8ee92bb8 fix typo 2017-05-20 20:55:40 +02:00
Sebastiaan Janssen aee06c4574 U4-9898 Reset password should unlock a locked account 2017-05-20 14:33:33 +02:00
Sebastiaan Janssen d0f69907db Ignore one test for now that only seems to fail on build server 2017-05-20 13:08:48 +02:00
Sebastiaan Janssen 71db33f4cd Merge pull request #1955 from umbraco/dev-v7.6
Oops, wrong branch was targetted for U4-9908
2017-05-20 12:30:56 +02:00
Sebastiaan Janssen cec6322a84 Merge pull request #1948 from umbraco/temp-u4-9908
U4-9908 - fix scope-related issues
2017-05-20 12:21:40 +02:00
Sebastiaan Janssen eb85e8cd78 Merge branch 'AndyButland-u4-9558' into dev-v7 2017-05-20 12:13:47 +02:00
Sebastiaan Janssen cf7c0dffb0 Merge branch 'u4-9558' of https://github.com/AndyButland/Umbraco-CMS into AndyButland-u4-9558 2017-05-20 11:48:47 +02:00
Sebastiaan Janssen 78d91a353a Merge branch 'jamescoxhead-U4-9872' into dev-v7 2017-05-20 11:35:02 +02:00
Sebastiaan Janssen 22d778ed28 Adds UDI redirect for FollowExternalRedirect
Checks if the redirect property exists before trying to get it's value
Simplified conversions by asking for the property value by type
2017-05-20 11:34:03 +02:00
Sebastiaan Janssen a3a2b6499e Merge branch 'U4-9872' of https://github.com/jamescoxhead/Umbraco-CMS into jamescoxhead-U4-9872 2017-05-20 09:49:12 +02:00
dkoruba 65ed69cf06 add log if request to ScheduledPublishController fails without exception 2017-05-19 22:14:10 +02:00
Shannon Deminick c09cd95eb6 Merge pull request #1951 from umbraco/temp-U4-9919
U4-9919 Updated media files are deleted
2017-05-19 13:17:35 +10:00
Shannon Deminick 1d3490eb82 Merge pull request #1950 from umbraco/temp-U4-9646
U4-9646 RTE Link dialog should auto focus on url
2017-05-19 12:05:05 +10:00
Shannon b78c334589 Merge remote-tracking branch 'origin/master-v7' into dev-v7 2017-05-19 12:04:27 +10:00
Shannon Deminick b41de9b623 Merge pull request #1944 from umbraco/temp-U4-9848
U4-9848 Make sure NuGet version 3.4.4+ is installed in NuGet to prevent update errors
2017-05-19 12:02:11 +10:00
Shannon Deminick c51d29da52 Merge pull request #1947 from umbraco/temp-U4-9896
U4-9896 SqlCEconnection Type A originates from Version=4.0.0.0, Type B originates from 4.0.0.1
2017-05-19 11:54:40 +10:00
Shannon 54967e0150 U4-9935 UmbracoHelper doesn't have querying methods for handling UDI 2017-05-19 11:42:58 +10:00
Shannon 73e47402cb Fixes docs build 2017-05-19 10:20:00 +10:00
Claus 79844154fb U4-9919 Updated media files are deleted 2017-05-18 11:30:11 +02:00
Claus 067a1ba8e6 U4-9646 RTE Link dialog should auto focus on url 2017-05-18 10:02:46 +02:00
Warren Buckley 120cb964a5 Merge pull request #1949 from umbraco/temp-u4-9926
U4-9926 - fix partial view macro udis
2017-05-17 13:39:48 +01:00
Stephan 147a1daf6d U4-9926 - fix partial view macro udis 2017-05-17 12:09:28 +02:00
Shannon 9badb35c05 fix merge issue 2017-05-17 20:08:53 +10:00
Shannon 765decf3b1 Merge remote-tracking branch 'origin/dev-v7.6' into dev-v7
# Conflicts:
#	build/UmbracoVersion.txt
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Core/Services/MediaService.cs
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
#	src/Umbraco.Web/Trees/PartialViewMacrosTree.cs
#	src/Umbraco.Web/Trees/PartialViewsTree.cs
2017-05-17 20:00:29 +10:00
AndyButland eb35791003 Reverted media picker behaviour when selecting images to use just configured image types 2017-05-16 21:16:11 +01:00
mikkelhm 69775c369a Bump version to 7.5.14 2017-05-16 08:33:19 +02:00
mikkelhm 3f25d3637a Bump version to 7.5.14 2017-05-16 08:32:33 +02:00
Stephan 02136d3060 U4-9908 - fix scope-related issues 2017-05-16 08:09:11 +02:00
Sebastiaan Janssen 99d4b13bb0 Adds SQLCE assembly redirect on fresh installs and upgrades 2017-05-15 22:54:46 +02:00
Sebastiaan Janssen e7b007386a U4-9848 Make sure NuGet version 3.4.4+ is installed in NuGet to prevent update errors 2017-05-15 19:00:05 +02:00
Claus 5dc3e0a3fc Merge pull request #1880 from marcemarc/temp-U4-9765
debug logging when there is a distributed calls config issue
2017-05-15 10:28:26 +02:00
Claus d146df43e6 Merge pull request #1903 from HarveyWilliams/dev-v7
U4-9806 Media Picker media hover should show full title
2017-05-15 10:19:04 +02:00
James Coxhead 451826a329 Fixes umbracoInternalRedirectId property to work with UDI IDs 2017-05-14 21:52:45 +01:00
Mikkel Holck Madsen 080150baa3 Merge pull request #1924 from wanddy/dev-v7
Fix missing translation for some menu tree item
2017-05-10 21:18:58 +02:00
wanddy c6bc5ae6aa Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-05-10 22:37:47 +08:00
Shannon Deminick f84d3b435b Merge pull request #1898 from DaveLong/U4-9799
Fixed Serialization issue in ValidatePasswordResetCodeModel
2017-05-10 14:59:04 +10:00
Shannon Deminick 99855bce11 Adds AppVeyor build badge 2017-05-10 14:51:40 +10:00
Shannon d0b2f10a8c U4-9836 CreatorId on a media is overwritten on save 2017-05-10 14:32:09 +10:00
Shannon Deminick 70507501bd Merge pull request #1937 from AndyButland/u4-9836
U4-9836 - retains original media creator when media is updated
2017-05-10 14:31:34 +10:00
Shannon Deminick bbfd570b8a Merge pull request #1938 from suedeapple/U4-9886
U4 9886 - automaticly - > automatically (typo fix up)
2017-05-10 14:24:36 +10:00
AndyButland 4a593a0814 Reverted to empty whitelist for default. 2017-05-09 23:59:43 +02:00
AndyButland 3cc0df0273 Fixed media picker calculation of intersection of allowed whitelist and images list 2017-05-09 23:44:31 +02:00
AndyButland 712cd29fea Upload checks to utilise whitelist. Refactored check on white and black list to common extension method. 2017-05-09 23:29:30 +02:00
AndyButland 3d21448f89 Validated file uploads using white list if provided, before falling back to blacklist 2017-05-09 18:12:51 +02:00
suedeapple 7b4912b1e7 automaticly - > automatically 2017-05-09 16:47:36 +01:00
suedeapple 8c6362d947 automaticly - > automatically 2017-05-09 16:40:59 +01:00
AndyButland 01dd28fc61 Retains original media creator when media is updated 2017-05-09 16:01:06 +02:00
mikkelhm 67e2c911f7 Re adds the umbraco.presentation.targets for Umbraco.Web.UI as it handles default transormations for confg files 2017-05-09 00:26:40 +02:00
mikkelhm 36e60c774f Bump version to 7.6.1 2017-05-08 14:06:03 +02:00
mikkelhm 745252341f Merge branch 'dev-v7' into dev-v7.6
# Conflicts:
#	src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs
#	src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js
2017-05-08 13:58:08 +02:00
Mikkel Holck Madsen a2df4c5232 Merge pull request #1933 from umbraco/temp-U4-9864
U4-9864 Missing import and xss check in other PermissionEditor.aspx
2017-05-08 10:29:03 +02:00
Shannon Deminick d012d8e8b6 Merge pull request #1925 from SaDa1337/dev-v7
fixed console error on media picker
2017-05-08 17:11:28 +10:00
Mikkel Holck Madsen 9318da2883 Merge pull request #1931 from umbraco/temp-U4-9849-2
U4-9849 Query Builder not working in template editor. Always returns …
2017-05-08 09:05:29 +02:00
Shannon Deminick a08849f60a Merge pull request #1935 from jamescoxhead/U4-9869
Fix typo error in upgrade installer
2017-05-08 13:40:36 +10:00
Shannon Deminick 9792d8df25 Merge pull request #1930 from TomSteer/U4-9852
Change Context to be public on MigrationBase
2017-05-08 13:39:06 +10:00
Shannon Deminick 635cfe6b20 Merge pull request #1932 from dawoe/patch-1
Return empty string when e-mail is not filled
2017-05-08 13:37:48 +10:00
James Coxhead 9ccf7bdbab Fix typo error in upgrade installer
Changed "your" to "you're"
2017-05-07 16:22:54 +01:00
Sebastiaan Janssen 0c520f2b43 Merge branch 'dev-v7' into dev-v7.6
# Conflicts:
#	build/Build.bat
2017-05-05 16:19:54 +02:00
Sebastiaan Janssen 85d10014c2 Make new build work when there's spaces in the current path 2017-05-05 16:14:59 +02:00
Claus 3c4b3f44c7 U4-9864 Missing import and xss check in other PermissionEditor.aspx 2017-05-05 14:52:01 +02:00
Sebastiaan Janssen c6956b5e98 Merge branch 'dev-v7' into dev-v7.6
# Conflicts:
#	.gitignore
#	build/Build.bat
2017-05-05 14:30:08 +02:00
Sebastiaan Janssen fcf5ecc166 Uses vswhere to figure out where VS17 is installed (if needed)
Removes targets file that was almost unused, moved the relevant bits to the main csproj
Updates BuildBelle.bat to be completely independent of installed version of node & npm on the machine
2017-05-05 14:14:37 +02:00
Dave Woestenborghs c5c87ff50d Return empty string when e-mail is not filled
Fix for http://issues.umbraco.org/issue/U4-9862
2017-05-05 13:27:32 +02:00
Stephan eb949e2cbc Fix UdiString to escape paths 2017-05-05 12:46:20 +02:00
Claus 8a096cd826 Merge pull request #1794 from TheBekker/fix-U4-9038
[fix-U4-9038] get and set media start node for mediaPickerOverlay in …
2017-05-05 10:51:31 +02:00
Claus 3b236ba724 Merge pull request #1794 from TheBekker/fix-U4-9038
[fix-U4-9038] get and set media start node for mediaPickerOverlay in …
2017-05-05 10:47:52 +02:00
Claus e7eaf6959f U4-9849 Query Builder not working in template editor. Always returns Model.Content.Site().Children()
adding missing nullchecks in the endpoint action.
ensuring promise returns before setting init data - the unresolved promise was being used on the query model instead of the actual text string the promise returns - causing the endpoint to fail to bind the model.
2017-05-04 15:08:37 +02:00
Tom Steer 3e294e290b Change Context to be public on MigrationBase 2017-05-04 09:10:35 +01:00
Shannon Deminick 751dc8df23 Merge pull request #1926 from avatart0ph/dev-v7.6
fix Add basic xss prevention logic
2017-05-04 11:05:49 +10:00
Morten Christensen 91047182fa Merge pull request #1929 from umbraco/temp-U4-9704
U4-9704 Sorting UDI media picker items, makes it store Int's
2017-05-03 13:20:25 +02:00
Claus 1030fd5294 U4-9704 Sorting UDI media picker items, makes it store Int's 2017-05-03 10:21:00 +02:00
Denise Michelle del Bando be2eb3f555 fix Add basic xss prevention logic
missing import on CleanForXss
2017-05-02 23:16:32 -04:00
Maciej Sadowski 0eafa14246 fixed console error on media picker 2017-05-02 15:36:39 +02:00
wanddy b807b84466 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-05-02 14:23:36 +08:00
wanddy ab551b2c96 Fix some menu tree header won't be translated.
This may be caused by the explicit definition of tree node name.

Signed-off-by: wanddy <wanddy@163.com>
2017-05-02 14:20:44 +08:00
wanddy 1520fa77d5 Add missing translation item for en.xml and zh.xml
Signed-off-by: wanddy <wanddy@163.com>
2017-05-02 14:12:58 +08:00
Shannon c1853e8c51 bumps version to 7.6.0 rtm 2017-05-02 13:42:20 +10:00
Shannon 31c965ae42 Merge remote-tracking branch 'origin/dev-v7' into dev-v7.6 2017-05-02 13:41:03 +10:00
Shannon Deminick d91fc6ce60 Merge pull request #1887 from umbraco/temp-U4-9775
U4-9775 AlreadyClosedException is thrown when retrieving media if the…
2017-05-02 13:40:28 +10:00
Shannon d5124e9739 Ensures that an UmbracoContext exist before emitting the cache handler events 2017-05-01 21:10:22 +10:00
Shannon d9b507c947 bumps version to RC4 so we can build new dependencies against forms/deploy 2017-04-30 23:26:04 +10:00
Shannon d3fcdfb176 updates nuget semver ref in nuspec 2017-04-30 23:24:26 +10:00
Shannon 2479c5a272 updates other nuget refs that shouldnt be there 2017-04-30 23:21:19 +10:00
Shannon fee071db22 Merge branch 'dev-v7.6' of https://github.com/umbraco/Umbraco-CMS into dev-v7.6 2017-04-30 23:20:16 +10:00
Shannon 004e00599d Fixing nuget package issues , semver 2 is only for 452+ which we dont have, we shouldnt be using it and it adds more dependencies that we don't need right now 2017-04-30 23:19:45 +10:00
Morten Christensen 2e2e8b43b0 Merge pull request #1917 from Frozire/patch-1
Edit DA with minor spelling and compound word changes
2017-04-30 14:05:14 +02:00
Morten Christensen e77c5f8667 Keep the Concierge Product name 2017-04-30 14:04:00 +02:00
Shannon Deminick 3509a2c40f Merge pull request #1908 from umbraco/temp-scope-events-stale-entities
POC to normalize all event entities when we track events so that all …
2017-04-30 19:28:19 +10:00
Shannon 378d0f7939 chagnes test params to be slightly less hacky 2017-04-30 19:21:13 +10:00
Shannon d64fa7f92d Fixes tests, ensures we null check when generating hashes for items in a collection 2017-04-30 19:14:36 +10:00
Stephan ea14170272 minor cleanup 2017-04-30 10:14:48 +02:00
Shannon 73209d7e2c Merge branch 'dev-v7' into dev-v7.6 2017-04-30 17:13:14 +10:00
Shannon Deminick cf8ead62ac Merge pull request #1904 from jwoods1/patch-2
Fixed issue on line 216
2017-04-30 17:11:44 +10:00
Shannon Deminick 8461aea7d8 Merge pull request #1907 from wanddy/dev-v7
Improve Chinese translation.
2017-04-30 17:10:58 +10:00
Shannon Deminick 034de1651b Merge pull request #1910 from abryukhov/patch-9
ru.xml - Missing newest area & key from en.xml
2017-04-30 17:09:30 +10:00
Shannon Deminick dcb8aa7e56 Merge pull request #1909 from abryukhov/patch-8
en_us.xml - Missing newest area & key from en.xml
2017-04-30 17:09:15 +10:00
Shannon Deminick e8a52a95da Merge pull request #1914 from dawoe/patch-1
Added dutch translation for usernameHint
2017-04-30 17:08:42 +10:00
Shannon Deminick 42c99e0f07 Merge pull request #1916 from stelim/patch-1
Adding login hint to German language file
2017-04-30 17:08:29 +10:00
Shannon Deminick a31b368b60 Merge pull request #1919 from NathalieLarsson/patch-1
Adding login hint to Swedish language file
2017-04-30 17:05:29 +10:00
Shannon Deminick 77f6d28a74 Merge pull request #1920 from camaya/patch-1
Add Spanish translation for usernameHint
2017-04-30 17:04:56 +10:00
Shannon Deminick 0b8d3ef214 Merge pull request #1921 from mikecp/patch-1
Adding login hint to French language file
2017-04-30 17:04:44 +10:00
Shannon Deminick a4f83f9c00 Merge pull request #1922 from abryukhov/patch-10
Adding 'usernameHint' key to ru.xml lang file
2017-04-30 17:04:30 +10:00
Shannon Deminick 85467976ad Merge pull request #1913 from umbraco/temp-U4-9824-v76
Change username to email in login dialog
2017-04-30 17:04:16 +10:00
Alexander Bryukhov d7e93fe466 Adding 'usernameHint' key to ru.xml lang file 2017-04-30 11:56:47 +07:00
Sebastiaan Janssen 660f048b4f U4-9812 FailedLoginAttempts should be reset to 0 after a successfull login attempt
(cherry picked from commit 3242b31a8a)
2017-04-29 10:22:57 +02:00
Sebastiaan Janssen 9fa76a0133 Merge pull request #1911 from umbraco/temp-U4-9812
U4-9812 FailedLoginAttempts should be reset to 0 after a successfull …
2017-04-29 10:19:26 +02:00
Michael Latouche 444c444f0e Adding login hint to French language file 2017-04-29 00:03:57 +02:00
Cristhian Amaya 383bbbe7e0 Add Spanish translation for usernameHint 2017-04-28 15:19:27 -05:00
Stephan 72eddca3c6 Merge branch 'dev-v7.6' into temp-scope-events-stale-entities 2017-04-28 19:19:36 +02:00
Nicklas Kevin Frank 7c2ddde311 Fixed typo in Dokumenttype 2017-04-28 17:24:43 +02:00
Nathalie Festin c6229e4fcb Adding login hint to Swedish language file
Added usernamehint to placeholders
2017-04-28 15:44:46 +02:00
Nicklas Kevin Frank fbac0aba8b Update da.xml with translation for concierge 2017-04-28 14:56:57 +02:00
Nicklas Kevin Frank f01511c592 Edit DA with minor spelling and compound word changes 2017-04-28 14:48:32 +02:00
Stefan Limbacher 187354f0bd Adding login hint to German language file 2017-04-28 14:29:13 +02:00
Dave Woestenborghs 2f540b1bfa Translated the usually part 2017-04-28 14:25:21 +02:00
Dave Woestenborghs b1f104d1de Changed it to be more consisten
Changed to be more consistent with other dutch translations
2017-04-28 14:24:10 +02:00
Dave Woestenborghs ba5fcad09a Added dutch translation for usernameHint 2017-04-28 14:17:51 +02:00
Niels Hartvig d553eb2978 Change it back to username and then with a hint for email (for backwards compat.) 2017-04-28 13:57:29 +02:00
Niels Hartvig d1e6c0e835 Change username to email in login dialog 2017-04-28 13:37:19 +02:00
Stephan 244977dc95 packages - trace errors 2017-04-28 13:34:35 +02:00
Sebastiaan Janssen 3242b31a8a U4-9812 FailedLoginAttempts should be reset to 0 after a successfull login attempt 2017-04-28 12:46:58 +02:00
Stephan efc3261163 scope - dont break 2017-04-28 11:43:48 +02:00
Stephan 8c6aa9875d scope - dont rename 2017-04-28 11:26:41 +02:00
Stephan f89ce1ff26 scope - cleanup 2017-04-28 10:58:57 +02:00
Shannon 1274fbaefd Fixes up the equality members for the event args types to include Gethash code and sequence equal checking, this is done by a base class used by event args that deal with collections. 2017-04-28 18:14:50 +10:00
Shannon 8140dfdc04 ads notes 2017-04-28 16:57:13 +10:00
Shannon a69eba61c8 Fixes detecting enumerable and ensures that the event is added to the result if we can't cast to IEntity 2017-04-28 14:54:08 +10:00
Alexander Bryukhov 46078a841c Missing newest area & key from en.xml 2017-04-28 11:43:50 +07:00
Alexander Bryukhov 0eb5e5f6e4 Missing newest area & key from en.xml 2017-04-28 11:41:20 +07:00
Shannon ec9020f63e Fixes mappings 2017-04-28 13:34:32 +10:00
Shannon 0b61685fc8 Adds ability to supersede events so we don't have an issue of saved event being raised for an entity after it's been deleted. 2017-04-28 13:26:56 +10:00
Shannon 3779b3c782 Updates base entities to contain a DeletedDate if the entity gets deleted 2017-04-28 11:15:19 +10:00
Shannon 5b0e824301 Merge branch 'dev-v7.6' into temp-scope-events-stale-entities 2017-04-28 10:32:01 +10:00
Shannon d24b0aa9eb oops undeletes a couple files that are still needed for the custom package ascx page 2017-04-28 10:30:47 +10:00
Shannon 9cd7e09986 POC to normalize all event entities when we track events so that all args contain the latest (non stale) entity 2017-04-28 10:04:43 +10:00
Shannon 9f505a7976 bumps to rc3 version 2017-04-28 08:27:31 +10:00
Jason Woods f737004544 Removed space before svalue 2017-04-27 16:13:41 -06:00
Jason Woods 850e354b11 wrapped all values in double quotes
Wrapped image src and crop values in double quotes to keep consistent across all saves and updates.
2017-04-27 16:03:45 -06:00
Shannon 1b27114014 Merge branch 'temp-CON-1267' into dev-v7.6 2017-04-28 07:53:16 +10:00
Shannon Deminick d8b235ad62 Merge pull request #1906 from umbraco/temp-CON-1267
CON-1267 Update Our to not offer v6 to people on < 7.6.0
2017-04-28 07:52:19 +10:00
Shannon 56581478c8 Merge remote-tracking branch 'origin/dev-v7' into temp-CON-1267 2017-04-28 07:48:04 +10:00
Shannon 2be330d237 adds notes, changes to protected 2017-04-28 07:45:01 +10:00
Shannon 4381a700ba Updates UmbracoVirtualNodeRouteHandler to have a new protected GetUmbracoContext method used to get the umb context used in the rest of the code 2017-04-28 07:38:03 +10:00
Shannon 99821954f1 adds notes 2017-04-28 07:31:44 +10:00
Shannon Deminick 10a15be8ad Merge pull request #1901 from tompipe/U4-9384-StaleVariableFix
Quick/simple fix for the stale variable
2017-04-28 07:28:00 +10:00
wanddy 0a2830aece Improve Chinese translation.
Signed-off-by: wanddy <wanddy@163.com>
2017-04-27 22:59:17 +08:00
Stephan d1094eea7a Merge pull request #1905 from umbraco/temp-tasks
Publicize more IBackgroundTask plumbing
2017-04-27 14:46:33 +02:00
Shannon c629a50f39 Fixes entity service and figuring out which GUID to go with which object type 2017-04-27 13:29:31 +10:00
Shannon 430f906ae6 Merge remote-tracking branch 'origin/dev-v7.6' into temp-CON-1267 2017-04-27 13:28:34 +10:00
Shannon 736798c769 Merge remote-tracking branch 'origin/dev-v7' into temp-CON-1267
# Conflicts:
#	src/Umbraco.Core/Exceptions/ConnectionException.cs
#	src/Umbraco.Core/Services/PackagingService.cs
#	src/Umbraco.Web/Editors/PackageInstallController.cs
2017-04-27 13:27:23 +10:00
Shannon e913034d93 Changes PackagingService to not have a different base class since it was not needed 2017-04-27 13:21:56 +10:00
Shannon bed5f8a03b backports updates from 7.6 so that the packages.umbraco.org endpoint is not used for fetching package files any longer 2017-04-27 13:21:07 +10:00
Stephan 0291ab615d Fix shadow wrapper cleanup 2017-04-26 17:38:06 +02:00
Stephan ceeea7827e Fix shadow wrapper cleanup 2017-04-26 14:44:48 +02:00
Shannon 756b4d24c0 Updates endpoint to include hidden package files 2017-04-26 22:10:34 +10:00
Stephan ffe3fc9257 deploy-293 - fix normalization 2017-04-26 13:25:54 +02:00
Shannon 26bd3c7c0b removes unneeded closing of stream since it's disposed 2017-04-26 19:42:58 +10:00
Shannon 944b3dcaac New method for IPackagingService to fetch a package from the repo, removes usages of the old repo endpoint, removes ability to push a package from the back office to Our since that would require a different endpoint. 2017-04-26 19:02:36 +10:00
Stephan ba489afe9a Publicize more IBackgroundTask plumbing 2017-04-26 09:07:48 +02:00
Shannon 968d52e490 Removes old packager files that should absolutely never be used 2017-04-26 15:46:07 +10:00
Shannon ebbe9f6ed0 Removes old packager files that should absolutely never be used 2017-04-26 15:45:37 +10:00
Shannon ba32636fe7 Merge remote-tracking branch 'origin/dev-v7' into temp-CON-1267 2017-04-26 14:18:27 +10:00
Shannon a6f9d14a1b Merge remote-tracking branch 'origin/dev-v7.6' into temp-CON-1267 2017-04-26 14:18:05 +10:00
Shannon 7cd385dd6b disables ssl by default 2017-04-26 14:17:24 +10:00
Shannon 5d4a97591a Cherry picks changes for package fetching for Our to use the new endpoint and passes in the current version 2017-04-26 14:08:37 +10:00
Shannon bfb81f6362 Allows for the umb pckage repo rest api endpoint to be configurable - for testing 2017-04-26 14:04:47 +10:00
Jason Woods 23816665f3 Fixed issue on line 216
Found that when uploading media from the folder browser caused an issue of invalid JSON object being stored in the database.  Added quotes around the property values.
2017-04-25 08:21:02 -06:00
Warren Buckley ca3dc030bc Merge pull request #1893 from umbraco/temp-u4-9764
U4-9764 - add FirstChild with predicate extension
2017-04-25 11:37:37 +01:00
Harvey Williams 81354cea3c U4-9806 Media Picker media hover should show full title
Added title to all media items in the media picker rather than just SVG and normal images.

Solving an issue where whole titles could not be visible if the title was too long.
2017-04-24 16:29:35 +01:00
Tom Pipe 67e3ec2ae0 Quick/simple fix for the stale variable
The umbracoContext variable can hold a null reference to UmbracoContext.Current. 

If a request containing a file extension is passed through an UmbracoVirtualNodeRouteHandler, the UmbracoContext will be null, because a context is never created for urls containing extensions due to https://github.com/umbraco/Umbraco-CMS/blob/5397f2c53acbdeb0805e1fe39fda938f571d295a/src/Umbraco.Core/UriExtensions.cs#L143

A call can be made to EnsureContext in the overridden FindContent method, but the fresh context would never get picked up, instead the variable always contains a null reference, and an exception is then thrown on line 23
2017-04-24 13:23:12 +01:00
Shannon d295174e53 Updates JS to include the current umbraco version when requesting a package's details, updates the c# to use a new endpoint on OUR to ensure that the correct file is downloaded based on the umb version passed in. 2017-04-24 21:31:35 +10:00
Dave Long b88e714050 Fixed Serialization issue in Password Reset Validate Model 2017-04-21 08:33:21 +02:00
Shannon Deminick da8c46e426 Merge pull request #1859 from alexxn/dev-v7
Add basic xss prevention logic
2017-04-21 13:05:40 +10:00
Stephan 5880df3859 U4-9764 - add FirstChild with predicate extension 2017-04-19 18:56:12 +02:00
Shannon 13ccd86192 Adds another check for not being able to read the index 2017-04-18 12:35:21 +10:00
Shannon 336266c0eb U4-9775 AlreadyClosedException is thrown when retrieving media if the app domain is currently in a shutdown state and the site is under heavy load 2017-04-18 12:32:44 +10:00
Marc Goodson 58f9ff4b79 Add some debug logging when there is a distributed calls configuration issue 2017-04-11 20:37:59 +01:00
Alex Novgorodov de9739118e Add basic xss prevention logic 2017-04-04 18:11:48 +03:00
TheBekker ab14b65078 [fix-U4-9038] get and set media start node for mediaPickerOverlay in grid 2017-03-13 22:54:20 +01:00
Marc Goodson 78bc38fe1b getUserLog and getLog don't have an id parameter
these methods blow up when the api doesn't return because they referenced an id variable that does not exist
2017-02-04 18:40:28 +00:00
Marc Goodson edb0a934a1 Fixes U4-9480
Allow more than one item from the dictionary object to be returned on the querystring
2017-02-04 18:35:47 +00:00
207 changed files with 3505 additions and 4404 deletions
+3 -1
View File
@@ -142,4 +142,6 @@ build/ui-docs.zip
build/csharp-docs.zip
build/msbuild.log
.vs/
src/packages/
src/packages/
build/tools/
src/PrecompiledWeb/*
+2
View File
@@ -1,3 +1,5 @@
[![Build status](https://ci.appveyor.com/api/projects/status/ikpgqxiw9v8opltv/branch/dev-v7?svg=true)](https://ci.appveyor.com/project/Umbraco/umbraco-cms-hs8dx/branch/dev-v7)
Umbraco CMS
===========
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 390,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
+46 -3
View File
@@ -113,18 +113,61 @@ REM This is necessary because SETLOCAL is on in InstallGit.cmd so that one might
REM but the path setting is lost due to SETLOCAL
SET PATH="C:\Program Files (x86)\Git\cmd";"C:\Program Files\Git\cmd";%PATH%
SET toolsFolder=%CD%\tools\
IF NOT EXIST "%toolsFolder%" (
MD tools
)
SET nuGetExecutable=%CD%\tools\nuget.exe
IF NOT EXIST "%nuGetExecutable%" (
ECHO Getting NuGet so we can fetch some tools
ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable%
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')"
)
:: We need 7za.exe for BuildBelle.bat
IF NOT EXIST "%toolsFolder%7za.exe" (
ECHO 7zip not found - fetching now
"%nuGetExecutable%" install 7-Zip.CommandLine -OutputDirectory tools -Verbosity quiet
)
:: We need vswhere.exe for VS2017+
IF NOT EXIST "%toolsFolder%vswhere.exe" (
ECHO vswhere not found - fetching now
"%nuGetExecutable%" install vswhere -OutputDirectory tools -Verbosity quiet
)
:: Put 7za.exe and vswhere.exe in a predictable path (not version specific)
FOR /f "delims=" %%A in ('dir "%toolsFolder%7-Zip.CommandLine.*" /b') DO SET "sevenZipExePath=%toolsFolder%%%A\"
MOVE "%sevenZipExePath%tools\7za.exe" "%toolsFolder%7za.exe"
FOR /f "delims=" %%A in ('dir "%toolsFolder%vswhere.*" /b') DO SET "vswhereExePath=%toolsFolder%%%A\"
MOVE "%vswhereExePath%tools\vswhere.exe" "%toolsFolder%vswhere.exe"
ECHO.
ECHO Making sure we have a web.config
IF NOT EXIST "%CD%\..\src\Umbraco.Web.UI\web.config" COPY "%CD%\..\src\Umbraco.Web.UI\web.Template.config" "%CD%\..\src\Umbraco.Web.UI\web.config"
for /f "usebackq tokens=1* delims=: " %%i in (`"%CD%\tools\vswhere.exe" -latest -requires Microsoft.Component.MSBuild`) do (
if /i "%%i"=="installationPath" set InstallDir=%%j
)
SET VSWherePath="%InstallDir%\MSBuild"
ECHO.
ECHO Visual Studio is installed in: %InstallDir%
SET MSBUILDPATH=C:\Program Files (x86)\MSBuild\14.0\Bin
SET MSBUILD="%MSBUILDPATH%\MsBuild.exe"
ECHO.
ECHO Reporting NuGet version
"%CD%\..\src\.nuget\NuGet.exe" help | findstr "^NuGet Version:"
"%nuGetExecutable%" help | findstr "^NuGet Version:"
ECHO.
ECHO Restoring NuGet packages
ECHO Into %nuGetFolder%
"%CD%\..\src\.nuget\NuGet.exe" restore "%CD%\..\src\umbraco.sln" -Verbosity Quiet -NonInteractive -PackagesDirectory "%nuGetFolder%"
"%nuGetExecutable%" restore "%CD%\..\src\umbraco.sln" -Verbosity Quiet -NonInteractive -PackagesDirectory "%nuGetFolder%"
IF ERRORLEVEL 1 GOTO :error
ECHO.
@@ -134,7 +177,7 @@ ECHO This takes a few minutes and logging is set to report warnings
ECHO and errors only so it might seems like nothing is happening for a while.
ECHO You can check the msbuild.log file for progress.
ECHO.
%MSBUILD% "Build.proj" /p:BUILD_RELEASE=%RELEASE% /p:BUILD_COMMENT=%COMMENT% /p:NugetPackagesDirectory="%nuGetFolder%" /consoleloggerparameters:Summary;ErrorsOnly /fileLogger
%MSBUILD% "Build.proj" /p:BUILD_RELEASE=%RELEASE% /p:BUILD_COMMENT=%COMMENT% /p:NugetPackagesDirectory="%nuGetFolder%" /p:VSWherePath=%VSWherePath% /consoleloggerparameters:Summary;ErrorsOnly /fileLogger
IF ERRORLEVEL 1 GOTO error
ECHO.
+48 -22
View File
@@ -1,33 +1,59 @@
@ECHO OFF
SETLOCAL
:: SETLOCAL is on, so changes to the path not persist to the actual user's path
SET release=%1
ECHO Installing Npm NuGet Package
SET nuGetFolder=%CD%\..\src\packages\
ECHO Configured packages folder: %nuGetFolder%
SET toolsFolder=%CD%\tools\
ECHO Current folder: %CD%
%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder% -Verbosity quiet
SET nodeFileName=node-v6.9.1-win-x86.7z
SET nodeExtractFolder=%toolsFolder%node.js.691
for /f "delims=" %%A in ('dir %nuGetFolder%node.js.* /b') do set "nodePath=%nuGetFolder%%%A\"
for /f "delims=" %%A in ('dir %nuGetFolder%npm.js.* /b') do set "npmPath=%nuGetFolder%%%A\tools\"
IF NOT EXIST "%nodeExtractFolder%" (
ECHO Downloading http://nodejs.org/dist/v6.9.1/%nodeFileName% to %toolsFolder%%nodeFileName%
powershell -Command "(New-Object Net.WebClient).DownloadFile('http://nodejs.org/dist/v6.9.1/%nodeFileName%', '%toolsFolder%%nodeFileName%')"
ECHO Extracting %nodeFileName% to %nodeExtractFolder%
"%toolsFolder%\7za.exe" x "%toolsFolder%\%nodeFileName%" -o"%nodeExtractFolder%" -aos > nul
)
FOR /f "delims=" %%A in ('dir "%nodeExtractFolder%\node*" /b') DO SET "nodePath=%nodeExtractFolder%\%%A"
ECHO Adding Npm and Node to path
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
PATH=%npmPath%;%nodePath%;%PATH%
SET buildFolder=%CD%
SET nuGetExecutable=%CD%\tools\nuget.exe
IF NOT EXIST "%nuGetExecutable%" (
ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable%
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')"
)
ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
CD %CD%\..\src\Umbraco.Web.UI.Client\
SET drive=%CD:~0,2%
SET nuGetFolder=%drive%\packages\
FOR /f "delims=" %%A in ('dir "%nuGetFolder%npm.*" /b') DO SET "npmPath=%nuGetFolder%%%A\"
ECHO Do npm install and the grunt build of Belle
call npm cache clean --quiet
call npm install --quiet
call npm install -g grunt-cli --quiet
call npm install -g bower --quiet
call grunt build --buildversion=%release%
IF [%npmPath%] == [] GOTO :installnpm
IF NOT [%npmPath%] == [] GOTO :build
ECHO Move back to the build folder
CD %buildFolder%
:installnpm
ECHO Downloading npm
ECHO Configured packages folder: %nuGetFolder%
ECHO Installing Npm NuGet Package
"%nuGetExecutable%" install Npm -OutputDirectory %nuGetFolder% -Verbosity detailed
REM Ensures that we look for the just downloaded NPM, not whatever the user has installed on their machine
FOR /f "delims=" %%A in ('dir %nuGetFolder%npm.* /b') DO SET "npmPath=%nuGetFolder%%%A\"
GOTO :build
:build
ECHO Adding Npm and Node to path
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
PATH="%npmPath%";"%nodePath%";%PATH%
SET buildFolder=%CD%
ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
CD %CD%\..\src\Umbraco.Web.UI.Client\
ECHO Do npm install and the grunt build of Belle
call npm cache clean --quiet
call npm install --quiet
call npm install -g grunt-cli --quiet
call npm install -g bower --quiet
call grunt build --buildversion=%release%
ECHO Move back to the build folder
CD "%buildFolder%"
+14
View File
@@ -57,6 +57,20 @@ $IndexPath = "../src/umbraco.web.ui.client/docs/api/index.html"
# Build the solution in debug mode
$SolutionPath = Join-Path -Path $SolutionRoot -ChildPath "umbraco.sln"
# Go get nuget.exe if we don't hae it
$NuGet = "$ToolsRoot\nuget.exe"
$FileExists = Test-Path $NuGet
If ($FileExists -eq $False) {
Write-Host "Retrieving nuget.exe..."
$SourceNugetExe = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
Invoke-WebRequest $SourceNugetExe -OutFile $NuGet
}
#restore nuget packages
Write-Host "Restoring nuget packages..."
& $NuGet restore $SolutionPath
& $MSBuild "$SolutionPath" /p:Configuration=Debug /maxcpucount /t:Clean
if (-not $?)
{
+3 -3
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<metadata minClientVersion="3.4.4">
<id>UmbracoCms.Core</id>
<version>7.0.0</version>
<title>Umbraco Cms Core Binaries</title>
@@ -37,8 +37,8 @@
<dependency id="Examine" version="[0.1.82, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.5.3, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.8.3, 5.0.0)" />
<dependency id="semver" version="[2.0.4, 3.0.0)" />
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
<dependency id="semver" version="[1.1.2, 3.0.0)" />
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.7.0, 5.0.0)" />
</dependencies>
+2 -2
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="2.8">
<metadata minClientVersion="3.4.4">
<id>UmbracoCms</id>
<version>7.0.0</version>
<title>Umbraco Cms</title>
@@ -19,7 +19,7 @@
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.7, 4.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
</dependencies>
</metadata>
<files>
@@ -332,6 +332,7 @@
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http.Formatting')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.CodeAnalysis.CSharp')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='log4net')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Data.SqlServerCe')" xdt:Transform="Remove" />
</assemblyBinding>
</runtime>
@@ -389,6 +390,10 @@
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0"/>
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
+1 -2
View File
@@ -1,3 +1,2 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.6.0
RC2
7.6.3
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.6.0")]
[assembly: AssemblyInformationalVersion("7.6.0-RC2")]
[assembly: AssemblyFileVersion("7.6.3")]
[assembly: AssemblyInformationalVersion("7.6.3")]
@@ -139,6 +139,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
internal CommaDelimitedConfigurationElement DisallowedUploadFiles
{
get { return GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"}); }
}
[ConfigurationProperty("allowedUploadFiles")]
internal CommaDelimitedConfigurationElement AllowedUploadFiles
{
get { return GetOptionalDelimitedElement("allowedUploadFiles", new string[0]); }
}
[ConfigurationProperty("cloneXmlContent")]
@@ -307,6 +313,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
IEnumerable<string> IContentSection.DisallowedUploadFiles
{
get { return DisallowedUploadFiles; }
}
IEnumerable<string> IContentSection.AllowedUploadFiles
{
get { return AllowedUploadFiles; }
}
bool IContentSection.CloneXmlContent
@@ -0,0 +1,19 @@
using System.Linq;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public static class ContentSectionExtensions
{
/// <summary>
/// Determines if file extension is allowed for upload based on (optional) white list and black list
/// held in settings.
/// Allow upload if extension is whitelisted OR if there is no whitelist and extension is NOT blacklisted.
/// </summary>
public static bool IsFileAllowedForUpload(this IContentSection contentSection, string extension)
{
return contentSection.AllowedUploadFiles.Any(x => x.InvariantEquals(extension)) ||
(contentSection.AllowedUploadFiles.Any() == false &&
contentSection.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false);
}
}
}
@@ -52,7 +52,9 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
MacroErrorBehaviour MacroErrorBehaviour { get; }
IEnumerable<string> DisallowedUploadFiles { get; }
IEnumerable<string> DisallowedUploadFiles { get; }
IEnumerable<string> AllowedUploadFiles { get; }
bool CloneXmlContent { get; }
@@ -8,6 +8,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
Guid Id { get; }
string RepositoryUrl { get; }
string WebServiceUrl { get; }
bool HasCustomWebServiceUrl { get; }
bool HasCustomWebServiceUrl { get; }
string RestApiUrl { get; }
}
}
@@ -0,0 +1,19 @@
using System;
using System.Linq;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public static class RepositoryConfigExtensions
{
//Our package repo
private static readonly Guid RepoGuid = new Guid("65194810-1f85-11dd-bd0b-0800200c9a66");
public static IRepository GetDefault(this IRepositoriesSection repos)
{
var found = repos.Repositories.FirstOrDefault(x => x.Id == RepoGuid);
if (found == null)
throw new InvalidOperationException("No default package repository found with id " + RepoGuid);
return found;
}
}
}
@@ -38,9 +38,16 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get
{
var prop = Properties["webserviceurl"];
var repoUrl = this[prop] as ConfigurationElement;
return (repoUrl != null && repoUrl.ElementInformation.IsPresent);
return (string) prop.DefaultValue != (string) this[prop];
}
}
[ConfigurationProperty("restapiurl", DefaultValue = "https://our.umbraco.org/webapi/packages/v1")]
public string RestApiUrl
{
get { return (string)base["restapiurl"]; }
set { base["restapiurl"] = value; }
}
}
}
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.6.0");
private static readonly Version Version = new Version("7.6.3");
/// <summary>
/// Gets the current version of Umbraco.
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
/// Gets the version comment (like beta or RC).
/// </summary>
/// <value>The version comment.</value>
public static string CurrentComment { get { return "RC2"; } }
public static string CurrentComment { get { return ""; } }
// Get the version of the umbraco.dll by looking at a class in that dll
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
@@ -1,85 +1,177 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Events
{
/// <summary>
/// Event args for a strongly typed object that can support cancellation
/// </summary>
/// <typeparam name="T"></typeparam>
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
public class CancellableObjectEventArgs<T> : CancellableEventArgs, IEquatable<CancellableObjectEventArgs<T>>
{
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
/// <summary>
/// Used as a base class for the generic type CancellableObjectEventArgs{T} so that we can get direct 'object' access to the underlying EventObject
/// </summary>
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
public abstract class CancellableObjectEventArgs : CancellableEventArgs
{
protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
: base(canCancel, messages, additionalData)
{
{
EventObject = eventObject;
}
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages)
protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages eventMessages)
: base(canCancel, eventMessages)
{
EventObject = eventObject;
}
public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages)
protected CancellableObjectEventArgs(object eventObject, EventMessages eventMessages)
: this(eventObject, true, eventMessages)
{
}
protected CancellableObjectEventArgs(object eventObject, bool canCancel)
: base(canCancel)
{
EventObject = eventObject;
}
protected CancellableObjectEventArgs(object eventObject)
: this(eventObject, true)
{
}
/// <summary>
/// Returns the object relating to the event
/// </summary>
/// <remarks>
/// This is protected so that inheritors can expose it with their own name
/// </remarks>
internal object EventObject { get; set; }
}
/// <summary>
/// Event args for a strongly typed object that can support cancellation
/// </summary>
/// <typeparam name="T"></typeparam>
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
public class CancellableObjectEventArgs<T> : CancellableObjectEventArgs, IEquatable<CancellableObjectEventArgs<T>>
{
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
: base(eventObject, canCancel, messages, additionalData)
{
}
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages)
: base(eventObject, canCancel, eventMessages)
{
}
public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages)
: base(eventObject, eventMessages)
{
}
public CancellableObjectEventArgs(T eventObject, bool canCancel)
: base(canCancel)
{
EventObject = eventObject;
}
: base(eventObject, canCancel)
{
}
public CancellableObjectEventArgs(T eventObject)
: this(eventObject, true)
{
}
public CancellableObjectEventArgs(T eventObject)
: base(eventObject)
{
}
/// <summary>
/// Returns the object relating to the event
/// </summary>
/// <remarks>
/// This is protected so that inheritors can expose it with their own name
/// </remarks>
protected T EventObject { get; set; }
/// <summary>
/// Returns the object relating to the event
/// </summary>
/// <remarks>
/// This is protected so that inheritors can expose it with their own name
/// </remarks>
protected new T EventObject
{
get { return (T) base.EventObject; }
set { base.EventObject = value; }
}
public bool Equals(CancellableObjectEventArgs<T> other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return base.Equals(other) && EqualityComparer<T>.Default.Equals(EventObject, other.EventObject);
}
public bool Equals(CancellableObjectEventArgs<T> other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return base.Equals(other) && EqualityComparer<T>.Default.Equals(EventObject, other.EventObject);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CancellableObjectEventArgs<T>) obj);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CancellableObjectEventArgs<T>)obj);
}
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ EqualityComparer<T>.Default.GetHashCode(EventObject);
}
}
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ EqualityComparer<T>.Default.GetHashCode(EventObject);
}
}
public static bool operator ==(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
{
return Equals(left, right);
}
public static bool operator ==(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
{
return Equals(left, right);
}
public static bool operator !=(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
{
return !Equals(left, right);
}
}
public static bool operator !=(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
{
return !Equals(left, right);
}
}
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
public class CancellableEnumerableObjectEventArgs<T> : CancellableObjectEventArgs<IEnumerable<T>>, IEquatable<CancellableEnumerableObjectEventArgs<T>>
{
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
: base(eventObject, canCancel, messages, additionalData)
{ }
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel, EventMessages eventMessages)
: base(eventObject, canCancel, eventMessages)
{ }
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, EventMessages eventMessages)
: base(eventObject, eventMessages)
{ }
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel)
: base(eventObject, canCancel)
{ }
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject)
: base(eventObject)
{ }
public bool Equals(CancellableEnumerableObjectEventArgs<T> other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return EventObject.SequenceEqual(other.EventObject);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CancellableEnumerableObjectEventArgs<T>)obj);
}
public override int GetHashCode()
{
return HashCodeHelper.GetHashCode(EventObject);
}
}
}
+7 -2
View File
@@ -1,9 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Events
{
public class DeleteEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<DeleteEventArgs<TEntity>>, IDeletingMediaFilesEventArgs
[SupersedeEvent(typeof(SaveEventArgs<>))]
[SupersedeEvent(typeof(PublishEventArgs<>))]
[SupersedeEvent(typeof(MoveEventArgs<>))]
[SupersedeEvent(typeof(CopyEventArgs<>))]
public class DeleteEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<DeleteEventArgs<TEntity>>, IDeletingMediaFilesEventArgs
{
/// <summary>
/// Constructor accepting multiple entities that are used in the delete operation
@@ -106,7 +111,7 @@ namespace Umbraco.Core.Events
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return base.Equals(other) && MediaFilesToDelete.Equals(other.MediaFilesToDelete);
return base.Equals(other) && MediaFilesToDelete.SequenceEqual(other.MediaFilesToDelete);
}
public override bool Equals(object obj)
+1 -1
View File
@@ -4,7 +4,7 @@ using System.Xml.Linq;
namespace Umbraco.Core.Events
{
public class ImportEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<ImportEventArgs<TEntity>>
public class ImportEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportEventArgs<TEntity>>
{
/// <summary>
/// Constructor accepting an XElement with the xml being imported
@@ -4,7 +4,7 @@ using Umbraco.Core.Packaging.Models;
namespace Umbraco.Core.Events
{
internal class ImportPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<ImportPackageEventArgs<TEntity>>
internal class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
{
private readonly MetaData _packageMetaData;
@@ -32,7 +32,8 @@ namespace Umbraco.Core.Events
public bool Equals(ImportPackageEventArgs<TEntity> other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (ReferenceEquals(this, other)) return true;
//TODO: MetaData for package metadata has no equality operators :/
return base.Equals(other) && _packageMetaData.Equals(other._packageMetaData);
}
@@ -5,8 +5,10 @@ using System.Linq;
namespace Umbraco.Core.Events
{
/// <summary>
/// This event manager supports event cancellation and will raise the events as soon as they are tracked, it does not store tracked events
/// An IEventDispatcher that immediately raise all events.
/// </summary>
/// <remarks>This means that events will be raised during the scope transaction,
/// whatever happens, and the transaction could roll back in the end.</remarks>
internal class PassThroughEventDispatcher : IEventDispatcher
{
public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string eventName = null)
+1 -1
View File
@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace Umbraco.Core.Events
{
public class PublishEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<PublishEventArgs<TEntity>>
public class PublishEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<PublishEventArgs<TEntity>>
{
/// <summary>
/// Constructor accepting multiple entities that are used in the publish operation
+2 -3
View File
@@ -1,8 +1,9 @@
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Events
{
public class SaveEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
public class SaveEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>
{
/// <summary>
/// Constructor accepting multiple entities that are used in the saving operation
@@ -116,7 +117,5 @@ namespace Umbraco.Core.Events
{
get { return EventObject; }
}
}
}
@@ -3,11 +3,9 @@ using Umbraco.Core.IO;
namespace Umbraco.Core.Events
{
/// <summary>
/// This event manager is created for each scope and is aware of if it is nested in an outer scope
/// An IEventDispatcher that queues events, and raise them when the scope
/// exits and has been completed.
/// </summary>
/// <remarks>
/// The outer scope is the only scope that can raise events, the inner scope's will defer to the outer scope
/// </remarks>
internal class ScopeEventDispatcher : ScopeEventDispatcherBase
{
public ScopeEventDispatcher()
@@ -1,11 +1,23 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Events
{
/// <summary>
/// An IEventDispatcher that queues events.
/// </summary>
/// <remarks>
/// <para>Can raise, or ignore, cancelable events, depending on option.</para>
/// <para>Implementations must override ScopeExitCompleted to define what
/// to do with the events when the scope exits and has been completed.</para>
/// <para>If the scope exits without being completed, events are ignored.</para>
/// </remarks>
public abstract class ScopeEventDispatcherBase : IEventDispatcher
{
//events will be enlisted in the order they are raised
private List<IEventDefinition> _events;
private readonly bool _raiseCancelable;
@@ -64,29 +76,263 @@ namespace Umbraco.Core.Events
{
if (_events == null)
return Enumerable.Empty<IEventDefinition>();
switch (filter)
{
case EventDefinitionFilter.All:
return _events;
return FilterSupersededAndUpdateToLatestEntity(_events);
case EventDefinitionFilter.FirstIn:
var l1 = new OrderedHashSet<IEventDefinition>();
foreach (var e in _events)
{
l1.Add(e);
}
return l1;
return FilterSupersededAndUpdateToLatestEntity(l1);
case EventDefinitionFilter.LastIn:
var l2 = new OrderedHashSet<IEventDefinition>(keepOldest: false);
foreach (var e in _events)
{
l2.Add(e);
}
return l2;
return FilterSupersededAndUpdateToLatestEntity(l2);
default:
throw new ArgumentOutOfRangeException("filter", filter, null);
}
}
private class EventDefinitionTypeData
{
public IEventDefinition EventDefinition { get; set; }
public Type EventArgType { get; set; }
public SupersedeEventAttribute[] SupersedeAttributes { get; set; }
}
/// <summary>
/// This will iterate over the events (latest first) and filter out any events or entities in event args that are included
/// in more recent events that Supersede previous ones. For example, If an Entity has been Saved and then Deleted, we don't want
/// to raise the Saved event (well actually we just don't want to include it in the args for that saved event)
/// </summary>
/// <param name="events"></param>
/// <returns></returns>
private static IEnumerable<IEventDefinition> FilterSupersededAndUpdateToLatestEntity(IReadOnlyList<IEventDefinition> events)
{
//used to keep the 'latest' entity and associated event definition data
var allEntities = new List<Tuple<IEntity, EventDefinitionTypeData>>();
//tracks all CancellableObjectEventArgs instances in the events which is the only type of args we can work with
var cancelableArgs = new List<CancellableObjectEventArgs>();
var result = new List<IEventDefinition>();
//This will eagerly load all of the event arg types and their attributes so we don't have to continuously look this data up
var allArgTypesWithAttributes = events.Select(x => x.Args.GetType())
.Distinct()
.ToDictionary(x => x, x => x.GetCustomAttributes<SupersedeEventAttribute>(false).ToArray());
//Iterate all events and collect the actual entities in them and relates them to their corresponding EventDefinitionTypeData
//we'll process the list in reverse because events are added in the order they are raised and we want to filter out
//any entities from event args that are not longer relevant
//(i.e. if an item is Deleted after it's Saved, we won't include the item in the Saved args)
for (var index = events.Count - 1; index >= 0; index--)
{
var eventDefinition = events[index];
var argType = eventDefinition.Args.GetType();
var attributes = allArgTypesWithAttributes[eventDefinition.Args.GetType()];
var meta = new EventDefinitionTypeData
{
EventDefinition = eventDefinition,
EventArgType = argType,
SupersedeAttributes = attributes
};
var args = eventDefinition.Args as CancellableObjectEventArgs;
if (args != null)
{
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
if (list == null)
{
//extract the event object
var obj = args.EventObject as IEntity;
if (obj != null)
{
//Now check if this entity already exists in other event args that supersede this current event arg type
if (IsFiltered(obj, meta, allEntities) == false)
{
//if it's not filtered we can adde these args to the response
cancelableArgs.Add(args);
result.Add(eventDefinition);
//track the entity
allEntities.Add(Tuple.Create(obj, meta));
}
}
else
{
//Can't retrieve the entity so cant' filter or inspect, just add to the output
result.Add(eventDefinition);
}
}
else
{
var toRemove = new List<IEntity>();
foreach (var entity in list)
{
//extract the event object
var obj = entity as IEntity;
if (obj != null)
{
//Now check if this entity already exists in other event args that supersede this current event arg type
if (IsFiltered(obj, meta, allEntities))
{
//track it to be removed
toRemove.Add(obj);
}
else
{
//track the entity, it's not filtered
allEntities.Add(Tuple.Create(obj, meta));
}
}
else
{
//we don't need to do anything here, we can't cast to IEntity so we cannot filter, so it will just remain in the list
}
}
//remove anything that has been filtered
foreach (var entity in toRemove)
{
list.Remove(entity);
}
//track the event and include in the response if there's still entities remaining in the list
if (list.Count > 0)
{
if (toRemove.Count > 0)
{
//re-assign if the items have changed
args.EventObject = list;
}
cancelableArgs.Add(args);
result.Add(eventDefinition);
}
}
}
else
{
//it's not a cancelable event arg so we just include it in the result
result.Add(eventDefinition);
}
}
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
UpdateToLatestEntities(allEntities, cancelableArgs);
//we need to reverse the result since we've been adding by latest added events first!
result.Reverse();
return result;
}
private static void UpdateToLatestEntities(IEnumerable<Tuple<IEntity, EventDefinitionTypeData>> allEntities, IEnumerable<CancellableObjectEventArgs> cancelableArgs)
{
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
var latestEntities = new OrderedHashSet<IEntity>(keepOldest: true);
foreach (var entity in allEntities.OrderByDescending(entity => entity.Item1.UpdateDate))
{
latestEntities.Add(entity.Item1);
}
foreach (var args in cancelableArgs)
{
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
if (list == null)
{
//try to find the args entity in the latest entity - based on the equality operators, this will
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, args.EventObject));
if (foundEntity != null)
{
args.EventObject = foundEntity;
}
}
else
{
var updated = false;
for (int i = 0; i < list.Count; i++)
{
//try to find the args entity in the latest entity - based on the equality operators, this will
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, list[i]));
if (foundEntity != null)
{
list[i] = foundEntity;
updated = true;
}
}
if (updated)
{
args.EventObject = list;
}
}
}
}
/// <summary>
/// This will check against all of the processed entity/events (allEntities) to see if this entity already exists in
/// event args that supersede the event args being passed in and if so returns true.
/// </summary>
/// <param name="entity"></param>
/// <param name="eventDef"></param>
/// <param name="allEntities"></param>
/// <returns></returns>
private static bool IsFiltered(
IEntity entity,
EventDefinitionTypeData eventDef,
List<Tuple<IEntity, EventDefinitionTypeData>> allEntities)
{
var argType = eventDef.EventDefinition.Args.GetType();
//check if the entity is found in any processed event data that could possible supersede this one
var foundByEntity = allEntities
.Where(x => x.Item2.SupersedeAttributes.Length > 0
//if it's the same arg type than it cannot supersede
&& x.Item2.EventArgType != argType
&& Equals(x.Item1, entity))
.ToArray();
//no args have been processed with this entity so it should not be filtered
if (foundByEntity.Length == 0)
return false;
if (argType.IsGenericType)
{
var supercededBy = foundByEntity
.FirstOrDefault(x =>
x.Item2.SupersedeAttributes.Any(y =>
//if the attribute type is a generic type def then compare with the generic type def of the event arg
(y.SupersededEventArgsType.IsGenericTypeDefinition && y.SupersededEventArgsType == argType.GetGenericTypeDefinition())
//if the attribute type is not a generic type def then compare with the normal type of the event arg
|| (y.SupersededEventArgsType.IsGenericTypeDefinition == false && y.SupersededEventArgsType == argType)));
return supercededBy != null;
}
else
{
var supercededBy = foundByEntity
.FirstOrDefault(x =>
x.Item2.SupersedeAttributes.Any(y =>
//since the event arg type is not a generic type, then we just compare type 1:1
y.SupersededEventArgsType == argType));
return supercededBy != null;
}
}
public void ScopeExit(bool completed)
{
@@ -0,0 +1,20 @@
using System;
namespace Umbraco.Core.Events
{
/// <summary>
/// This is used to know if the event arg attributed should supersede another event arg type when
/// tracking events for the same entity. If one event args supercedes another then the event args that have been superseded
/// will mean that the event will not be dispatched or the args will be filtered to exclude the entity.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
internal class SupersedeEventAttribute : Attribute
{
public Type SupersededEventArgsType { get; private set; }
public SupersedeEventAttribute(Type supersededEventArgsType)
{
SupersededEventArgsType = supersededEventArgsType;
}
}
}
@@ -0,0 +1,12 @@
using System;
namespace Umbraco.Core.Exceptions
{
internal class ConnectionException : Exception
{
public ConnectionException(string message, Exception innerException) : base(message, innerException)
{
}
}
}
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Exceptions
public T Operation { get; private set; }
public DataOperationException(T operation, string message)
:base(message)
: base(message)
{
Operation = operation;
}
+74 -75
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -7,32 +6,32 @@ using System.Text;
namespace Umbraco.Core
{
/// <summary>
/// Used to create a hash code from multiple objects.
/// </summary>
/// <remarks>
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
/// which we've not included here as we just need a quick easy class for this in order to create a unique
/// hash of directories/files to see if they have changed.
/// </remarks>
internal class HashCodeCombiner
{
private long _combinedHash = 5381L;
/// <summary>
/// Used to create a hash code from multiple objects.
/// </summary>
/// <remarks>
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
/// which we've not included here as we just need a quick easy class for this in order to create a unique
/// hash of directories/files to see if they have changed.
/// </remarks>
internal class HashCodeCombiner
{
private long _combinedHash = 5381L;
internal void AddInt(int i)
{
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
}
internal void AddInt(int i)
{
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
}
internal void AddObject(object o)
{
AddInt(o.GetHashCode());
}
internal void AddObject(object o)
{
AddInt(o.GetHashCode());
}
internal void AddDateTime(DateTime d)
{
AddInt(d.GetHashCode());
}
internal void AddDateTime(DateTime d)
{
AddInt(d.GetHashCode());
}
internal void AddString(string s)
{
@@ -40,61 +39,61 @@ namespace Umbraco.Core
AddInt((StringComparer.InvariantCulture).GetHashCode(s));
}
internal void AddCaseInsensitiveString(string s)
{
if (s != null)
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
}
internal void AddCaseInsensitiveString(string s)
{
if (s != null)
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
}
internal void AddFileSystemItem(FileSystemInfo f)
{
//if it doesn't exist, don't proceed.
if (!f.Exists)
return;
internal void AddFileSystemItem(FileSystemInfo f)
{
//if it doesn't exist, don't proceed.
if (!f.Exists)
return;
AddCaseInsensitiveString(f.FullName);
AddDateTime(f.CreationTimeUtc);
AddDateTime(f.LastWriteTimeUtc);
//check if it is a file or folder
var fileInfo = f as FileInfo;
if (fileInfo != null)
{
AddInt(fileInfo.Length.GetHashCode());
}
var dirInfo = f as DirectoryInfo;
if (dirInfo != null)
{
foreach (var d in dirInfo.GetFiles())
{
AddFile(d);
}
foreach (var s in dirInfo.GetDirectories())
{
AddFolder(s);
}
}
}
AddCaseInsensitiveString(f.FullName);
AddDateTime(f.CreationTimeUtc);
AddDateTime(f.LastWriteTimeUtc);
internal void AddFile(FileInfo f)
{
AddFileSystemItem(f);
}
//check if it is a file or folder
var fileInfo = f as FileInfo;
if (fileInfo != null)
{
AddInt(fileInfo.Length.GetHashCode());
}
internal void AddFolder(DirectoryInfo d)
{
AddFileSystemItem(d);
}
var dirInfo = f as DirectoryInfo;
if (dirInfo != null)
{
foreach (var d in dirInfo.GetFiles())
{
AddFile(d);
}
foreach (var s in dirInfo.GetDirectories())
{
AddFolder(s);
}
}
}
/// <summary>
/// Returns the hex code of the combined hash code
/// </summary>
/// <returns></returns>
internal string GetCombinedHashCode()
{
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
}
internal void AddFile(FileInfo f)
{
AddFileSystemItem(f);
}
}
internal void AddFolder(DirectoryInfo d)
{
AddFileSystemItem(d);
}
/// <summary>
/// Returns the hex code of the combined hash code
/// </summary>
/// <returns></returns>
internal string GetCombinedHashCode()
{
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
}
}
}
+104
View File
@@ -0,0 +1,104 @@
using System.Collections.Generic;
namespace Umbraco.Core
{
/// <summary>
/// Borrowed from http://stackoverflow.com/a/2575444/694494
/// </summary>
internal static class HashCodeHelper
{
public static int GetHashCode<T1, T2>(T1 arg1, T2 arg2)
{
unchecked
{
return 31 * arg1.GetHashCode() + arg2.GetHashCode();
}
}
public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
{
unchecked
{
int hash = arg1.GetHashCode();
hash = 31 * hash + arg2.GetHashCode();
return 31 * hash + arg3.GetHashCode();
}
}
public static int GetHashCode<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3,
T4 arg4)
{
unchecked
{
int hash = arg1.GetHashCode();
hash = 31 * hash + arg2.GetHashCode();
hash = 31 * hash + arg3.GetHashCode();
return 31 * hash + arg4.GetHashCode();
}
}
public static int GetHashCode<T>(T[] list)
{
unchecked
{
int hash = 0;
foreach (var item in list)
{
if (item == null) continue;
hash = 31 * hash + item.GetHashCode();
}
return hash;
}
}
public static int GetHashCode<T>(IEnumerable<T> list)
{
unchecked
{
int hash = 0;
foreach (var item in list)
{
if (item == null) continue;
hash = 31 * hash + item.GetHashCode();
}
return hash;
}
}
/// <summary>
/// Gets a hashcode for a collection for that the order of items
/// does not matter.
/// So {1, 2, 3} and {3, 2, 1} will get same hash code.
/// </summary>
public static int GetHashCodeForOrderNoMatterCollection<T>(
IEnumerable<T> list)
{
unchecked
{
int hash = 0;
int count = 0;
foreach (var item in list)
{
if (item == null) continue;
hash += item.GetHashCode();
count++;
}
return 31 * hash + count.GetHashCode();
}
}
/// <summary>
/// Alternative way to get a hashcode is to use a fluent
/// interface like this:<br />
/// return 0.CombineHashCode(field1).CombineHashCode(field2).
/// CombineHashCode(field3);
/// </summary>
public static int CombineHashCode<T>(this int hashCode, T arg)
{
unchecked
{
return 31 * hashCode + arg.GetHashCode();
}
}
}
}
+1 -1
View File
@@ -159,7 +159,7 @@ namespace Umbraco.Core.IO
// ReSharper disable once AssignNullToNotNullAttribute
var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
? Path.Combine(folder, filename)
? Path.Combine(folder, filename).Replace('\\', '/')
: folder + "-" + filename;
return filepath;
+14 -3
View File
@@ -52,9 +52,20 @@ namespace Umbraco.Core.IO
try
{
Directory.Delete(dir, true);
dir = dir.Substring(0, dir.Length - _shadowPath.Length - 1);
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
Directory.Delete(dir, true);
// shadowPath make be path/to/dir, remove each
dir = dir.Replace("/", "\\");
var min = IOHelper.MapPath("~/App_Data/TEMP/ShadowFs").Length;
var pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase);
while (pos > min)
{
dir = dir.Substring(0, pos);
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
Directory.Delete(dir, true);
else
break;
pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase);
}
}
catch
{
@@ -42,6 +42,7 @@ namespace Umbraco.Core.Models
public Guid Key { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
public DateTime? DeletedDate { get; set; }
/// <summary>
/// Special case, always return false, this will cause the repositories managing
@@ -60,5 +61,7 @@ namespace Umbraco.Core.Models
DeepCloneHelper.DeepCloneRefProperties(this, clone);
return clone;
}
}
}
@@ -101,6 +101,9 @@ namespace Umbraco.Core.Models.EntityBase
set { SetPropertyValueAndDetectChanges(value, ref _updateDate, Ps.Value.UpdateDateSelector); }
}
[IgnoreDataMember]
public DateTime? DeletedDate { get; set; }
internal virtual void ResetIdentity()
{
_hasIdentity = false;
@@ -3,7 +3,7 @@
/// <summary>
/// Marker interface for aggregate roots
/// </summary>
public interface IAggregateRoot : IEntity
public interface IAggregateRoot : IDeletableEntity
{
}
@@ -0,0 +1,11 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models.EntityBase
{
public interface IDeletableEntity : IEntity
{
[DataMember]
DateTime? DeletedDate { get; set; }
}
}
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Models.EntityBase
/// <summary>
/// Guid based Id
/// </summary>
/// <remarks>The key is currectly used to store the Unique Id from the
/// <remarks>The key is currectly used to store the Unique Id from the
/// umbracoNode table, which many of the entities are based on.</remarks>
[DataMember]
Guid Key { get; set; }
+1 -1
View File
@@ -2,6 +2,6 @@
{
public interface IPartialView : IFile
{
PartialViewType ViewType { get; }
}
}
+11 -6
View File
@@ -1,10 +1,8 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Services;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a Partial View file
/// </summary>
@@ -12,14 +10,21 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
public class PartialView : File, IPartialView
{
[Obsolete("Use the ctor that explicitely sets the view type.")]
public PartialView(string path)
: this(path, null)
: this(PartialViewType.PartialView, path, null)
{ }
internal PartialView(string path, Func<File, string> getFileContent)
public PartialView(PartialViewType viewType, string path)
: this(viewType, path, null)
{ }
internal PartialView(PartialViewType viewType, string path, Func<File, string> getFileContent)
: base(path, getFileContent)
{ }
{
ViewType = viewType;
}
internal PartialViewType ViewType { get; set; }
public PartialViewType ViewType { get; set; }
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Models
{
internal enum PartialViewType : byte
public enum PartialViewType : byte
{
Unknown = 0, // default
PartialView = 1,
+1 -1
View File
@@ -11,7 +11,7 @@ namespace Umbraco.Core
{
private readonly bool _keepOldest;
public OrderedHashSet(bool keepOldest = true)
public OrderedHashSet(bool keepOldest = true)
{
_keepOldest = keepOldest;
}
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Migrations
Logger = logger;
}
public IMigrationContext Context { get; internal set; }
public IMigrationContext Context;
public abstract void Up();
public abstract void Down();
@@ -30,8 +30,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
var version = database.FirstOrDefault<string>("SELECT version FROM umbracoMigration WHERE name=@name ORDER BY version DESC", new { name = Constants.System.UmbracoMigrationName });
if (version != null && version.StartsWith("7.6.0")) return string.Empty;
var updates = database.Query<dynamic>("SELECT id, text FROM umbracoNode WHERE nodeObjectType = @guid", new { guid = Constants.ObjectTypes.TemplateTypeGuid})
.Select(template => Tuple.Create((int) template.id, ("template____" + (string) template.text).ToGuid()))
var updates = database.Query<dynamic>(@"SELECT umbracoNode.id, cmsTemplate.alias FROM umbracoNode
JOIN cmsTemplate ON umbracoNode.id=cmsTemplate.nodeId
WHERE nodeObjectType = @guid", new { guid = Constants.ObjectTypes.TemplateTypeGuid})
.Select(template => Tuple.Create((int) template.id, ("template____" + (string) template.alias).ToGuid()))
.ToList();
foreach (var update in updates)
@@ -2,6 +2,7 @@
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
@@ -16,7 +17,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
public override void Up()
{
var exists = Context.Database.FirstOrDefault<RelationTypeDto>("WHERE alias=@alias", new {alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias});
var exists = Context.Database.FirstOrDefault<RelationTypeDtoCapture>("WHERE alias=@alias", new {alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias});
if (exists == null)
{
Insert.IntoTable("umbracoRelationType").Row(new
@@ -28,13 +29,42 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias
});
}
}
public override void Down()
{ }
// need to capture the DTO as it is modified in later migrations
[TableName("umbracoRelationType")]
[PrimaryKey("id")]
[ExplicitColumns]
internal class RelationTypeDtoCapture
{
public const int NodeIdSeed = 3;
[Column("id")]
[PrimaryKeyColumn(IdentitySeed = NodeIdSeed)]
public int Id { get; set; }
[Column("dual")]
public bool Dual { get; set; }
[Column("parentObjectType")]
public Guid ParentObjectType { get; set; }
[Column("childObjectType")]
public Guid ChildObjectType { get; set; }
[Column("name")]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoRelationType_name")]
public string Name { get; set; }
[Column("alias")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(100)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoRelationType_alias")]
public string Alias { get; set; }
}
}
}
@@ -70,6 +70,8 @@ namespace Umbraco.Core.Persistence.Repositories
{
//Remove 'published' xml from the cmsContentXml table for the unpublished content
Database.Delete<ContentXmlDto>("WHERE nodeId = @Id", new { Id = entity.Id });
entity.DeletedDate = DateTime.Now;
}
protected override void PersistNewItem(ContentXmlEntity<TContent> entity)
@@ -270,6 +270,8 @@ AND umbracoNode.id <> @id",
//Delete (base) node data
Database.Delete<NodeDto>("WHERE uniqueID = @Id", new { Id = entity.Key });
entity.DeletedDate = DateTime.Now;
}
#endregion
@@ -539,6 +541,8 @@ AND umbracoNode.id <> @id",
Database.Execute(
"DELETE FROM cmsDataTypePreValues WHERE id=@Id",
new { Id = entity.Id });
entity.DeletedDate = DateTime.Now;
}
protected override void PersistNewItem(PreValueEntity entity)
@@ -195,6 +195,8 @@ namespace Umbraco.Core.Persistence.Repositories
//Clear the cache entries that exist by uniqueid/item key
IsolatedCache.ClearCacheItem(GetCacheIdKey<IDictionaryItem>(entity.ItemKey));
IsolatedCache.ClearCacheItem(GetCacheIdKey<IDictionaryItem>(entity.Key));
entity.DeletedDate = DateTime.Now;
}
private void RecursiveDelete(Guid parentId)
@@ -167,6 +167,8 @@ namespace Umbraco.Core.Persistence.Repositories
// delete
Database.Delete(nodeDto);
entity.DeletedDate = DateTime.Now;
}
protected override void PersistNewItem(EntityContainer entity)
@@ -30,7 +30,7 @@ namespace Umbraco.Core.Persistence.Repositories
var updated = FileSystem.GetLastModified(path).UtcDateTime;
//var content = GetFileContent(path);
var view = new PartialView(path, file => GetFileContent(file.OriginalPath))
var view = new PartialView(ViewType, path, file => GetFileContent(file.OriginalPath))
{
//id can be the hash
Id = path.GetHashCode(),
@@ -38,8 +38,7 @@ namespace Umbraco.Core.Persistence.Repositories
//Content = content,
CreateDate = created,
UpdateDate = updated,
VirtualPath = FileSystem.GetUrl(id),
ViewType = ViewType
VirtualPath = FileSystem.GetUrl(id)
};
//on initial construction we don't want to have dirty properties tracked
@@ -74,6 +74,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
Database.Execute(delete, new { Id = GetEntityId(entity) });
}
entity.DeletedDate = DateTime.Now;
}
}
}
@@ -311,6 +311,8 @@ namespace Umbraco.Core.Persistence.Repositories
var masterpageName = string.Concat(entity.Alias, ".master");
_masterpagesFileSystem.DeleteFile(masterpageName);
}
entity.DeletedDate = DateTime.Now;
}
#endregion
@@ -8,5 +8,6 @@ namespace Umbraco.Core.Persistence.UnitOfWork
IScope Scope { get; }
EventMessages Messages { get; }
IEventDispatcher Events { get; }
void Flush();
}
}
@@ -160,7 +160,33 @@ namespace Umbraco.Core.Persistence.UnitOfWork
_key = Guid.NewGuid();
}
public object Key
public void Flush()
{
if (_readOnly)
throw new NotSupportedException("This unit of work is read-only.");
while (_operations.Count > 0)
{
var operation = _operations.Dequeue();
switch (operation.Type)
{
case TransactionType.Insert:
operation.Repository.PersistNewItem(operation.Entity);
break;
case TransactionType.Delete:
operation.Repository.PersistDeletedItem(operation.Entity);
break;
case TransactionType.Update:
operation.Repository.PersistUpdatedItem(operation.Entity);
break;
}
}
_operations.Clear();
_key = Guid.NewGuid();
}
public object Key
{
get { return _key; }
}
@@ -20,6 +20,11 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview)
{
if(source == null)
{
return string.Empty;
}
return source.ToString();
}
+1
View File
@@ -465,6 +465,7 @@ namespace Umbraco.Core.Scoping
}
finally
{
// removes the ambient context (ambient scope already gone)
_scopeProvider.SetAmbient(null);
}
}
+41 -35
View File
@@ -1,16 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Scoping
{
public class ScopeContext : IInstanceIdentifiable
{
private Dictionary<string, IEnlistedObject> _enlisted;
private bool _exiting;
public void ScopeExit(bool completed)
{
if (_enlisted == null)
return;
_exiting = true;
List<Exception> exceptions = null;
foreach (var enlisted in Enlisted.Values)
foreach (var enlisted in _enlisted.Values.OrderBy(x => x.Priority))
{
try
{
@@ -23,6 +30,7 @@ namespace Umbraco.Core.Scoping
exceptions.Add(e);
}
}
if (exceptions != null)
throw new AggregateException("Exceptions were thrown by listed actions.", exceptions);
}
@@ -42,73 +50,71 @@ namespace Umbraco.Core.Scoping
private interface IEnlistedObject
{
void Execute(bool completed);
int Priority { get; }
}
private class EnlistedObject<T> : IEnlistedObject
{
private readonly Action<bool, T> _action;
public EnlistedObject(T item)
{
Item = item;
}
public EnlistedObject(T item, Action<bool, T> action)
public EnlistedObject(T item, Action<bool, T> action, int priority)
{
Item = item;
Priority = priority;
_action = action;
}
public T Item { get; private set; }
public int Priority { get; private set; }
public void Execute(bool completed)
{
_action(completed, Item);
}
}
/// <inheritdoc />
// todo: replace with optional parameters when we can break things
public T Enlist<T>(string key, Func<T> creator)
{
IEnlistedObject enlisted;
if (Enlisted.TryGetValue(key, out enlisted))
{
var enlistedAs = enlisted as EnlistedObject<T>;
if (enlistedAs == null) throw new Exception("An item with a different type has already been enlisted with the same key.");
return enlistedAs.Item;
}
var enlistedOfT = new EnlistedObject<T>(creator());
Enlisted[key] = enlistedOfT;
return enlistedOfT.Item;
return Enlist(key, creator, null, 100);
}
/// <inheritdoc />
// todo: replace with optional parameters when we can break things
public T Enlist<T>(string key, Func<T> creator, Action<bool, T> action)
{
IEnlistedObject enlisted;
if (Enlisted.TryGetValue(key, out enlisted))
{
var enlistedAs = enlisted as EnlistedObject<T>;
if (enlistedAs == null) throw new Exception("An item with a different type has already been enlisted with the same key.");
return enlistedAs.Item;
}
var enlistedOfT = new EnlistedObject<T>(creator(), action);
Enlisted[key] = enlistedOfT;
return enlistedOfT.Item;
return Enlist(key, creator, action, 100);
}
/// <inheritdoc />
// todo: replace with optional parameters when we can break things
public void Enlist(string key, Action<bool> action)
{
Enlist<object>(key, null, (completed, item) => action(completed), 100);
}
public void Enlist(string key, Action<bool> action, int priority)
{
Enlist<object>(key, null, (completed, item) => action(completed), priority);
}
public T Enlist<T>(string key, Func<T> creator, Action<bool, T> action, int priority)
{
if (_exiting)
throw new InvalidOperationException("Cannot enlist now, context is exiting.");
var enlistedObjects = _enlisted ?? (_enlisted = new Dictionary<string, IEnlistedObject>());
IEnlistedObject enlisted;
if (Enlisted.TryGetValue(key, out enlisted))
if (enlistedObjects.TryGetValue(key, out enlisted))
{
var enlistedAs = enlisted as EnlistedObject<object>;
if (enlistedAs == null) throw new Exception("An item with a different type has already been enlisted with the same key.");
return;
var enlistedAs = enlisted as EnlistedObject<T>;
if (enlistedAs == null) throw new InvalidOperationException("An item with the key already exists, but with a different type.");
if (enlistedAs.Priority != priority) throw new InvalidOperationException("An item with the key already exits, but with a different priority.");
return enlistedAs.Item;
}
var enlistedOfT = new EnlistedObject<object>(null, (completed, item) => action(completed));
var enlistedOfT = new EnlistedObject<T>(creator == null ? default(T) : creator(), action, priority);
Enlisted[key] = enlistedOfT;
return enlistedOfT.Item;
}
}
}
@@ -191,6 +191,7 @@ namespace Umbraco.Core.Security
//track the last login date
user.LastLoginDateUtc = DateTime.UtcNow;
user.AccessFailedCount = 0;
await UserManager.UpdateAsync(user);
_logger.WriteCore(TraceEventType.Information, 0,
@@ -231,4 +232,4 @@ namespace Umbraco.Core.Security
return null;
}
}
}
}
@@ -83,7 +83,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public bool HasContainerInPath(string contentPath)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
// can use same repo for both content and media
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
+15 -29
View File
@@ -95,6 +95,16 @@ namespace Umbraco.Core.Services
return result.HasValue ? Attempt.Succeed(result.Value) : Attempt<int>.Fail();
}
public Attempt<int> GetIdForUdi(Udi udi)
{
var guidUdi = udi as GuidUdi;
if (guidUdi == null)
return Attempt<int>.Fail();
var umbracoType = Constants.UdiEntityType.ToUmbracoObjectType(guidUdi.EntityType);
return GetIdForKey(guidUdi.Guid, umbracoType);
}
/// <summary>
/// Returns the GUID for a given integer id
/// </summary>
@@ -124,35 +134,11 @@ namespace Umbraco.Core.Services
private static Guid GetNodeObjectTypeGuid(UmbracoObjectTypes umbracoObjectType)
{
switch (umbracoObjectType)
{
case UmbracoObjectTypes.Document:
return Constants.ObjectTypes.DocumentGuid;
case UmbracoObjectTypes.MemberType:
return Constants.ObjectTypes.MemberTypeGuid;
case UmbracoObjectTypes.Media:
return Constants.ObjectTypes.MediaGuid;
case UmbracoObjectTypes.Template:
return Constants.ObjectTypes.TemplateTypeGuid;
case UmbracoObjectTypes.MediaType:
return Constants.ObjectTypes.MediaTypeGuid;
case UmbracoObjectTypes.DocumentType:
return Constants.ObjectTypes.DocumentTypeGuid;
case UmbracoObjectTypes.Member:
return Constants.ObjectTypes.MemberGuid;
case UmbracoObjectTypes.DataType:
return Constants.ObjectTypes.DataTypeGuid;
case UmbracoObjectTypes.MemberGroup:
return Constants.ObjectTypes.MemberGroupGuid;
case UmbracoObjectTypes.RecycleBin:
case UmbracoObjectTypes.Stylesheet:
case UmbracoObjectTypes.ContentItem:
case UmbracoObjectTypes.ContentItemType:
case UmbracoObjectTypes.ROOT:
case UmbracoObjectTypes.Unknown:
default:
throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ").");
}
var guid = umbracoObjectType.GetGuid();
if (guid == Guid.Empty)
throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ").");
return guid;
}
public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true)
@@ -14,8 +14,7 @@ namespace Umbraco.Core.Services
{
public ExternalLoginService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
}
{ }
/// <summary>
/// Returns all user logins assigned
@@ -23,30 +22,32 @@ namespace Umbraco.Core.Services
/// <param name="userId"></param>
/// <returns></returns>
public IEnumerable<IIdentityUserLogin> GetAll(int userId)
{
using (var uow = UowProvider.GetUnitOfWork())
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
// ToList is important here, must evaluate within uow!
var repo = RepositoryFactory.CreateExternalLoginRepository(uow);
var ret = repo.GetByQuery(new Query<IIdentityUserLogin>().Where(x => x.UserId == userId));
uow.Commit();
return ret;
return repo.GetByQuery(new Query<IIdentityUserLogin>()
.Where(x => x.UserId == userId))
.ToList();
}
}
/// <summary>
/// Returns all logins matching the login info - generally there should only be one but in some cases
/// Returns all logins matching the login info - generally there should only be one but in some cases
/// there might be more than one depending on if an adminstrator has been editing/removing members
/// </summary>
/// <param name="login"></param>
/// <returns></returns>
public IEnumerable<IIdentityUserLogin> Find(UserLoginInfo login)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
// ToList is important here, must evaluate within uow!
var repo = RepositoryFactory.CreateExternalLoginRepository(uow);
var ret = repo.GetByQuery(new Query<IIdentityUserLogin>().Where(x => x.ProviderKey == login.ProviderKey && x.LoginProvider == login.LoginProvider));
uow.Commit();
return ret;
return repo.GetByQuery(new Query<IIdentityUserLogin>()
.Where(x => x.ProviderKey == login.ProviderKey && x.LoginProvider == login.LoginProvider))
.ToList();
}
}
@@ -78,7 +79,5 @@ namespace Umbraco.Core.Services
uow.Commit();
}
}
}
}
+8 -1
View File
@@ -28,7 +28,14 @@ namespace Umbraco.Core.Services
/// <param name="key"></param>
/// <param name="umbracoObjectType"></param>
/// <returns></returns>
Attempt<int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType);
Attempt<int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType);
/// <summary>
/// Returns the integer id for a given Udi
/// </summary>
/// <param name="udi"></param>
/// <returns></returns>
Attempt<int> GetIdForUdi(Udi udi);
/// <summary>
/// Returns the GUID for a given integer id
+11 -1
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Umbraco.Core.Models;
@@ -6,6 +7,15 @@ namespace Umbraco.Core.Services
{
public interface IPackagingService : IService
{
/// <summary>
/// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file
/// </summary>
/// <param name="packageId"></param>
/// <param name="umbracoVersion"></param>
/// <param name="userId">The current user id performing the operation</param>
/// <returns></returns>
string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId);
/// <summary>
/// Imports and saves package xml as <see cref="IContent"/>
/// </summary>
+14 -8
View File
@@ -692,11 +692,11 @@ namespace Umbraco.Core.Services
}
Func<string, Sql> createSql = url => new Sql().Select("*")
.From<PropertyDataDto>()
.InnerJoin<PropertyTypeDto>()
.On<PropertyDataDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.Where<PropertyTypeDto>(x => x.Alias == "umbracoFile")
.Where<PropertyDataDto>(x => x.VarChar == url);
.From<PropertyDataDto>()
.InnerJoin<PropertyTypeDto>()
.On<PropertyDataDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.Where<PropertyTypeDto>(x => x.Alias == "umbracoFile")
.Where<PropertyDataDto>(x => x.VarChar == url);
var sql = createSql(umbracoFileValue);
@@ -899,8 +899,14 @@ namespace Umbraco.Core.Services
throw new ArgumentException("Cannot save media with empty name.");
}
var repository = RepositoryFactory.CreateMediaRepository(uow);
media.CreatorId = userId;
var repository = RepositoryFactory.CreateMediaRepository(uow);
//set the creator id if it's new
if (media.HasIdentity == false)
{
media.CreatorId = userId;
}
repository.AddOrUpdate(media);
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, m));
// generate preview for blame history?
@@ -1048,7 +1054,7 @@ namespace Umbraco.Core.Services
/// <param name="userId">Optional id of the user deleting the media</param>
public void DeleteMediaOfType(int mediaTypeId, int userId = 0)
{
DeleteMediaOfTypes(new[] {mediaTypeId}, userId);
DeleteMediaOfTypes(new[] { mediaTypeId }, userId);
}
/// <summary>
@@ -1,15 +1,20 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI.WebControls;
using System.Xml.Linq;
using System.Xml.XPath;
using Newtonsoft.Json;
using Umbraco.Core.Auditing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
@@ -75,6 +80,61 @@ namespace Umbraco.Core.Services
_importedContentTypes = new Dictionary<string, IContentType>();
}
/// <summary>
/// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file
/// </summary>
/// <param name="packageId"></param>
/// <param name="umbracoVersion"></param>
/// /// <param name="userId">The current user id performing the operation</param>
/// <returns></returns>
public string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId)
{
var packageRepo = UmbracoConfig.For.UmbracoSettings().PackageRepositories.GetDefault();
using (var httpClient = new HttpClient())
using (var uow = _uowProvider.GetUnitOfWork())
{
//includeHidden = true because we don't care if it's hidden we want to get the file regardless
var url = string.Format("{0}/{1}?version={2}&includeHidden=true&asFile=true", packageRepo.RestApiUrl, packageId, umbracoVersion.ToString(3));
byte[] bytes;
try
{
bytes = httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult();
}
catch (HttpRequestException ex)
{
throw new ConnectionException("An error occuring downloading the package from " + url, ex);
}
//successfull
if (bytes.Length > 0)
{
var packagePath = IOHelper.MapPath(SystemDirectories.Packages);
// Check for package directory
if (Directory.Exists(packagePath) == false)
Directory.CreateDirectory(packagePath);
var packageFilePath = Path.Combine(packagePath, packageId + ".umb");
using (var fs1 = new FileStream(packageFilePath, FileMode.Create))
{
fs1.Write(bytes, 0, bytes.Length);
return "packages\\" + packageId + ".umb";
}
}
Audit(uow, AuditType.PackagerInstall, string.Format("Package {0} fetched from {1}", packageId, packageRepo.Id), userId, -1);
return null;
}
}
private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId)
{
var auditRepo = _repositoryFactory.CreateAuditRepository(uow);
auditRepo.AddOrUpdate(new AuditItem(objectId, message, type, userId));
}
#region Content
/// <summary>
+16 -2
View File
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Linq;
namespace Umbraco.Core
{
@@ -20,7 +21,7 @@ namespace Umbraco.Core
/// <param name="entityType">The entity type part of the udi.</param>
/// <param name="id">The string id part of the udi.</param>
public StringUdi(string entityType, string id)
: base(entityType, "umb://" + entityType + "/" + id)
: base(entityType, "umb://" + entityType + "/" + EscapeUriString(id))
{
Id = id;
}
@@ -32,7 +33,20 @@ namespace Umbraco.Core
public StringUdi(Uri uriValue)
: base(uriValue)
{
Id = uriValue.AbsolutePath.TrimStart('/');
Id = Uri.UnescapeDataString(uriValue.AbsolutePath.TrimStart('/'));
}
private static string EscapeUriString(string s)
{
// Uri.EscapeUriString preserves / but also [ and ] which is bad
// Uri.EscapeDataString does not preserve / which is bad
// reserved = : / ? # [ ] @ ! $ & ' ( ) * + , ; =
// unreserved = alpha digit - . _ ~
// we want to preserve the / and the unreserved
// so...
return string.Join("/", s.Split('/').Select(Uri.EscapeDataString));
}
/// <summary>
@@ -4,6 +4,7 @@ using System.Web;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Sync
{
@@ -40,8 +41,9 @@ namespace Umbraco.Core.Sync
.ToList();
if (serversA.Length == 0)
{
{
_serverRole = ServerRole.Unknown; // config error, actually
LogHelper.Debug<ConfigServerRegistrar>(string.Format("Server Role Unknown: DistributedCalls are enabled but no servers are listed"));
}
else
{
@@ -50,7 +52,10 @@ namespace Umbraco.Core.Sync
var serverName = master.ServerName;
if (appId.IsNullOrWhiteSpace() && serverName.IsNullOrWhiteSpace())
{
_serverRole = ServerRole.Unknown; // config error, actually
LogHelper.Debug<ConfigServerRegistrar>(string.Format("Server Role Unknown: Server Name or AppId missing from Server configuration in DistributedCalls settings"));
}
else
_serverRole = IsCurrentServer(appId, serverName)
? ServerRole.Master
+2 -2
View File
@@ -166,8 +166,8 @@ namespace Umbraco.Core
return true;
}
return false;
}
}
/// <summary>
/// Determines whether [is of generic type] [the specified type].
/// </summary>
+45 -4
View File
@@ -2,6 +2,7 @@ using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
@@ -15,11 +16,51 @@ namespace Umbraco.Core
{
private static readonly ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]> GetPropertiesCache
= new ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]>();
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache
= new ConcurrentDictionary<Type, FieldInfo[]>();
private static readonly Assembly[] EmptyAssemblies = new Assembly[0];
/// <summary>
/// Based on a type we'll check if it is IEnumerable{T} (or similar) and if so we'll return a List{T}, this will also deal with array types and return List{T} for those too.
/// If it cannot be done, null is returned.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
internal static IList CreateGenericEnumerableFromObject(object obj)
{
var type = obj.GetType();
if (type.IsGenericType)
{
var genericTypeDef = type.GetGenericTypeDefinition();
if (genericTypeDef == typeof(IEnumerable<>)
|| genericTypeDef == typeof(ICollection<>)
|| genericTypeDef == typeof(Collection<>)
|| genericTypeDef == typeof(IList<>)
|| genericTypeDef == typeof(List<>)
//this will occur when Linq is used and we get the odd WhereIterator or DistinctIterators since those are special iterator types
|| obj is IEnumerable)
{
//if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<>
var genericType = typeof(List<>).MakeGenericType(type.GetGenericArguments());
//pass in obj to fill the list
return (IList)Activator.CreateInstance(genericType, obj);
}
}
if (type.IsArray)
{
//if its an array, we'll use a List<>
var genericType = typeof(List<>).MakeGenericType(type.GetElementType());
//pass in obj to fill the list
return (IList)Activator.CreateInstance(genericType, obj);
}
return null;
}
/// <summary>
/// Checks if the method is actually overriding a base method
/// </summary>
@@ -45,8 +86,8 @@ namespace Umbraco.Core
if (assembly.IsAppCodeAssembly() || assembly.IsGlobalAsaxAssembly())
return EmptyAssemblies;
// find all assembly references that are referencing the current type's assembly since we
// find all assembly references that are referencing the current type's assembly since we
// should only be scanning those assemblies because any other assembly will definitely not
// contain sub type's of the one we're currently looking for
var name = assembly.GetName().Name;
+3 -2
View File
@@ -101,7 +101,8 @@ namespace Umbraco.Core
public override string ToString()
{
// UriValue is created in the ctor and is never null
return UriValue.ToString();
// use AbsoluteUri here and not ToString else it's not encoded!
return UriValue.AbsoluteUri;
}
/// <summary>
@@ -159,7 +160,7 @@ namespace Umbraco.Core
}
if (udiType == UdiType.StringUdi)
{
udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, path);
udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, Uri.UnescapeDataString(path));
return true;
}
if (tryParse) return false;
+7 -1
View File
@@ -198,7 +198,13 @@ namespace Umbraco.Core
public static StringUdi GetUdi(this IPartialView entity)
{
if (entity == null) throw new ArgumentNullException("entity");
return new StringUdi(Constants.UdiEntityType.PartialView, entity.Path.TrimStart('/')).EnsureClosed();
// we should throw on Unknown but for the time being, assume it means PartialView
var entityType = entity.ViewType == PartialViewType.PartialViewMacro
? Constants.UdiEntityType.PartialViewMacro
: Constants.UdiEntityType.PartialView;
return new StringUdi(entityType, entity.Path.TrimStart('/')).EnsureClosed();
}
/// <summary>
+8 -3
View File
@@ -100,9 +100,8 @@
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Semver, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Semver.2.0.4\lib\netstandard1.1\Semver.dll</HintPath>
<Private>True</Private>
<Reference Include="Semver, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\semver.1.1.2\lib\net45\Semver.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
@@ -238,6 +237,7 @@
<Compile Include="Configuration\UmbracoSettings\ContentError404Collection.cs" />
<Compile Include="Configuration\UmbracoSettings\ContentErrorPageElement.cs" />
<Compile Include="Configuration\UmbracoSettings\ContentErrorsElement.cs" />
<Compile Include="Configuration\UmbracoSettings\ContentSectionExtensions.cs" />
<Compile Include="Configuration\UmbracoSettings\ImagingAutoFillPropertiesCollection.cs" />
<Compile Include="Configuration\UmbracoSettings\ImagingAutoFillUploadFieldElement.cs" />
<Compile Include="Configuration\UmbracoSettings\ContentImagingElement.cs" />
@@ -292,6 +292,7 @@
<Compile Include="Configuration\UmbracoSettings\RazorStaticMappingElement.cs" />
<Compile Include="Configuration\UmbracoSettings\RepositoriesCollection.cs" />
<Compile Include="Configuration\UmbracoSettings\RepositoriesElement.cs" />
<Compile Include="Configuration\UmbracoSettings\RepositoryConfigExtensions.cs" />
<Compile Include="Configuration\UmbracoSettings\RepositoryElement.cs" />
<Compile Include="Configuration\UmbracoSettings\RequestHandlerElement.cs" />
<Compile Include="Configuration\UmbracoSettings\ScheduledTaskElement.cs" />
@@ -338,7 +339,11 @@
<Compile Include="Events\IDeletingMediaFilesEventArgs.cs" />
<Compile Include="Events\ScopeEventDispatcherBase.cs" />
<Compile Include="Events\ScopeLifespanMessagesFactory.cs" />
<Compile Include="Events\SupersedeEventAttribute.cs" />
<Compile Include="Exceptions\ConnectionException.cs" />
<Compile Include="HashCodeHelper.cs" />
<Compile Include="IHttpContextAccessor.cs" />
<Compile Include="Models\EntityBase\IDeletableEntity.cs" />
<Compile Include="Models\PublishedContent\PublishedContentTypeConverter.cs" />
<Compile Include="OrderedHashSet.cs" />
<Compile Include="Events\UninstallPackageEventArgs.cs" />
+1 -5
View File
@@ -15,11 +15,7 @@
<package id="MySql.Data" version="6.9.9" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="Semver" version="2.0.4" targetFramework="net45" />
<package id="semver" version="1.1.2" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
<package id="System.Runtime" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net45" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net45" />
<package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net45" />
</packages>
+1
View File
@@ -79,6 +79,7 @@
</system.data>
<system.web>
<httpRuntime targetFramework="4.5" />
<compilation defaultLanguage="c#" debug="true" batch="false" targetFramework="4.0"></compilation>
<machineKey validationKey="5E7B955FCE36F5F2A867C2A0D85DC61E7FEA9E15F1561E8386F78BFE9EE23FF18B21E6A44AA17300B3B9D5DBEB37AA61A2C73884A5BBEDA6D3B14BA408A7A8CD" decryptionKey="116B853D031219E404E088FCA0986D6CF2DFA77E1957B59FCC9404B8CA3909A1" validation="SHA1" decryption="AES" />
<!--<trust level="Medium" originUrl=".*"/>-->
@@ -7,6 +7,7 @@ using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Cache;
using System.Linq;
namespace Umbraco.Tests.Cache
{
@@ -31,70 +32,70 @@ namespace Umbraco.Tests.Cache
new EventDefinition<ISectionService, EventArgs>(null, ServiceContext.SectionService, new EventArgs(), "Deleted"),
new EventDefinition<ISectionService, EventArgs>(null, ServiceContext.SectionService, new EventArgs(), "New"),
new EventDefinition<IUserService, SaveEventArgs<IUserType>>(null, ServiceContext.UserService, new SaveEventArgs<IUserType>((IUserType) null)),
new EventDefinition<IUserService, DeleteEventArgs<IUserType>>(null, ServiceContext.UserService, new DeleteEventArgs<IUserType>((IUserType) null)),
new EventDefinition<IUserService, SaveEventArgs<IUserType>>(null, ServiceContext.UserService, new SaveEventArgs<IUserType>(Enumerable.Empty<IUserType>())),
new EventDefinition<IUserService, DeleteEventArgs<IUserType>>(null, ServiceContext.UserService, new DeleteEventArgs<IUserType>(Enumerable.Empty<IUserType>())),
new EventDefinition<IUserService, SaveEventArgs<IUser>>(null, ServiceContext.UserService, new SaveEventArgs<IUser>((IUser) null)),
new EventDefinition<IUserService, DeleteEventArgs<IUser>>(null, ServiceContext.UserService, new DeleteEventArgs<IUser>((IUser) null)),
new EventDefinition<IUserService, DeleteEventArgs<IUser>>(null, ServiceContext.UserService, new DeleteEventArgs<IUser>((IUser) null)),
new EventDefinition<IUserService, SaveEventArgs<IUser>>(null, ServiceContext.UserService, new SaveEventArgs<IUser>(Enumerable.Empty<IUser>())),
new EventDefinition<IUserService, DeleteEventArgs<IUser>>(null, ServiceContext.UserService, new DeleteEventArgs<IUser>(Enumerable.Empty<IUser>())),
new EventDefinition<IUserService, DeleteEventArgs<IUser>>(null, ServiceContext.UserService, new DeleteEventArgs<IUser>(Enumerable.Empty<IUser>())),
new EventDefinition<ILocalizationService, SaveEventArgs<IDictionaryItem>>(null, ServiceContext.LocalizationService, new SaveEventArgs<IDictionaryItem>((IDictionaryItem) null)),
new EventDefinition<ILocalizationService, DeleteEventArgs<IDictionaryItem>>(null, ServiceContext.LocalizationService, new DeleteEventArgs<IDictionaryItem>((IDictionaryItem) null)),
new EventDefinition<ILocalizationService, SaveEventArgs<IDictionaryItem>>(null, ServiceContext.LocalizationService, new SaveEventArgs<IDictionaryItem>(Enumerable.Empty<IDictionaryItem>())),
new EventDefinition<ILocalizationService, DeleteEventArgs<IDictionaryItem>>(null, ServiceContext.LocalizationService, new DeleteEventArgs<IDictionaryItem>(Enumerable.Empty<IDictionaryItem>())),
new EventDefinition<IDataTypeService, SaveEventArgs<IDataTypeDefinition>>(null, ServiceContext.DataTypeService, new SaveEventArgs<IDataTypeDefinition>((IDataTypeDefinition) null)),
new EventDefinition<IDataTypeService, DeleteEventArgs<IDataTypeDefinition>>(null, ServiceContext.DataTypeService, new DeleteEventArgs<IDataTypeDefinition>((IDataTypeDefinition) null)),
new EventDefinition<IDataTypeService, SaveEventArgs<IDataTypeDefinition>>(null, ServiceContext.DataTypeService, new SaveEventArgs<IDataTypeDefinition>(Enumerable.Empty<IDataTypeDefinition>())),
new EventDefinition<IDataTypeService, DeleteEventArgs<IDataTypeDefinition>>(null, ServiceContext.DataTypeService, new DeleteEventArgs<IDataTypeDefinition>(Enumerable.Empty<IDataTypeDefinition>())),
new EventDefinition<IFileService, SaveEventArgs<Stylesheet>>(null, ServiceContext.FileService, new SaveEventArgs<Stylesheet>((Stylesheet) null)),
new EventDefinition<IFileService, DeleteEventArgs<Stylesheet>>(null, ServiceContext.FileService, new DeleteEventArgs<Stylesheet>((Stylesheet) null)),
new EventDefinition<IFileService, SaveEventArgs<Stylesheet>>(null, ServiceContext.FileService, new SaveEventArgs<Stylesheet>(Enumerable.Empty<Stylesheet>())),
new EventDefinition<IFileService, DeleteEventArgs<Stylesheet>>(null, ServiceContext.FileService, new DeleteEventArgs<Stylesheet>(Enumerable.Empty<Stylesheet>())),
new EventDefinition<IDomainService, SaveEventArgs<IDomain>>(null, ServiceContext.DomainService, new SaveEventArgs<IDomain>((IDomain) null)),
new EventDefinition<IDomainService, DeleteEventArgs<IDomain>>(null, ServiceContext.DomainService, new DeleteEventArgs<IDomain>((IDomain) null)),
new EventDefinition<IDomainService, SaveEventArgs<IDomain>>(null, ServiceContext.DomainService, new SaveEventArgs<IDomain>(Enumerable.Empty<IDomain>())),
new EventDefinition<IDomainService, DeleteEventArgs<IDomain>>(null, ServiceContext.DomainService, new DeleteEventArgs<IDomain>(Enumerable.Empty<IDomain>())),
new EventDefinition<ILocalizationService, SaveEventArgs<ILanguage>>(null, ServiceContext.LocalizationService, new SaveEventArgs<ILanguage>((ILanguage) null)),
new EventDefinition<ILocalizationService, DeleteEventArgs<ILanguage>>(null, ServiceContext.LocalizationService, new DeleteEventArgs<ILanguage>((ILanguage) null)),
new EventDefinition<ILocalizationService, SaveEventArgs<ILanguage>>(null, ServiceContext.LocalizationService, new SaveEventArgs<ILanguage>(Enumerable.Empty<ILanguage>())),
new EventDefinition<ILocalizationService, DeleteEventArgs<ILanguage>>(null, ServiceContext.LocalizationService, new DeleteEventArgs<ILanguage>(Enumerable.Empty<ILanguage>())),
new EventDefinition<IContentTypeService, SaveEventArgs<IContentType>>(null, ServiceContext.ContentTypeService, new SaveEventArgs<IContentType>((IContentType) null)),
new EventDefinition<IContentTypeService, DeleteEventArgs<IContentType>>(null, ServiceContext.ContentTypeService, new DeleteEventArgs<IContentType>((IContentType) null)),
new EventDefinition<IContentTypeService, SaveEventArgs<IMediaType>>(null, ServiceContext.ContentTypeService, new SaveEventArgs<IMediaType>((IMediaType) null)),
new EventDefinition<IContentTypeService, DeleteEventArgs<IMediaType>>(null, ServiceContext.ContentTypeService, new DeleteEventArgs<IMediaType>((IMediaType) null)),
new EventDefinition<IContentTypeService, SaveEventArgs<IContentType>>(null, ServiceContext.ContentTypeService, new SaveEventArgs<IContentType>(Enumerable.Empty<IContentType>())),
new EventDefinition<IContentTypeService, DeleteEventArgs<IContentType>>(null, ServiceContext.ContentTypeService, new DeleteEventArgs<IContentType>(Enumerable.Empty<IContentType>())),
new EventDefinition<IContentTypeService, SaveEventArgs<IMediaType>>(null, ServiceContext.ContentTypeService, new SaveEventArgs<IMediaType>(Enumerable.Empty<IMediaType>())),
new EventDefinition<IContentTypeService, DeleteEventArgs<IMediaType>>(null, ServiceContext.ContentTypeService, new DeleteEventArgs<IMediaType>(Enumerable.Empty<IMediaType>())),
new EventDefinition<IMemberTypeService, SaveEventArgs<IMemberType>>(null, ServiceContext.MemberTypeService, new SaveEventArgs<IMemberType>((IMemberType) null)),
new EventDefinition<IMemberTypeService, DeleteEventArgs<IMemberType>>(null, ServiceContext.MemberTypeService, new DeleteEventArgs<IMemberType>((IMemberType) null)),
new EventDefinition<IMemberTypeService, SaveEventArgs<IMemberType>>(null, ServiceContext.MemberTypeService, new SaveEventArgs<IMemberType>(Enumerable.Empty<IMemberType>())),
new EventDefinition<IMemberTypeService, DeleteEventArgs<IMemberType>>(null, ServiceContext.MemberTypeService, new DeleteEventArgs<IMemberType>(Enumerable.Empty<IMemberType>())),
new EventDefinition<IFileService, SaveEventArgs<ITemplate>>(null, ServiceContext.FileService, new SaveEventArgs<ITemplate>((ITemplate) null)),
new EventDefinition<IFileService, DeleteEventArgs<ITemplate>>(null, ServiceContext.FileService, new DeleteEventArgs<ITemplate>((ITemplate) null)),
new EventDefinition<IFileService, SaveEventArgs<ITemplate>>(null, ServiceContext.FileService, new SaveEventArgs<ITemplate>(Enumerable.Empty<ITemplate>())),
new EventDefinition<IFileService, DeleteEventArgs<ITemplate>>(null, ServiceContext.FileService, new DeleteEventArgs<ITemplate>(Enumerable.Empty<ITemplate>())),
new EventDefinition<IMacroService, SaveEventArgs<IMacro>>(null, ServiceContext.MacroService, new SaveEventArgs<IMacro>((IMacro) null)),
new EventDefinition<IMacroService, DeleteEventArgs<IMacro>>(null, ServiceContext.MacroService, new DeleteEventArgs<IMacro>((IMacro) null)),
new EventDefinition<IMacroService, SaveEventArgs<IMacro>>(null, ServiceContext.MacroService, new SaveEventArgs<IMacro>(Enumerable.Empty<IMacro>())),
new EventDefinition<IMacroService, DeleteEventArgs<IMacro>>(null, ServiceContext.MacroService, new DeleteEventArgs<IMacro>(Enumerable.Empty<IMacro>())),
new EventDefinition<IMemberService, SaveEventArgs<IMember>>(null, ServiceContext.MemberService, new SaveEventArgs<IMember>((IMember) null)),
new EventDefinition<IMemberService, DeleteEventArgs<IMember>>(null, ServiceContext.MemberService, new DeleteEventArgs<IMember>((IMember) null)),
new EventDefinition<IMemberService, SaveEventArgs<IMember>>(null, ServiceContext.MemberService, new SaveEventArgs<IMember>(Enumerable.Empty<IMember>())),
new EventDefinition<IMemberService, DeleteEventArgs<IMember>>(null, ServiceContext.MemberService, new DeleteEventArgs<IMember>(Enumerable.Empty<IMember>())),
new EventDefinition<IMemberGroupService, SaveEventArgs<IMemberGroup>>(null, ServiceContext.MemberGroupService, new SaveEventArgs<IMemberGroup>((IMemberGroup) null)),
new EventDefinition<IMemberGroupService, DeleteEventArgs<IMemberGroup>>(null, ServiceContext.MemberGroupService, new DeleteEventArgs<IMemberGroup>((IMemberGroup) null)),
new EventDefinition<IMemberGroupService, SaveEventArgs<IMemberGroup>>(null, ServiceContext.MemberGroupService, new SaveEventArgs<IMemberGroup>(Enumerable.Empty<IMemberGroup>())),
new EventDefinition<IMemberGroupService, DeleteEventArgs<IMemberGroup>>(null, ServiceContext.MemberGroupService, new DeleteEventArgs<IMemberGroup>(Enumerable.Empty<IMemberGroup>())),
new EventDefinition<IMediaService, SaveEventArgs<IMedia>>(null, ServiceContext.MediaService, new SaveEventArgs<IMedia>((IMedia) null)),
new EventDefinition<IMediaService, DeleteEventArgs<IMedia>>(null, ServiceContext.MediaService, new DeleteEventArgs<IMedia>((IMedia) null)),
new EventDefinition<IMediaService, SaveEventArgs<IMedia>>(null, ServiceContext.MediaService, new SaveEventArgs<IMedia>(Enumerable.Empty<IMedia>())),
new EventDefinition<IMediaService, DeleteEventArgs<IMedia>>(null, ServiceContext.MediaService, new DeleteEventArgs<IMedia>(Enumerable.Empty<IMedia>())),
new EventDefinition<IMediaService, MoveEventArgs<IMedia>>(null, ServiceContext.MediaService, new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(null, "", -1)), "Moved"),
new EventDefinition<IMediaService, MoveEventArgs<IMedia>>(null, ServiceContext.MediaService, new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(null, "", -1)), "Trashed"),
new EventDefinition<IMediaService, RecycleBinEventArgs>(null, ServiceContext.MediaService, new RecycleBinEventArgs(Guid.NewGuid(), new Dictionary<int, IEnumerable<Property>>(), true)),
new EventDefinition<IContentService, SaveEventArgs<IContent>>(null, ServiceContext.ContentService, new SaveEventArgs<IContent>((IContent) null)),
new EventDefinition<IContentService, DeleteEventArgs<IContent>>(null, ServiceContext.ContentService, new DeleteEventArgs<IContent>((IContent) null)),
new EventDefinition<IContentService, SaveEventArgs<IContent>>(null, ServiceContext.ContentService, new SaveEventArgs<IContent>(Enumerable.Empty<IContent>())),
new EventDefinition<IContentService, DeleteEventArgs<IContent>>(null, ServiceContext.ContentService, new DeleteEventArgs<IContent>(Enumerable.Empty<IContent>())),
new EventDefinition<IContentService, CopyEventArgs<IContent>>(null, ServiceContext.ContentService, new CopyEventArgs<IContent>(null, null, -1)),
new EventDefinition<IContentService, MoveEventArgs<IContent>>(null, ServiceContext.ContentService, new MoveEventArgs<IContent>(new MoveEventInfo<IContent>(null, "", -1)), "Trashed"),
new EventDefinition<IContentService, RecycleBinEventArgs>(null, ServiceContext.ContentService, new RecycleBinEventArgs(Guid.NewGuid(), new Dictionary<int, IEnumerable<Property>>(), true)),
new EventDefinition<IContentService, PublishEventArgs<IContent>>(null, ServiceContext.ContentService, new PublishEventArgs<IContent>((IContent) null), "Published"),
new EventDefinition<IContentService, PublishEventArgs<IContent>>(null, ServiceContext.ContentService, new PublishEventArgs<IContent>((IContent) null), "UnPublished"),
new EventDefinition<IContentService, PublishEventArgs<IContent>>(null, ServiceContext.ContentService, new PublishEventArgs<IContent>(Enumerable.Empty<IContent>()), "Published"),
new EventDefinition<IContentService, PublishEventArgs<IContent>>(null, ServiceContext.ContentService, new PublishEventArgs<IContent>(Enumerable.Empty<IContent>()), "UnPublished"),
new EventDefinition<IPublicAccessService, SaveEventArgs<PublicAccessEntry>>(null, ServiceContext.PublicAccessService, new SaveEventArgs<PublicAccessEntry>((PublicAccessEntry) null)),
new EventDefinition<IPublicAccessService, DeleteEventArgs<PublicAccessEntry>>(null, ServiceContext.PublicAccessService, new DeleteEventArgs<PublicAccessEntry>((PublicAccessEntry) null)),
new EventDefinition<IPublicAccessService, SaveEventArgs<PublicAccessEntry>>(null, ServiceContext.PublicAccessService, new SaveEventArgs<PublicAccessEntry>(Enumerable.Empty<PublicAccessEntry>())),
new EventDefinition<IPublicAccessService, DeleteEventArgs<PublicAccessEntry>>(null, ServiceContext.PublicAccessService, new DeleteEventArgs<PublicAccessEntry>(Enumerable.Empty<PublicAccessEntry>())),
new EventDefinition<IRelationService, SaveEventArgs<IRelationType>>(null, ServiceContext.RelationService, new SaveEventArgs<IRelationType>((IRelationType) null)),
new EventDefinition<IRelationService, DeleteEventArgs<IRelationType>>(null, ServiceContext.RelationService, new DeleteEventArgs<IRelationType>((IRelationType) null)),
new EventDefinition<IRelationService, SaveEventArgs<IRelationType>>(null, ServiceContext.RelationService, new SaveEventArgs<IRelationType>(Enumerable.Empty<IRelationType>())),
new EventDefinition<IRelationService, DeleteEventArgs<IRelationType>>(null, ServiceContext.RelationService, new DeleteEventArgs<IRelationType>(Enumerable.Empty<IRelationType>())),
new EventDefinition<IRelationService, SaveEventArgs<IRelationType>>(null, ServiceContext.RelationService, new SaveEventArgs<IRelationType>((IRelationType) null)),
new EventDefinition<IRelationService, DeleteEventArgs<IRelationType>>(null, ServiceContext.RelationService, new DeleteEventArgs<IRelationType>((IRelationType) null)),
new EventDefinition<IRelationService, SaveEventArgs<IRelationType>>(null, ServiceContext.RelationService, new SaveEventArgs<IRelationType>(Enumerable.Empty<IRelationType>())),
new EventDefinition<IRelationService, DeleteEventArgs<IRelationType>>(null, ServiceContext.RelationService, new DeleteEventArgs<IRelationType>(Enumerable.Empty<IRelationType>())),
};
foreach (var definition in definitions)
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
@@ -177,6 +178,39 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings
public void DisallowedUploadFiles()
{
Assert.IsTrue(SettingsSection.Content.DisallowedUploadFiles.All(x => "ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd".Split(',').Contains(x)));
}
[Test]
public void AllowedUploadFiles()
{
Assert.IsTrue(SettingsSection.Content.AllowedUploadFiles.All(x => "jpg,gif,png".Split(',').Contains(x)));
}
[Test]
[TestCase("png", true)]
[TestCase("jpg", true)]
[TestCase("gif", true)]
// TODO: Why does it flip to TestingDefaults=true for these two tests on AppVeyor. WHY?
//[TestCase("bmp", false)]
//[TestCase("php", false)]
[TestCase("ashx", false)]
[TestCase("config", false)]
public void IsFileAllowedForUpload_WithWhitelist(string extension, bool expected)
{
// Make really sure that defaults are NOT used
TestingDefaults = false;
Debug.WriteLine("Extension being tested", extension);
Debug.WriteLine("AllowedUploadFiles: {0}", SettingsSection.Content.AllowedUploadFiles);
Debug.WriteLine("DisallowedUploadFiles: {0}", SettingsSection.Content.DisallowedUploadFiles);
var allowedContainsExtension = SettingsSection.Content.AllowedUploadFiles.Any(x => x.InvariantEquals(extension));
var disallowedContainsExtension = SettingsSection.Content.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension));
Debug.WriteLine("AllowedContainsExtension: {0}", allowedContainsExtension);
Debug.WriteLine("DisallowedContainsExtension: {0}", disallowedContainsExtension);
Assert.AreEqual(SettingsSection.Content.IsFileAllowedForUpload(extension), expected);
}
}
}
@@ -1,7 +1,7 @@
using System.Configuration;
using System.Diagnostics;
using System.IO;
using NUnit.Framework;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Tests.TestHelpers;
@@ -9,20 +9,17 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings
{
public abstract class UmbracoSettingsTests
{
protected virtual bool TestingDefaults
{
get { return false; }
}
protected virtual bool TestingDefaults { get; set; }
[SetUp]
public void Init()
{
var config = new FileInfo(TestHelper.MapPathForTest("~/Configurations/UmbracoSettings/web.config"));
var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = config.FullName };
var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = config.FullName };
var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Debug.WriteLine("Testing defaults? {0}", TestingDefaults);
if (TestingDefaults)
{
SettingsSection = configuration.GetSection("umbracoConfiguration/defaultSettings") as UmbracoSettingsSection;
@@ -32,8 +29,6 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings
SettingsSection = configuration.GetSection("umbracoConfiguration/settings") as UmbracoSettingsSection;
}
Assert.IsNotNull(SettingsSection);
}
@@ -100,6 +100,9 @@
<!-- These file types will not be allowed to be uploaded via the upload control for media and content -->
<disallowedUploadFiles>ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd</disallowedUploadFiles>
<!-- If completed, only the file extensions listed below will be allowed to be uploaded. If empty, disallowedUploadFiles will apply to prevent upload of specific file extensions. -->
<allowedUploadFiles>jpg,png,gif</allowedUploadFiles>
<!-- Defines the default document type property used when adding properties in the back-office (if missing or empty, defaults to Textstring -->
<defaultDocumentTypeProperty>Textstring</defaultDocumentTypeProperty>
</content>
@@ -37,14 +37,14 @@ namespace Umbraco.Tests.Persistence.Repositories
var unitOfWork = provider.GetUnitOfWork();
var repository = new PartialViewRepository(unitOfWork, _fileSystem);
var partialView = new PartialView("test-path-1.cshtml") { Content = "// partialView" };
var partialView = new PartialView(PartialViewType.PartialView, "test-path-1.cshtml") { Content = "// partialView" };
repository.AddOrUpdate(partialView);
unitOfWork.Commit();
Assert.IsTrue(_fileSystem.FileExists("test-path-1.cshtml"));
Assert.AreEqual("test-path-1.cshtml", partialView.Path);
Assert.AreEqual("/Views/Partials/test-path-1.cshtml", partialView.VirtualPath);
partialView = new PartialView("path-2/test-path-2.cshtml") { Content = "// partialView" };
partialView = new PartialView(PartialViewType.PartialView, "path-2/test-path-2.cshtml") { Content = "// partialView" };
repository.AddOrUpdate(partialView);
unitOfWork.Commit();
Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-2.cshtml"));
@@ -56,7 +56,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.AreEqual("path-2\\test-path-2.cshtml", partialView.Path);
Assert.AreEqual("/Views/Partials/path-2/test-path-2.cshtml", partialView.VirtualPath);
partialView = new PartialView("path-2\\test-path-3.cshtml") { Content = "// partialView" };
partialView = new PartialView(PartialViewType.PartialView, "path-2\\test-path-3.cshtml") { Content = "// partialView" };
repository.AddOrUpdate(partialView);
unitOfWork.Commit();
Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-3.cshtml"));
@@ -73,7 +73,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.AreEqual("path-2\\test-path-3.cshtml", partialView.Path);
Assert.AreEqual("/Views/Partials/path-2/test-path-3.cshtml", partialView.VirtualPath);
partialView = new PartialView("\\test-path-4.cshtml") { Content = "// partialView" };
partialView = new PartialView(PartialViewType.PartialView, "\\test-path-4.cshtml") { Content = "// partialView" };
Assert.Throws<FileSecurityException>(() => // fixed in 7.3 - 7.2.8 used to strip the \
{
repository.AddOrUpdate(partialView);
@@ -4,13 +4,16 @@ using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
namespace Umbraco.Tests.Scoping
{
[TestFixture]
public class ScopeEventDispatcherTests
public class ScopeEventDispatcherTests : BaseUmbracoConfigurationTest
{
[SetUp]
public void Setup()
@@ -79,7 +82,7 @@ namespace Umbraco.Tests.Scoping
var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray();
var knownNames = new[] { "DoThing1", "DoThing2", "DoThing3" };
var knownArgTypes = new[] { typeof (SaveEventArgs<string>), typeof (SaveEventArgs<int>), typeof (SaveEventArgs<decimal>) };
var knownArgTypes = new[] { typeof(SaveEventArgs<string>), typeof(SaveEventArgs<int>), typeof(SaveEventArgs<decimal>) };
for (var i = 0; i < events.Length; i++)
{
@@ -89,6 +92,166 @@ namespace Umbraco.Tests.Scoping
}
}
[Test]
public void SupersededEvents()
{
DoSaveForContent += OnDoThingFail;
DoDeleteForContent += OnDoThingFail;
DoForTestArgs += OnDoThingFail;
DoForTestArgs2 += OnDoThingFail;
var contentType = MockedContentTypes.CreateBasicContentType();
var content1 = MockedContent.CreateBasicContent(contentType);
content1.Id = 123;
var content2 = MockedContent.CreateBasicContent(contentType);
content2.Id = 456;
var content3 = MockedContent.CreateBasicContent(contentType);
content3.Id = 789;
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
//content1 will be filtered from the args
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(new[]{ content1 , content3}));
scope.Events.Dispatch(DoDeleteForContent, this, new DeleteEventArgs<IContent>(content1));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
//this entire event will be filtered
scope.Events.Dispatch(DoForTestArgs, this, new TestEventArgs(content1));
scope.Events.Dispatch(DoForTestArgs2, this, new TestEventArgs2(content1));
// events have been queued
var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray();
Assert.AreEqual(4, events.Length);
Assert.AreEqual(typeof(SaveEventArgs<IContent>), events[0].Args.GetType());
Assert.AreEqual(1, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.Count());
Assert.AreEqual(content3.Id, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First().Id);
Assert.AreEqual(typeof(DeleteEventArgs<IContent>), events[1].Args.GetType());
Assert.AreEqual(content1.Id, ((DeleteEventArgs<IContent>) events[1].Args).DeletedEntities.First().Id);
Assert.AreEqual(typeof(SaveEventArgs<IContent>), events[2].Args.GetType());
Assert.AreEqual(content2.Id, ((SaveEventArgs<IContent>)events[2].Args).SavedEntities.First().Id);
Assert.AreEqual(typeof(TestEventArgs2), events[3].Args.GetType());
}
}
/// <summary>
/// This will test that when we track events that before we Get the events we normalize all of the
/// event entities to be the latest one (most current) found amongst the event so that there is
/// no 'stale' entities in any of the args
/// </summary>
[Test]
public void LatestEntities()
{
DoSaveForContent += OnDoThingFail;
var now = DateTime.Now;
var contentType = MockedContentTypes.CreateBasicContentType();
var content1 = MockedContent.CreateBasicContent(contentType);
content1.Id = 123;
content1.UpdateDate = now.AddMinutes(1);
var content2 = MockedContent.CreateBasicContent(contentType);
content2.Id = 123;
content2.UpdateDate = now.AddMinutes(2);
var content3 = MockedContent.CreateBasicContent(contentType);
content3.Id = 123;
content3.UpdateDate = now.AddMinutes(3);
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content1));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content3));
// events have been queued
var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray();
Assert.AreEqual(3, events.Length);
foreach (var t in events)
{
var args = (SaveEventArgs<IContent>)t.Args;
foreach (var entity in args.SavedEntities)
{
Assert.AreEqual(content3, entity);
Assert.IsTrue(object.ReferenceEquals(content3, entity));
}
}
}
}
[Test]
public void FirstIn()
{
DoSaveForContent += OnDoThingFail;
var now = DateTime.Now;
var contentType = MockedContentTypes.CreateBasicContentType();
var content1 = MockedContent.CreateBasicContent(contentType);
content1.Id = 123;
content1.UpdateDate = now.AddMinutes(1);
var content2 = MockedContent.CreateBasicContent(contentType);
content2.Id = 123;
content1.UpdateDate = now.AddMinutes(2);
var content3 = MockedContent.CreateBasicContent(contentType);
content3.Id = 123;
content1.UpdateDate = now.AddMinutes(3);
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content1));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content3));
// events have been queued
var events = scope.Events.GetEvents(EventDefinitionFilter.FirstIn).ToArray();
Assert.AreEqual(1, events.Length);
Assert.AreEqual(content1, ((SaveEventArgs<IContent>) events[0].Args).SavedEntities.First());
Assert.IsTrue(object.ReferenceEquals(content1, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First()));
Assert.AreEqual(content1.UpdateDate, ((SaveEventArgs<IContent>) events[0].Args).SavedEntities.First().UpdateDate);
}
}
[Test]
public void LastIn()
{
DoSaveForContent += OnDoThingFail;
var now = DateTime.Now;
var contentType = MockedContentTypes.CreateBasicContentType();
var content1 = MockedContent.CreateBasicContent(contentType);
content1.Id = 123;
content1.UpdateDate = now.AddMinutes(1);
var content2 = MockedContent.CreateBasicContent(contentType);
content2.Id = 123;
content2.UpdateDate = now.AddMinutes(2);
var content3 = MockedContent.CreateBasicContent(contentType);
content3.Id = 123;
content3.UpdateDate = now.AddMinutes(3);
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content1));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content3));
// events have been queued
var events = scope.Events.GetEvents(EventDefinitionFilter.LastIn).ToArray();
Assert.AreEqual(1, events.Length);
Assert.AreEqual(content3, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First());
Assert.IsTrue(object.ReferenceEquals(content3, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First()));
Assert.AreEqual(content3.UpdateDate, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First().UpdateDate);
}
}
[TestCase(true)]
[TestCase(false)]
public void EventsDispatching_Passive(bool complete)
@@ -177,12 +340,41 @@ namespace Umbraco.Tests.Scoping
Assert.Fail();
}
public static event EventHandler<SaveEventArgs<IContent>> DoSaveForContent;
public static event EventHandler<DeleteEventArgs<IContent>> DoDeleteForContent;
public static event EventHandler<TestEventArgs> DoForTestArgs;
public static event EventHandler<TestEventArgs2> DoForTestArgs2;
public static event EventHandler<SaveEventArgs<string>> DoThing1;
public static event EventHandler<SaveEventArgs<int>> DoThing2;
public static event TypedEventHandler<ScopeEventDispatcherTests, SaveEventArgs<decimal>> DoThing3;
public class TestEventArgs : CancellableObjectEventArgs
{
public TestEventArgs(object eventObject) : base(eventObject)
{
}
public object MyEventObject
{
get { return EventObject; }
}
}
[SupersedeEvent(typeof(TestEventArgs))]
public class TestEventArgs2 : CancellableObjectEventArgs
{
public TestEventArgs2(object eventObject) : base(eventObject)
{
}
public object MyEventObject
{
get { return EventObject; }
}
}
public class PassiveEventDispatcher : ScopeEventDispatcherBase
{
public PassiveEventDispatcher()
+39 -1
View File
@@ -591,7 +591,7 @@ namespace Umbraco.Tests.Scoping
Assert.IsNull(scopeProvider.AmbientContext);
// back to original thread
ScopeProvider.HttpContextItemsGetter = () => httpContextItems;
ScopeProvider.HttpContextItemsGetter = () => httpContextItems;
}
Assert.IsNotNull(scopeProvider.AmbientScope);
Assert.AreSame(scope, scopeProvider.AmbientScope);
@@ -656,6 +656,44 @@ namespace Umbraco.Tests.Scoping
Assert.IsNotNull(ambientContext); // the context is still there
}
[TestCase(true)]
[TestCase(false)]
public void ScopeContextEnlistAgain(bool complete)
{
var scopeProvider = DatabaseContext.ScopeProvider;
bool? completed = null;
Exception exception = null;
Assert.IsNull(scopeProvider.AmbientScope);
using (var scope = scopeProvider.CreateScope())
{
scopeProvider.Context.Enlist("name", c =>
{
completed = c;
// at that point the scope is gone, but the context is still there
var ambientContext = scopeProvider.AmbientContext;
try
{
ambientContext.Enlist("another", c2 => { });
}
catch (Exception e)
{
exception = e;
}
});
if (complete)
scope.Complete();
}
Assert.IsNull(scopeProvider.AmbientScope);
Assert.IsNull(scopeProvider.AmbientContext);
Assert.IsNotNull(completed);
Assert.IsNotNull(exception);
Assert.IsInstanceOf<InvalidOperationException>(exception);
}
[Test]
public void ScopeContextException()
{
+3 -1
View File
@@ -179,7 +179,9 @@ namespace Umbraco.Tests.Scoping
scope.Complete();
}
Assert.AreEqual(complete ? 2 : 0, evented);
//The reason why there is only 1 event occuring is because we are publishing twice for the same event for the same
//object and the scope deduplicates the events (uses the latest)
Assert.AreEqual(complete ? 1 : 0, evented);
// this should never change
Assert.AreEqual(beforeOuterXml, beforeXml.OuterXml);
+51
View File
@@ -31,6 +31,57 @@ namespace Umbraco.Tests
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/test-id", udi.ToString());
}
[Test]
public void StringEncodingTest()
{
// absolute path is unescaped
var uri = new Uri("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test");
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/this is a test", uri.ToString());
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test", uri.AbsoluteUri);
Assert.AreEqual("/this%20is%20a%20test", uri.AbsolutePath);
Assert.AreEqual("/this is a test", Uri.UnescapeDataString(uri.AbsolutePath));
Assert.AreEqual("%2Fthis%20is%20a%20test", Uri.EscapeDataString("/this is a test"));
Assert.AreEqual("/this%20is%20a%20test", Uri.EscapeUriString("/this is a test"));
var udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test");
Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType);
Assert.IsInstanceOf<StringUdi>(udi);
var stringEntityId = udi as StringUdi;
Assert.IsNotNull(stringEntityId);
Assert.AreEqual("this is a test", stringEntityId.Id);
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test", udi.ToString());
var udi2 = new StringUdi(Constants.UdiEntityType.AnyString, "this is a test");
Assert.AreEqual(udi, udi2);
var udi3 = new StringUdi(Constants.UdiEntityType.AnyString, "path to/this is a test.xyz");
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/path%20to/this%20is%20a%20test.xyz", udi3.ToString());
}
[Test, Ignore]
public void StringEncodingTest2()
{
// reserved = : / ? # [ ] @ ! $ & ' ( ) * + , ; =
// unreserved = alpha digit - . _ ~
Assert.AreEqual("%3A%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2B%2C%3B%3D.-_~%25", Uri.EscapeDataString(":/?#[]@!$&'()+,;=.-_~%"));
Assert.AreEqual(":/?#[]@!$&'()+,;=.-_~%25", Uri.EscapeUriString(":/?#[]@!$&'()+,;=.-_~%"));
// we cannot have reserved chars at random places
// we want to keep the / in string udis
var r = string.Join("/", "path/to/View[1].cshtml".Split('/').Select(Uri.EscapeDataString));
Assert.AreEqual("path/to/View%5B1%5D.cshtml", r);
Assert.IsTrue(Uri.IsWellFormedUriString("umb://partial-view-macro/" + r, UriKind.Absolute));
// with the proper fix in StringUdi this should work:
var udi1 = new StringUdi("partial-view-macro", "path/to/View[1].cshtml");
Assert.AreEqual("umb://partial-view-macro/path/to/View%5B1%5D.cshtml", udi1.ToString());
var udi2 = Udi.Parse("umb://partial-view-macro/path/to/View%5B1%5D.cshtml");
Assert.AreEqual("path/to/View[1].cshtml", ((StringUdi) udi2).Id);
}
[Test]
public void GuidEntityCtorTest()
{
+2 -3
View File
@@ -97,9 +97,8 @@
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="Semver, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Semver.2.0.4\lib\netstandard1.1\Semver.dll</HintPath>
<Private>True</Private>
<Reference Include="Semver, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\semver.1.1.2\lib\net45\Semver.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
+2 -1
View File
@@ -21,9 +21,10 @@
<package id="Moq" version="4.1.1309.0919" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
<package id="NUnit" version="2.6.2" targetFramework="net45" />
<package id="NUnitTestAdapter" version="2.1.1" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="Selenium.WebDriver" version="2.32.0" targetFramework="net45" />
<package id="Semver" version="2.0.4" targetFramework="net45" />
<package id="semver" version="1.1.2" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
<package id="System.Runtime" version="4.3.0" targetFramework="net45" />
@@ -105,14 +105,14 @@ angular.module("umbraco.directives")
});
//// INIT /////
$image.load(function(){
$timeout(function(){
setDimensions();
scope.loaded = true;
if (scope.onImageLoaded) {
scope.onImageLoaded();
}
});
$image.load(function() {
$timeout(function() {
setDimensions();
scope.loaded = true;
if (angular.isFunction(scope.onImageLoaded)) {
scope.onImageLoaded();
}
});
});
$(window).on('resize.umbImageGravity', function(){
@@ -134,25 +134,42 @@ Use this directive to generate a thumbnail grid of media items.
}
function setItemData(item) {
item.isFolder = !mediaHelper.hasFilePropertyType(item);
// check if item is a folder
if(item.image) {
// if is has an image path, it is not a folder
item.isFolder = false;
} else {
item.isFolder = !mediaHelper.hasFilePropertyType(item);
}
if (!item.isFolder) {
item.thumbnail = mediaHelper.resolveFile(item, true);
item.image = mediaHelper.resolveFile(item, false);
// handle entity
if(item.image) {
item.thumbnail = mediaHelper.resolveFileFromEntity(item, true);
item.extension = mediaHelper.getFileExtension(item.image);
// handle full media object
} else {
item.thumbnail = mediaHelper.resolveFile(item, true);
item.image = mediaHelper.resolveFile(item, false);
var fileProp = _.find(item.properties, function (v) {
return (v.alias === "umbracoFile");
});
var fileProp = _.find(item.properties, function (v) {
return (v.alias === "umbracoFile");
});
if (fileProp && fileProp.value) {
item.file = fileProp.value;
}
if (fileProp && fileProp.value) {
item.file = fileProp.value;
}
var extensionProp = _.find(item.properties, function (v) {
return (v.alias === "umbracoExtension");
});
var extensionProp = _.find(item.properties, function (v) {
return (v.alias === "umbracoExtension");
});
if (extensionProp && extensionProp.value) {
item.extension = extensionProp.value;
}
if (extensionProp && extensionProp.value) {
item.extension = extensionProp.value;
}
}
}
@@ -68,7 +68,7 @@ function logResource($q, $http, umbRequestHelper) {
"logApiBaseUrl",
"GetCurrentUserLog",
[{ logtype: type, sinceDate: since }])),
'Failed to retrieve user data for id ' + id);
'Failed to retrieve log data for current user of type ' + type + ' since ' + since);
},
/**
@@ -99,7 +99,7 @@ function logResource($q, $http, umbRequestHelper) {
"logApiBaseUrl",
"GetLog",
[{ logtype: type, sinceDate: since }])),
'Failed to retrieve user data for id ' + id);
'Failed to retrieve log data of type ' + type + ' since ' + since);
}
};
}
@@ -5,15 +5,14 @@
**/
function ourPackageRepositoryResource($q, $http, umbDataFormatter, umbRequestHelper) {
//var baseurl = "http://localhost:24292/webapi/packages/v1";
var baseurl = "https://our.umbraco.org/webapi/packages/v1";
var baseurl = Umbraco.Sys.ServerVariables.umbracoUrls.packagesRestApiBaseUrl;
return {
getDetails: function (packageId) {
return umbRequestHelper.resourcePromise(
$http.get(baseurl + "/" + packageId),
$http.get(baseurl + "/" + packageId + "?version=" + Umbraco.Sys.ServerVariables.application.version),
'Failed to get package details');
},
@@ -365,6 +365,28 @@ function mediaHelper(umbRequestHelper) {
return newFileTypesArray.join(",");
},
/**
* @ngdoc function
* @name umbraco.services.mediaHelper#getFileExtension
* @methodOf umbraco.services.mediaHelper
* @function
*
* @description
* Returns file extension
*
* @param {string} filePath File path, ex /media/1234/my-image.jpg
*/
getFileExtension: function(filePath) {
if (!filePath) {
return false;
}
var lowered = filePath.toLowerCase();
var ext = lowered.substr(lowered.lastIndexOf(".") + 1);
return ext;
}
};
@@ -103,15 +103,15 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
* @description
* This returns a promise with an underlying http call, it is a helper method to reduce
* the amount of duplicate code needed to query http resources and automatically handle any
* 500 Http server errors.
* Http errors. See /docs/source/using-promises-resources.md
*
* @param {object} opts A mixed object which can either be a `string` representing the error message to be
* returned OR an `object` containing either:
* @param {object} opts A mixed object which can either be a string representing the error message to be
* returned OR an object containing either:
* { success: successCallback, errorMsg: errorMessage }
* OR
* { success: successCallback, error: errorCallback }
* In both of the above, the successCallback must accept these parameters: `data`, `status`, `headers`, `config`
* If using the errorCallback it must accept these parameters: `data`, `status`, `headers`, `config`
* In both of the above, the successCallback must accept these parameters: data, status, headers, config
* If using the errorCallback it must accept these parameters: data, status, headers, config
* The success callback must return the data which will be resolved by the deferred object.
* The error callback must return an object containing: {errorMsg: errorMessage, data: originalData, status: status }
*/
@@ -5,7 +5,7 @@
</p>
<p>
To read a report of changes between your current version <strong>{{installer.current.model.currentVersion}}</strong> and this version your upgrading to <strong>{{installer.current.model.newVersion}}</strong>
To read a report of changes between your current version <strong>{{installer.current.model.currentVersion}}</strong> and this version you're upgrading to <strong>{{installer.current.model.newVersion}}</strong>
</p>
<p>
<a ng-href="{{installer.current.model.reportUrl}}" target="_blank" class="btn btn-info">View Report</a>
+1 -1
View File
@@ -49,7 +49,7 @@
.umb-tree li.current > div i.icon,
.umb-tree li.current > div ins {
color: @white !important;
background: @turquoise-d1;
background-color: @turquoise-d1;
border-color: @turquoise-d1;
}
@@ -50,7 +50,7 @@
<div class="control-group" ng-class="{error: loginForm.username.$invalid}">
<label><localize key="general_username">Username</localize></label>
<input type="text" ng-model="login" name="username" class="-full-width-input" localize="placeholder" placeholder="@placeholders_username" />
<input type="text" ng-model="login" name="username" class="-full-width-input" localize="placeholder" placeholder="@placeholders_usernameHint" />
</div>
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
@@ -6,7 +6,8 @@
placeholder="@general_url"
class="umb-editor umb-textstring"
ng-model="model.target.url"
ng-disabled="model.target.id"/>
ng-disabled="model.target.id"
focus-when="{{true}} "/>
</umb-control-group>
<umb-control-group label="@content_nodeName">
@@ -16,14 +16,22 @@ angular.module("umbraco")
$scope.startNodeId = dialogOptions.startNodeId ? dialogOptions.startNodeId : -1;
$scope.cropSize = dialogOptions.cropSize;
$scope.lastOpenedNode = localStorageService.get("umbLastOpenedMediaNodeId");
var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings;
var allowedUploadFiles = mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles);
if ($scope.onlyImages) {
$scope.acceptedFileTypes = mediaHelper
.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes);
$scope.acceptedFileTypes = mediaHelper.formatFileTypes(umbracoSettings.imageFileTypes);
} else {
$scope.acceptedFileTypes = !mediaHelper
.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles);
// Use whitelist of allowed file types if provided
if (allowedUploadFiles !== '') {
$scope.acceptedFileTypes = allowedUploadFiles;
} else {
// If no whitelist, we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles
$scope.acceptedFileTypes = !mediaHelper.formatFileTypes(umbracoSettings.disallowedUploadFiles);
}
}
$scope.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB";
$scope.maxFileSize = umbracoSettings.maxFileSize + "KB";
$scope.model.selectedImages = [];
@@ -131,8 +139,16 @@ angular.module("umbraco")
} else {
eventsService.emit("dialogs.mediaPicker.select", image);
if ($scope.showDetails) {
$scope.target = image;
$scope.target.url = mediaHelper.resolveFile(image);
// handle both entity and full media object
if(image.image) {
$scope.target.url = image.image;
} else {
$scope.target.url = mediaHelper.resolveFile(image);
}
$scope.openDetailsDialog();
} else {
selectImage(image);
@@ -1,14 +1,13 @@
(function () {
(function() {
"use strict";
function QueryBuilderOverlayController($scope, templateQueryResource, localizationService) {
var everything = localizationService.localize("template_allContent");
var myWebsite = localizationService.localize("template_websiteRoot");
var everything = "";
var myWebsite = "";
var ascendingTranslation = "";
var descendingTranslation = "";
var ascendingTranslation = localizationService.localize("template_ascending");
var descendingTranslation = localizationService.localize("template_descending");
var vm = this;
vm.properties = [];
@@ -21,34 +20,6 @@
format: "YYYY-MM-DD"
};
vm.query = {
contentType: {
name: everything
},
source: {
name: myWebsite
},
filters: [
{
property: undefined,
operator: undefined
}
],
sort: {
property: {
alias: "",
name: "",
},
direction: "ascending", //This is the value for sorting sent to server
translation: {
currentLabel: ascendingTranslation, //This is the localized UI value in the the dialog
ascending: ascendingTranslation,
descending: descendingTranslation
}
}
};
vm.chooseSource = chooseSource;
vm.getPropertyOperators = getPropertyOperators;
vm.addFilter = addFilter;
@@ -63,21 +34,48 @@
function onInit() {
vm.query = {
contentType: {
name: everything
},
source: {
name: myWebsite
},
filters: [
{
property: undefined,
operator: undefined
}
],
sort: {
property: {
alias: "",
name: "",
},
direction: "ascending", //This is the value for sorting sent to server
translation: {
currentLabel: ascendingTranslation, //This is the localized UI value in the the dialog
ascending: ascendingTranslation,
descending: descendingTranslation
}
}
};
templateQueryResource.getAllowedProperties()
.then(function (properties) {
.then(function(properties) {
vm.properties = properties;
});
templateQueryResource.getContentTypes()
.then(function (contentTypes) {
.then(function(contentTypes) {
vm.contentTypes = contentTypes;
});
templateQueryResource.getFilterConditions()
.then(function (conditions) {
.then(function(conditions) {
vm.conditions = conditions;
});
throttledFunc();
}
@@ -111,10 +109,11 @@
}
function getPropertyOperators(property) {
var conditions = _.filter(vm.conditions, function (condition) {
var index = condition.appliesTo.indexOf(property.type);
return index >= 0;
});
var conditions = _.filter(vm.conditions,
function(condition) {
var index = condition.appliesTo.indexOf(property.type);
return index >= 0;
});
return conditions;
}
@@ -123,10 +122,8 @@
}
function trashFilter(query, filter) {
for (var i = 0; i < query.filters.length; i++)
{
if (query.filters[i] == filter)
{
for (var i = 0; i < query.filters.length; i++) {
if (query.filters[i] == filter) {
query.filters.splice(i, 1);
}
}
@@ -173,7 +170,7 @@
function setFilterTerm(filter, term) {
filter.term = term;
if(filter.constraintValue) {
if (filter.constraintValue) {
throttledFunc();
}
}
@@ -183,22 +180,32 @@
}
function datePickerChange(event, filter) {
if(event.date && event.date.isValid()) {
if (event.date && event.date.isValid()) {
filter.constraintValue = event.date.format(vm.datePickerConfig.format);
throttledFunc();
}
}
var throttledFunc = _.throttle(function () {
templateQueryResource.postTemplateQuery(vm.query)
.then(function (response) {
$scope.model.result = response;
});
var throttledFunc = _.throttle(function() {
}, 200);
templateQueryResource.postTemplateQuery(vm.query)
.then(function(response) {
$scope.model.result = response;
});
onInit();
},
200);
localizationService.localizeMany([
"template_allContent", "template_websiteRoot", "template_ascending", "template_descending"
])
.then(function(res) {
everything = res[0];
myWebsite = res[1];
ascendingTranslation = res[2];
descendingTranslation = res[3];
onInit();
});
}
angular.module("umbraco").controller("Umbraco.Overlays.QueryBuilderController", QueryBuilderOverlayController);
@@ -1,5 +1,5 @@
<div class="umb-media-grid">
<div class="umb-media-grid__item" ng-click="clickItem(item, $event, $index)" ng-repeat="item in items | filter:filterBy" ng-style="item.flexStyle" ng-class="{'-selected': item.selected, '-file': !item.thumbnail, '-svg': item.extension == 'svg'}">
<div class="umb-media-grid__item" title="{{item.name}}" ng-click="clickItem(item, $event, $index)" ng-repeat="item in items | filter:filterBy" ng-style="item.flexStyle" ng-class="{'-selected': item.selected, '-file': !item.thumbnail, '-svg': item.extension == 'svg'}">
<div>
<i ng-show="item.selected" class="icon-check umb-media-grid__checkmark"></i>
@@ -12,10 +12,10 @@
<div class="umb-media-grid__image-background" ng-if="item.thumbnail || item.extension == 'svg'"></div>
<!-- Image thumbnail -->
<img class="umb-media-grid__item-image" width="{{item.width}}" height="{{item.height}}" ng-if="item.thumbnail" ng-src="{{item.thumbnail}}" alt="{{item.name}}" title="{{item.name}}" draggable="false" />
<img class="umb-media-grid__item-image" width="{{item.width}}" height="{{item.height}}" ng-if="item.thumbnail" ng-src="{{item.thumbnail}}" alt="{{item.name}}" draggable="false" />
<!-- SVG -->
<img class="umb-media-grid__item-image" width="{{item.width}}" height="{{item.height}}" ng-if="!item.thumbnail && item.extension == 'svg'" ng-src="{{item.file}}" alt="{{item.name}}" title="{{item.name}}" draggable="false" />
<img class="umb-media-grid__item-image" width="{{item.width}}" height="{{item.height}}" ng-if="!item.thumbnail && item.extension == 'svg'" ng-src="{{item.image}}" alt="{{item.name}}" draggable="false" />
<!-- Transparent image - fallback - used to keep image proportions on wrapper-->
<img class="umb-media-grid__item-image-placeholder" ng-if="!item.thumbnail && item.extension != 'svg'" src="assets/img/transparent.png" alt="{{item.name}}" draggable="false" />
@@ -138,15 +138,15 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag
//cannot just check for !newVal because it might be an empty string which we
//want to look for.
if (newVal !== null && newVal !== undefined && newVal !== oldVal) {
//now we need to check if we need to re-initialize our structure which is kind of tricky
// since we only want to do that if the server has changed the value, not if this controller
// has changed the value. There's only 2 scenarios where we change the value internall so
// we know what those values can be, if they are not either of them, then we'll re-initialize.
if (newVal.clearFiles !== true && newVal !== $scope.originalValue && !newVal.selectedFiles) {
// here we need to check if the value change needs to trigger an update in the UI.
// if the value is only changed in the controller and not in the server values, we do not
// want to trigger an update yet.
// we can however no longer rely on checking values in the controller vs. values from the server
// to determine whether to update or not, since you could potentially be uploading a file with
// the exact same name - in that case we need to reinitialize to show the newly uploaded file.
if (newVal.clearFiles !== true && !newVal.selectedFiles) {
initialize($scope.rebuildInput.index + 1);
}
}
});
};
@@ -1,10 +1,17 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.Grid.MediaController",
function ($scope, $rootScope, $timeout) {
function ($scope, $rootScope, $timeout, userService) {
if (!$scope.model.config.startNodeId) {
userService.getCurrentUser().then(function (userData) {
$scope.model.config.startNodeId = userData.startMediaId;
});
}
$scope.setImage = function(){
$scope.mediaPickerOverlay = {};
$scope.mediaPickerOverlay.view = "mediapicker";
$scope.mediaPickerOverlay.startNodeId = $scope.model.config && $scope.model.config.startNodeId ? $scope.model.config.startNodeId : undefined;
$scope.mediaPickerOverlay.cropSize = $scope.control.editor.config && $scope.control.editor.config.size ? $scope.control.editor.config.size : undefined;
$scope.mediaPickerOverlay.showDetails = true;
$scope.mediaPickerOverlay.disableFolderSelect = true;

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