Compare commits

...

161 Commits

Author SHA1 Message Date
Mikkel Holck Madsen cf86409e3f Merge pull request #2427 from umbraco/temp-U4-10935
fixes: U4-10935 Intro tour doesn't start automatically on cloud
2018-02-06 11:04:02 +01:00
Mads Rasmussen 134f5e2601 fixes: U4-10935 Intro tour doesn't start automatically on cloud 2018-02-06 10:14:30 +01:00
Sebastiaan Jansssen 37ac524e8e Don't enable tours for upgraders 2018-02-05 22:37:47 +01:00
Sebastiaan Jansssen 43af2f8e55 Fix UI docs generator 2018-02-05 21:12:25 +01:00
Sebastiaan Jansssen a20584e3de Not beta009, Final! 2018-02-01 16:18:49 +01:00
Sebastiaan Jansssen 19ec26fef9 Merge remote-tracking branch 'origin/dev-v7' into dev-v7.8 2018-02-01 15:20:13 +01:00
Claus 527f98189a Merge pull request #2423 from umbraco/temp-u4-10897
temp U4-10897
2018-02-01 13:29:45 +01:00
Sebastiaan Janssen 78c289a559 Merge pull request #2425 from umbraco/mittonp-dev-v7
Mittonp dev v7
2018-02-01 08:59:35 +01:00
Sebastiaan Jansssen 646abb3aea Merge branch 'dev-v7' of https://github.com/mittonp/Umbraco-CMS into mittonp-dev-v7
# Conflicts:
#	src/Umbraco.Web.UI/umbraco/config/lang/da.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/es.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/fr.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/nl.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/pl.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/ru.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/zh.xml
2018-02-01 08:57:47 +01:00
Sebastiaan Janssen 2af59471a2 Merge pull request #973 from mattbrailsford/dev-v7-insertmacrofix
Updated insert macro dialog to prevent closing on enter key
2018-02-01 08:28:59 +01:00
Sebastiaan Jansssen b76b09026b Merge branch 'dev-v7' into dev-v7.8
# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Web.UI.Client/src/assets/img/installer.jpg
#	src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour.directive.js
#	src/Umbraco.Web.UI.Client/src/common/services/tour.service.js
#	src/Umbraco.Web.UI.Client/src/controllers/search.controller.js
#	src/Umbraco.Web.UI.Client/src/views/common/tours/umbintrocreatedoctype/doctypename/doctypename.controller.js
#	src/Umbraco.Web.UI.Client/src/views/users/views/user/details.html
#	src/Umbraco.Web.UI/config/BackOfficeTours/getting-started.json
#	src/Umbraco.Web/Editors/TourController.cs
#	src/Umbraco.Web/Models/BackOfficeTour.cs
#	src/Umbraco.Web/Models/BackOfficeTourStep.cs
#	src/Umbraco.Web/Models/Mapping/UserModelMapper.cs
#	src/Umbraco.Web/TourFilterResolver.cs
#	src/Umbraco.Web/Trees/MacroTreeController.cs
#	src/Umbraco.Web/WebApi/Filters/FeatureAuthorizeAttribute.cs
#	src/umbraco.cms/businesslogic/Packager/Installer.cs
#	src/umbraco.cms/businesslogic/Packager/PackageInstance/utill.cs
2018-01-31 17:02:03 +01:00
Sebastiaan Janssen 090f89e5b6 Merge pull request #2223 from kgiszewski/fix/U4-6309
U4-6309: Fix black bars that appear on a RTE image resize
2018-01-31 10:43:29 +01:00
Stephan 4870afd2d3 U4-10897 - change enlisting priorities 2018-01-30 14:27:58 +01:00
Stephan 80257b6684 Revert "U4-10897 - change enlisting priorities"
This reverts commit 8f3a0b6919.
2018-01-30 14:26:59 +01:00
Stephan 8f3a0b6919 U4-10897 - change enlisting priorities 2018-01-30 14:25:43 +01:00
Stephan 9fd2f34343 U4-10897 - defer Examine indexing until scope is all done 2018-01-30 13:53:37 +01:00
Stephan e774717346 U4-10897 - expose enlisted mutable Xml in events 2018-01-30 13:14:01 +01:00
Warren Buckley 5f5759c8a3 Merge pull request #2422 from umbraco/temp-U4-10869
U4-10869 Make sure the getting started tour is only shown to the right users
2018-01-30 09:10:12 +00:00
Robert 0b90097aad "requiredSections" tour property documentation
Added a few words about "requiredSections" tour property
2018-01-30 10:00:54 +01:00
Sebastiaan Jansssen 7cd540c37e Remove additional premature uses of C#7 features 2018-01-29 14:35:30 +01:00
Sebastiaan Jansssen 83595ecaf5 Don't rely on C# 7 features 2018-01-29 14:06:25 +01:00
Robert e07c5e6ff8 Removed unused using directives 2018-01-29 13:18:11 +01:00
Robert 67ff827d67 Tours will only load if the current user has access to the same sections the tours has access to 2018-01-29 13:13:43 +01:00
Sebastiaan Jansssen 3f7159797f U4-10880 Update install background 2018-01-29 09:49:16 +01:00
Robert 6f81b7fe24 'getting-started' tour only available to admins 2018-01-25 12:10:34 +01:00
Stephan f2819f61e5 Merge pull request #2417 from umbraco/temp-u4-10846
U4-10846 - fix member group cache
2018-01-25 11:06:17 +01:00
Sebastiaan Janssen 2107e9d9e3 Merge pull request #2420 from PerplexDaniel/patch-1
Fix NullReferenceException when HttpContext is not available
2018-01-25 10:18:32 +01:00
Daniël Knippers c623b448ba Fix NullReferenceException when HttpContext is null
This method will throw a NullReferenceException in contexts without an HttpContext, like is the case in background threads. As HttpContext is only used to set an isDebug flag, it seems more sensible to not throw in cases without an HttpContext, but simply set isDebug to false instead. If this is not acceptable behavior, could we perhaps look at something other than HttpContext.Current.IsDebuggingEnabled to decide whether isDebug should be set?
2018-01-25 08:56:46 +01:00
Sebastiaan Janssen 8bb49f57e8 Merge pull request #2419 from umbraco/redmorello-U4-10864_close_back_office_search_results
Redmorello u4 10864 close back office search results
2018-01-24 17:47:44 +01:00
Sebastiaan Jansssen da0b1c2f23 Merge branch 'U4-10864_close_back_office_search_results' of https://github.com/redmorello/Umbraco-CMS into redmorello-U4-10864_close_back_office_search_results
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html
2018-01-24 17:43:19 +01:00
Sebastiaan Jansssen a288fc62eb Workaround: keep the cache we used to have but clear all cache for membergroups when a member group changes 2018-01-24 17:26:21 +01:00
Sebastiaan Jansssen 82e50ccd3a Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2018-01-24 16:13:31 +01:00
Sebastiaan Jansssen 15b0dc9f29 Merge branch 'dev-v7.8' of https://github.com/kristoffer-tvera/Umbraco-CMS into kristoffer-tvera-dev-v7.8 2018-01-24 16:12:06 +01:00
Sebastiaan Janssen 8057d09fc2 Merge pull request #2416 from PeteDuncanson/patch-1
Prevent Pinterest messing with media in the back office
2018-01-24 15:53:40 +01:00
Sebastiaan Jansssen 8877100bf0 Merge branch 'dev-v7' into temp-u4-10846 2018-01-24 15:50:08 +01:00
Stephan 41c96e6e26 Merge pull request #2398 from leekelleher/issue/U4-10756
Proposed patch for U4-10756 - Guid TypedContent performance
2018-01-24 15:27:43 +01:00
Sebastiaan Jansssen abdd117264 Fixes bug in MB 3.0.9 2018-01-24 15:26:40 +01:00
Sebastiaan Jansssen 6272dac698 Use string.Format instead of interpolation 2018-01-24 14:34:21 +01:00
Sebastiaan Jansssen 7a4b5fa796 Bump version to 7.7.10 2018-01-24 14:34:03 +01:00
Sebastiaan Jansssen c962132ee0 Update to ModelsBuilder 3.0.9 2018-01-24 14:33:32 +01:00
leekelleher 0780979469 Eagerly populating the Guid lookup
as per @Shazwazza's comment: https://github.com/umbraco/Umbraco-CMS/pull/2398#issuecomment-358752346

Tested against 12,000 nodes (in the XML cache), profiling showed it took 55ms.
2018-01-24 11:53:52 +00:00
leekelleher a42e568fdf Initialized the ConcurrentDictionary statically
as per @JimBobSquarePants's comment: https://github.com/umbraco/Umbraco-CMS/pull/2398#discussion_r162799543
2018-01-24 11:51:53 +00:00
Robert e62661cc6a Merge pull request #2397 from leekelleher/issue/U4-10845
U4-10845 MNTP value-converter - trashed content causes database lookups
2018-01-24 12:48:29 +01:00
leekelleher 6841b2ac61 Amended the lookup dictionary setter,
as per @JimBobSquarePants's comment: https://github.com/umbraco/Umbraco-CMS/pull/2398#discussion_r162522998
2018-01-24 10:29:23 +00:00
leekelleher f7f4276485 Removed the need for the UseLegacyXmlSchema check
The enhancement in PR #2367 removed the `"@isDoc"` check,
which was the main difference between the legacy and current XML schema.

Reducing the XPath to `"//*[@key=$guid]"` will perform the same for both types of schema.
_(and saves on a couple of allocations)_
2018-01-24 10:29:23 +00:00
leekelleher bb9e23ca3e Proposed patch for U4-10756 - Guid TypedContent performance
This is a proposal for a temporary workaround to issue U4-10756.

It uses a local static ConcurrentDictionary to store a lookup of Guid/int values.
If the Guid isn't in the lookup, then the traditional XPath is used, which would add the resulting node ID (int) to the lookup.
If the lookup contains the Guid, then the returned int value will be used to perform a more efficient retrieval.

<http://issues.umbraco.org/issue/U4-10756>
2018-01-24 10:29:23 +00:00
Warren Buckley 10db9363f4 Merge pull request #2411 from umbraco/temp-U4-10757
Can navigate trough global search results
2018-01-24 09:35:07 +00:00
Sebastiaan Janssen 7d5d69e2e3 Merge pull request #2418 from abjerner/patch-36
Nested Content should use the new turquoise/purple colors as the rest of the backoffice
2018-01-23 22:02:16 +01:00
Sebastiaan Janssen 06897aa8c6 Merge pull request #2413 from umbraco/temp-u4-10853
U4-10853 - fix (scheduled) unpublishing issues
2018-01-23 21:55:53 +01:00
Anders Bjerner ee75158dd0 Nested Content should use the new turquoise/purple colors as the rest of the backoffice 2018-01-23 21:55:15 +01:00
Stephan c022397d86 U4-10846 - fix member group cache 2018-01-23 20:54:47 +01:00
Shannon e25f6e82ed Merge branch 'dev-v7' into dev-v7.8
# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Web/Models/Mapping/UserModelMapper.cs
2018-01-23 11:42:14 -07:00
Shannon d104525a50 Updates core to use latest CDF version 2018-01-23 11:15:37 -07:00
Sebastiaan Janssen b0a64aa4b5 Merge pull request #2384 from umbraco/temp-u4-10822
U4-10822 - refactor view models binding error handling
2018-01-23 16:24:08 +01:00
Pete Duncanson ca86385269 Prevent Pinterest messing with media in the back office
Fixes: http://issues.umbraco.org/issue/U4-10865
2018-01-23 15:10:09 +00:00
Robert fb8368267e Merge pull request #2410 from umbraco/temp-U4-10851
Fixes U4-10851 - Unzip Umbraco packages into a flat structure
2018-01-23 16:06:41 +01:00
Claus ef4322a9b3 Merge pull request #2414 from umbraco/temp-u4-10844
U4-10844 - delete blueprints with content types
2018-01-23 15:15:15 +01:00
Stephan 7032e137b8 U4-10853 - refactor 2018-01-23 15:02:12 +01:00
Warren Buckley e99643ecfd Merge pull request #2415 from umbraco/temp-U4-10847
Removed authorize attribute from TourControlle
2018-01-23 13:44:52 +00:00
Robert a325529eb8 Merge pull request #2412 from umbraco/temp-U4-10840
Added in the create XML for the legacy UserControl based Create Dialog
2018-01-23 14:38:25 +01:00
Robert c68f832be6 Fixed anoying lower case delete action on macro context tree 2018-01-23 14:34:03 +01:00
Sebastiaan Janssen 4ab1c51327 Merge pull request #2392 from umbraco/temp-u4-10829
U4-10829 - fix tree controller
2018-01-23 14:13:39 +01:00
Robert 6f39bac32a Removed authorize attribute from TourControlle 2018-01-23 13:47:57 +01:00
Stephan e007a37c36 U4-10844 - delete blueprints with content types 2018-01-23 13:41:36 +01:00
Stephan ab9e029525 U4-10853 - fix (scheduled) unpublishing issues 2018-01-23 13:04:57 +01:00
Warren Buckley d298388a7b Update the UI.Release XML too 2018-01-23 11:47:59 +00:00
Warren Buckley 4463abe9bb Added in the create XML for the legacy UserControl based Create Dialog 2018-01-23 11:39:12 +00:00
Warren Buckley d1db38182f Fixes U4-10851 - Unzip Umbraco packages into a flat structure, so it supports packages that have files at the root, along with some packages that have the files nested insider another guid folder 2018-01-23 10:38:41 +00:00
Robert e808360653 Can navigate trough global search results 2018-01-23 10:46:02 +01:00
Mads Rasmussen c5df712471 Merge pull request #2405 from umbraco/temp-U4-10852
Fixes U4-10852 Where the ZipArchive stream was closed
2018-01-23 09:50:29 +01:00
Sebastiaan Janssen 2f67008987 Merge pull request #2407 from abjerner/patch-34
Removed unnecessary &nbsp;
2018-01-23 09:42:30 +01:00
Sebastiaan Janssen 1672e284c5 Merge pull request #2406 from abjerner/patch-33
Minor casing change
2018-01-23 09:41:46 +01:00
Ian Houghton 60ce36a7f2 U4-10864 add button when search returns no results, to clear the search 2018-01-22 22:03:35 +00:00
Mads Rasmussen 05c12d1f27 Merge pull request #2404 from umbraco/temp-U4-10843
Fixes U4-10843 and allows user detail page to upload a new avatar
2018-01-22 20:21:57 +01:00
Anders Bjerner 72e2cacc87 Removed unnecessary &nbsp; 2018-01-22 18:16:42 +01:00
Anders Bjerner 4285102422 Minor casing change 2018-01-22 18:08:37 +01:00
Warren Buckley 5ffdf4dd60 Fixes U4-10852 Where the ZipArchive stream was closed - 'Cannot access a closed Stream' 2018-01-22 14:20:01 +00:00
Mads Rasmussen abbcf0e26b Merge pull request #2358 from abjerner/patch-28
Triggers the save button to momentarily show an error icon
2018-01-22 14:55:10 +01:00
Sebastiaan Janssen 347b25472f Merge pull request #2403 from JimBobSquarePants/housekeeping-gitattributes
Add default gitattributes and cleanup editorconfig
2018-01-22 14:38:40 +01:00
Mads Rasmussen b745948dc6 Merge pull request #2361 from bjarnef/dev-v7-U4-10791
U4-10791 - Fix collapsed columns listview settings
2018-01-22 13:48:58 +01:00
Mads Rasmussen 8007c8869f Merge pull request #2401 from umbraco/temp-U4-10835
U4-10835 Adds context menu items to the User tree
2018-01-22 13:25:59 +01:00
Stephan b51a328ead Merge pull request #2402 from JimBobSquarePants/perf-tryconvertto
Performance - 8x Faster TryConvertTo
2018-01-22 13:22:22 +01:00
Warren Buckley f61437cc7c Fixes U4-10843 and allows user detail page to upload a new avatar 2018-01-22 12:09:28 +00:00
James Jackson-South f3b8f2eb5f Add default gitattributes and cleanup editorconfig 2018-01-22 21:44:08 +11:00
James Jackson-South de4628f450 Add perf explanation 2018-01-22 20:58:15 +11:00
James Jackson-South b0a64655b4 Fastest dictionary lookups 2018-01-22 16:43:02 +11:00
Stephan 48d88ec8fa Deal fix FIXME 2018-01-21 10:29:06 +01:00
Stephan 7ca151a3fa Use concurrent dictionaries 2018-01-21 10:18:13 +01:00
Stephan 363c8fab2c Cleanup 2018-01-21 10:03:17 +01:00
Stephan 8d4fd9d1cf Merge branch 'perf-tryconvertto' of https://github.com/JimBobSquarePants/Umbraco-CMS into perf-tryconvertto 2018-01-21 10:01:12 +01:00
James Jackson-South 24071eb3b1 Faster TryConvertTo 2018-01-20 14:54:52 +11:00
James Jackson-South 62ffbe7cf0 Cleanup benchmarks and add TryCOnvertTo 2018-01-20 13:00:10 +11:00
Warren Buckley f2d6b47e47 Update labels for context menu items to be just 'Create' & 'Invite' to keep the same consistency throughout the UI as other context menu items do not include the verb 2018-01-19 14:24:57 +00:00
Warren Buckley f3541908c7 Update Users tree context menu to include two new items that navigate directly to an Angular Location/Path which loads the Invite or Create User views as needed 2018-01-19 14:07:23 +00:00
Sebastiaan Jansssen 4e57e1cc18 Nicer variable name, thank to Lee Kelleher! 2018-01-19 12:50:45 +01:00
Sebastiaan Jansssen 410afffaa9 Optimizing use of newlines array 2018-01-19 12:42:04 +01:00
Claus 936e94789d adding to tinyMceConfig.Release.config. 2018-01-19 12:21:57 +01:00
Claus 468a56e5de Merge branch 'karltynan-dev-v7' into dev-v7 2018-01-19 11:11:53 +01:00
Claus 468ec8824a Merge branch 'dev-v7' of git://github.com/karltynan/Umbraco-CMS into karltynan-dev-v7 2018-01-19 11:11:13 +01:00
Sebastiaan Jansssen cad913b7a1 U4-10857 Update to ClientDependency 1.9.5 2018-01-19 08:26:34 +01:00
Sebastiaan Jansssen 382103d99d Bump version to 7.7.9 2018-01-19 08:26:33 +01:00
Sebastiaan Janssen cbb6b9bca0 Merge pull request #2310 from matthew-darby/U4-10495
U4-10495 - Install and customize buttons disabled
2018-01-18 18:38:37 +01:00
Sebastiaan Janssen a1b90a50cd Merge pull request #2343 from soreng/patch-5
Fix for U4-10733
2018-01-18 18:28:34 +01:00
Sebastiaan Janssen 9ea5855073 Merge pull request #2360 from janvanhelvoort/U4-10785
U4-10785 - Filtering of Grid Editors
2018-01-18 18:20:11 +01:00
Sebastiaan Janssen 4a37433042 Merge pull request #2372 from bjarnef/dev-v7-U4-10809
Fix checkmark tree icon, when custom font icon is used for tree icon
2018-01-18 18:00:53 +01:00
Sebastiaan Janssen 91469812d3 Merge pull request #2383 from MMasey/U4-10727
U4 10727 - If nodes with an empty name exist, it's not possible to empty recycle bin
2018-01-18 17:54:40 +01:00
Sebastiaan Janssen 68a8eb7f3f Merge pull request #2375 from redmorello/U4-10762
U4-10762 Fix issue with empty name when registering new members from …
2018-01-18 17:40:05 +01:00
Sebastiaan Janssen 2e7baabb94 Merge pull request #2394 from umbraco/temp-u4-10813
U4-10813 - fix error with groups having a large number of permissions
2018-01-18 17:27:11 +01:00
Sebastiaan Janssen 57745fe71d Merge pull request #2396 from leekelleher/issue/U4-10842
U4-10842 LegacyMediaPickerPropertyConverter null-reference check
2018-01-18 17:17:45 +01:00
Sebastiaan Janssen de6f9236e7 Merge pull request #2399 from leekelleher/issue/U4-8712
U4-8712 MultipleTextstring value newline delimiter changes
2018-01-18 17:13:46 +01:00
Sebastiaan Janssen a00c59e8b5 Merge pull request #2393 from umbraco/temp-u4-10079
U4-10079 - remove default template
2018-01-18 16:54:22 +01:00
Stephan 05c2da807f U4-10079 - fix test 2018-01-18 15:58:51 +01:00
leekelleher 0fd8ca43d6 U4-8712 MultipleTextstring value newline delimiter changes
PR #2185 goes towards resolving this, but doesn't handle the impromptu switch between the `\r\n` and `\n` newline delimiters when republishing a content node.

Using an explicit array of newline chars will resolve this, e.g. `Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)`

<http://issues.umbraco.org/issue/U4-8712>
2018-01-18 12:18:51 +00:00
leekelleher 87f09b2ee6 U4-10845 MultiNodeTreePickerPropertyConverter - trashed content causes database lookups
If the first ID in the MNTP value is a trashed content node, then the `ConvertSourceToObject` method would
check if the ID is a media or member node, both of these incur a database call.

This can cause a detrimental performance impact on the website.

This patch uses the `startNode.type` prevalue to detect the node type, (e.g. Content, Media or Member).
The prevalue is cached in a private `ConcurrentDictionary` and refreshed using the `DataTypeCacheRefresher` event.
> _Following the same caching-pattern as the Slider, Tags and MediaPicker value-converters._

<http://issues.umbraco.org/issue/U4-10845>
2018-01-18 10:49:18 +00:00
leekelleher e466878925 U4-10842 LegacyMediaPickerPropertyConverter ConvertDataToSource null-reference check
If a selected media node has been trashed on the source environment,
when Deploy comes to transfer the node ID, because it can't transfer the media dependency,
the node ID value is set to `null`.

This causes an issue for the `LegacyMediaPickerPropertyConverter`
and `ConvertDataToSource` throws a null-reference exception.

This patch adds in a null-reference check for the `source` value.

<http://issues.umbraco.org/issue/U4-10842>
2018-01-18 10:04:55 +00:00
Claus 7adf917570 Merge pull request #2395 from umbraco/temp-U4-10836
U4-10836 ContentService.GetPagedDescendants() is not returning any re…
2018-01-18 07:27:12 +01:00
Stephan 7c41db4bcc U4-10836 - fix a couple issues with the PR, and optimize 2018-01-17 17:14:26 +01:00
Stephan 5caaef7795 Merge branch origin/dev-v7.8 into temp-U4-10836 2018-01-17 16:54:28 +01:00
Claus 3b72945b1f applying path fix for MediaService. 2018-01-17 15:57:53 +01:00
Mads Rasmussen 71eb22d0e8 Merge branch 'dev-v7.8' of https://github.com/umbraco/Umbraco-CMS into dev-v7.8 2018-01-17 15:51:25 +01:00
Mads Rasmussen 9d780a2e8f fixes: U4-10837 CMS getting started tour can't create Home page 2018-01-17 15:50:01 +01:00
Claus 55b00069cb U4-10836 ContentService.GetPagedDescendants() is not returning any results 2018-01-17 15:40:25 +01:00
Robert b304728f4e Merge pull request #2390 from umbraco/temp-U4-10828
fixes: U4-10828 Add documentation to tour component and service
2018-01-17 14:27:01 +01:00
Mikulas Tomanka 319acc199e Merge pull request #2391 from matthew-darby/U4-10825
U4-10825 Search member by email in member section
2018-01-17 14:18:43 +01:00
Stephan 2a982f21a7 U4-10813 - fix error with groups having a large number of permissions 2018-01-17 13:07:03 +01:00
Stephan 3ff455f11d U4-10079 - remove default template 2018-01-17 11:36:08 +01:00
Stephan 41ad1bf27b U4-10829 - fix tree controller 2018-01-17 10:47:35 +01:00
Matt Darby f49d939a2d U4-10825 Search member by email in member section 2018-01-16 23:06:15 +08:00
Mads Rasmussen c7e80fc532 remove all client side code related to registering tours in the service. It should be done through .json files. 2018-01-16 13:40:57 +01:00
Mads Rasmussen b47d691841 add documentation to the tour component 2018-01-16 13:31:13 +01:00
Shannon 7e1e83b493 Fixes PackageInstaller event args to make sure the package metadata is passed through 2018-01-16 19:18:08 +11:00
Shannon f6971185f8 bumps version 2018-01-16 19:15:34 +11:00
Shannon 244429b972 Fixes PackageInstaller event args to make sure the package metadata is passed through 2018-01-16 19:15:01 +11:00
Shannon 80ceba36dc Merge branch 'dev-v7.8' of https://github.com/umbraco/Umbraco-CMS into dev-v7.8 2018-01-15 20:41:47 +11:00
Warren Buckley 2b5f370c92 Merge pull request #2351 from umbraco/temp-U4-9291
U4-9291 TypedSearch should have an overload specifying pager values, …
2018-01-15 09:38:51 +00:00
Shannon 3d90c2b83f oops, fixed returned type not picked up by compiler due to dynamics 2018-01-15 16:11:56 +11:00
Shannon 3b8b5b6dfa Merge branch 'dev-v7.8' into temp-U4-9291 2018-01-15 15:51:40 +11:00
Stephan 42959a1db5 U4-10822 - fix breaking change 2018-01-12 13:51:06 +01:00
Kristoffer Tverå a1cd22208b Extra check before assigning value to currentColor
In version 7.7.7 with the latest version of LeBlender (1.0.9.2), colorpickers will throw a javascript error in console. Applying this small check will resolve that issue.
ref: https://our.umbraco.org/forum/contributing-to-umbraco-cms/88890-color-picker-cannot-read-property-hasownproperty-of-null
2018-01-12 10:45:59 +01:00
Stephan 0bc4c7e2aa U4-10822 - refactor view models binding error handling 2018-01-11 16:42:20 +01:00
Mike 9f6e6e4701 Add tests to SimilarNodeNameTests to check for null and "" values. 2018-01-10 20:58:10 +00:00
Mike 34ba3f3351 Merge remote-tracking branch 'upstream/dev-v7' into U4-10727 2018-01-10 20:48:28 +00:00
Mike dcfb8b94d8 Refactor SimilarNodeName to account for null nodeName values. 2018-01-10 20:44:30 +00:00
Ian Houghton f5f3676a56 U4-10762 Fix issue with empty name when registering new members from snippet 2018-01-09 15:51:32 +00:00
Mike dc7b83ca6c Add initial test fix for SimilarNodeName when a node has no name. 2018-01-08 17:30:11 +00:00
Bjarne Fyrstenborg fcf9dcd803 Fix checkmark tree icon, when custom font icon is used for tree icon, e.g. in UCommerce 2018-01-08 14:40:31 +01:00
Sebastiaan Jansssen 3556043b55 Update to latest modelsbuilder 2018-01-08 12:44:29 +01:00
Bjarne Fyrstenborg fef9e3fde0 Ensure placeholder is same height as original rows 2017-12-29 22:49:06 +01:00
Bjarne Fyrstenborg e849d2d0d0 Add required ng-model to ui-sortable 2017-12-29 22:48:14 +01:00
Bjarne Fyrstenborg 9a6123579f Fix collapsed columns in row when sorting 2017-12-29 22:47:29 +01:00
Jan van Helvoort 591a881283 Filtering of Grid Editors
If there are more than 15 items, 5 rows of 3, then show the filter.
2017-12-24 15:48:16 +01:00
Anders Bjerner 1554d52ea9 Triggers the save button to momentarily show an error icon 2017-12-20 21:51:59 +01:00
Shannon 60924d93fb U4-9291 TypedSearch should have an overload specifying pager values, page size, page index, and with an out param to return the total number of results 2017-12-15 17:24:54 +11:00
Søren Gregersen 50335723b0 Fix for U4-10733 2017-12-06 10:09:40 +01:00
Karl Tynan 58697eaa04 Merge pull request #1 from karltynan/karltynan-patch-1
Added small to allowed TinyMCE valid elements
2017-11-21 15:20:06 +00:00
Karl Tynan ce58ad91b5 Added `small` to allowed TinyMCE valid elements
We use ``small`` a lot in the RTE, and ``small`` is now considered a really useful tag in HTML5. I would like to see this in the default valid elements list for people to use out-of-the box.
2017-11-21 15:18:42 +00:00
Matt Darby 77162e4b51 Move val-email attribute before required attribute 2017-11-07 19:17:42 +07:00
Kevin Giszewski 6c172702be Fix for U4-6309 2017-09-27 11:32:36 -04:00
Mitton 7c72e70967 Added grid editor names for localization. 2016-05-05 05:42:33 +02:00
Mitton 75b74a6687 Enabled localization of grid editor names 2016-05-05 05:12:33 +02:00
mattbrailsford 7dcb4435d8 Updated insert macro dialog to prevent closing on enter key 2015-12-22 11:18:32 +00:00
122 changed files with 2808 additions and 1287 deletions
+11 -5
View File
@@ -1,10 +1,16 @@
root=true
# editorconfig.org
# top-most EditorConfig file
root = true
# Default settings:
# A newline ending every file
# Use 4 spaces as indentation
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.{cs,cshtml,csx,vb,vbx,vbhtml,fs,fsx,txt,ps1,sql}]
indent_size = 4
# Trim trailing whitespace, limited support.
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
trim_trailing_whitespace = true
+49
View File
@@ -0,0 +1,49 @@
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.jpg binary
*.png binary
*.gif binary
*.cs text=auto diff=csharp
*.vb text=auto
*.c text=auto
*.cpp text=auto
*.cxx text=auto
*.h text=auto
*.hxx text=auto
*.py text=auto
*.rb text=auto
*.java text=auto
*.html text=auto
*.htm text=auto
*.css text=auto
*.scss text=auto
*.sass text=auto
*.less text=auto
*.js text=auto
*.lisp text=auto
*.clj text=auto
*.sql text=auto
*.php text=auto
*.lua text=auto
*.m text=auto
*.asm text=auto
*.erl text=auto
*.fs text=auto
*.fsx text=auto
*.hs text=auto
*.csproj text=auto merge=union
*.vbproj text=auto merge=union
*.fsproj text=auto merge=union
*.dbproj text=auto merge=union
*.sln text=auto eol=crlf merge=union
@@ -44,7 +44,7 @@ function Build-UmbracoDocs
# change baseUrl
$baseUrl = "https://our.umbraco.org/apidocs/ui/"
$indexPath = "$src/Umbraco.Web.UI.Client/docs/api/index.html"
(Get-Content $indexPath).Replace("location.href.replace(rUrl, indexFile)", "'$baseUrl'") `
(Get-Content $indexPath).Replace("origin + location.href.substr(origin.length).replace(rUrl, indexFile)", "'$baseUrl'") `
| Set-Content $indexPath
# restore
@@ -100,8 +100,9 @@ function Get-DocFx($uenv, $buildTemp)
$docFx = "$buildTemp\docfx"
if (-not (test-path $docFx))
{
Write-Host "Download DocFx..."
$source = "https://github.com/dotnet/docfx/releases/download/v2.19.2/docfx.zip"
Write-Host "Download DocFx from $source"
Invoke-WebRequest $source -OutFile "$buildTemp\docfx.zip"
&$uenv.Zip x "$buildTemp\docfx.zip" -o"$buildTemp\docfx" -aos > $nul
+1 -1
View File
@@ -28,7 +28,7 @@
<dependency id="HtmlAgilityPack" version="[1.4.9.5, 2.0.0)" />
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
<dependency id="ClientDependency" version="[1.9.4, 2.0.0)" />
<dependency id="ClientDependency" version="[1.9.6, 2.0.0)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
+1 -1
View File
@@ -17,7 +17,7 @@
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.8, 4.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.10, 4.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.1, 3.0.0)" />
</dependencies>
+16
View File
@@ -98,10 +98,26 @@ if ($project) {
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
} else {
# This part only runs for upgrades
$upgradeViewSource = Join-Path $umbracoFolderSource "Views\install\*"
$upgradeView = Join-Path $umbracoFolder "Views\install\"
Write-Host "Copying2 ${upgradeViewSource} to ${upgradeView}"
Copy-Item $upgradeViewSource $upgradeView -Force
Try
{
# Disable tours for upgrades, presumably Umbraco experience is already available
$umbracoSettingsConfigPath = Join-Path $configFolder "umbracoSettings.config"
$content = (Get-Content $umbracoSettingsConfigPath).Replace('<tours enable="true">','<tours enable="false">')
# Saves with UTF-8 encoding without BOM which makes sure Umbraco can still read it
# Reference: https://stackoverflow.com/a/32951824/5018
[IO.File]::WriteAllLines($umbracoSettingsConfigPath, $content)
}
Catch
{
# Not a big problem if this fails, let it go
}
}
$installFolder = Join-Path $projectPath "Install"
+1 -1
View File
@@ -12,4 +12,4 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.8.0")]
[assembly: AssemblyInformationalVersion("7.8.0-beta007")]
[assembly: AssemblyInformationalVersion("7.8.0")]
@@ -0,0 +1,61 @@
using System;
namespace Umbraco.Core.Collections
{
/// <summary>
/// Represents a composite key of (Type, Type) for fast dictionaries.
/// </summary>
internal struct CompositeTypeTypeKey : IEquatable<CompositeTypeTypeKey>
{
/// <summary>
/// Initializes a new instance of the <see cref="CompositeTypeTypeKey"/> struct.
/// </summary>
public CompositeTypeTypeKey(Type type1, Type type2) : this()
{
Type1 = type1;
Type2 = type2;
}
/// <summary>
/// Gets the first type.
/// </summary>
public Type Type1 { get; private set; }
/// <summary>
/// Gets the second type.
/// </summary>
public Type Type2 { get; private set; }
/// <inheritdoc/>
public bool Equals(CompositeTypeTypeKey other)
{
return Type1 == other.Type1 && Type2 == other.Type2;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var other = obj is CompositeTypeTypeKey ? (CompositeTypeTypeKey)obj : default(CompositeTypeTypeKey);
return Type1 == other.Type1 && Type2 == other.Type2;
}
public static bool operator ==(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2)
{
return key1.Type1 == key2.Type1 && key1.Type2 == key2.Type2;
}
public static bool operator !=(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2)
{
return key1.Type1 != key2.Type1 || key1.Type2 != key2.Type2;
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (Type1.GetHashCode() * 397) ^ Type2.GetHashCode();
}
}
}
}
+37 -1
View File
@@ -11,17 +11,53 @@
/// The integer identifier for global system root node.
/// </summary>
public const int Root = -1;
/// <summary>
/// The string identifier for global system root node.
/// </summary>
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
public const string RootString = "-1";
/// <summary>
/// The integer identifier for content's recycle bin.
/// </summary>
public const int RecycleBinContent = -20;
/// <summary>
/// The string identifier for content's recycle bin.
/// </summary>
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
public const string RecycleBinContentString = "-20";
/// <summary>
/// The string path prefix of the content's recycle bin.
/// </summary>
/// <remarks>
/// <para>Everything that is in the content recycle bin, has a path that starts with the prefix.</para>
/// <para>Use this instead of re-creating the string everywhere.</para>
/// </remarks>
public const string RecycleBinContentPathPrefix = "-1,-20,";
/// <summary>
/// The integer identifier for media's recycle bin.
/// </summary>
public const int RecycleBinMedia = -21;
/// <summary>
/// The string identifier for media's recycle bin.
/// </summary>
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
public const string RecycleBinMediaString = "-21";
/// <summary>
/// The string path prefix of the media's recycle bin.
/// </summary>
/// <remarks>
/// <para>Everything that is in the media recycle bin, has a path that starts with the prefix.</para>
/// <para>Use this instead of re-creating the string everywhere.</para>
/// </remarks>
public const string RecycleBinMediaPathPrefix = "-1,-21,";
public const int DefaultContentListViewDataTypeId = -95;
public const int DefaultMediaListViewDataTypeId = -96;
public const int DefaultMembersListViewDataTypeId = -97;
@@ -29,6 +65,6 @@
public const string UmbracoConnectionName = "umbracoDbDSN";
public const string UmbracoMigrationName = "Umbraco";
}
}
}
+34 -34
View File
@@ -21,9 +21,9 @@ namespace Umbraco.Core
public static DateTime TruncateTo(this DateTime dt, DateTruncate truncateTo)
{
if (truncateTo == DateTruncate.Year)
return new DateTime(dt.Year, 0, 0);
return new DateTime(dt.Year, 1, 1);
if (truncateTo == DateTruncate.Month)
return new DateTime(dt.Year, dt.Month, 0);
return new DateTime(dt.Year, dt.Month, 1);
if (truncateTo == DateTruncate.Day)
return new DateTime(dt.Year, dt.Month, dt.Day);
if (truncateTo == DateTruncate.Hour)
@@ -41,43 +41,43 @@ namespace Umbraco.Core
Hour,
Minute,
Second
}
}
/// <summary>
/// Calculates the number of minutes from a date time, on a rolling daily basis (so if
/// Calculates the number of minutes from a date time, on a rolling daily basis (so if
/// date time is before the time, calculate onto next day)
/// </summary>
/// <param name="fromDateTime">Date to start from</param>
/// <param name="scheduledTime">Time to compare against (in Hmm form, e.g. 330, 2200)</param>
/// <returns></returns>
public static int PeriodicMinutesFrom(this DateTime fromDateTime, string scheduledTime)
{
// Ensure time provided is 4 digits long
if (scheduledTime.Length == 3)
{
scheduledTime = "0" + scheduledTime;
}
var scheduledHour = int.Parse(scheduledTime.Substring(0, 2));
var scheduledMinute = int.Parse(scheduledTime.Substring(2));
DateTime scheduledDateTime;
if (IsScheduledInRemainingDay(fromDateTime, scheduledHour, scheduledMinute))
{
scheduledDateTime = new DateTime(fromDateTime.Year, fromDateTime.Month, fromDateTime.Day, scheduledHour, scheduledMinute, 0);
}
else
{
var nextDay = fromDateTime.AddDays(1);
scheduledDateTime = new DateTime(nextDay.Year, nextDay.Month, nextDay.Day, scheduledHour, scheduledMinute, 0);
}
return (int)(scheduledDateTime - fromDateTime).TotalMinutes;
}
private static bool IsScheduledInRemainingDay(DateTime fromDateTime, int scheduledHour, int scheduledMinute)
{
return scheduledHour > fromDateTime.Hour || (scheduledHour == fromDateTime.Hour && scheduledMinute >= fromDateTime.Minute);
/// <returns></returns>
public static int PeriodicMinutesFrom(this DateTime fromDateTime, string scheduledTime)
{
// Ensure time provided is 4 digits long
if (scheduledTime.Length == 3)
{
scheduledTime = "0" + scheduledTime;
}
var scheduledHour = int.Parse(scheduledTime.Substring(0, 2));
var scheduledMinute = int.Parse(scheduledTime.Substring(2));
DateTime scheduledDateTime;
if (IsScheduledInRemainingDay(fromDateTime, scheduledHour, scheduledMinute))
{
scheduledDateTime = new DateTime(fromDateTime.Year, fromDateTime.Month, fromDateTime.Day, scheduledHour, scheduledMinute, 0);
}
else
{
var nextDay = fromDateTime.AddDays(1);
scheduledDateTime = new DateTime(nextDay.Year, nextDay.Month, nextDay.Day, scheduledHour, scheduledMinute, 0);
}
return (int)(scheduledDateTime - fromDateTime).TotalMinutes;
}
private static bool IsScheduledInRemainingDay(DateTime fromDateTime, int scheduledHour, int scheduledMinute)
{
return scheduledHour > fromDateTime.Hour || (scheduledHour == fromDateTime.Hour && scheduledMinute >= fromDateTime.Minute);
}
}
}
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Umbraco.Core.Packaging.Models;
namespace Umbraco.Core.Events
@@ -7,18 +8,27 @@ namespace Umbraco.Core.Events
public class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
{
private readonly MetaData _packageMetaData;
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use the overload specifying packageMetaData instead")]
public ImportPackageEventArgs(TEntity eventObject, bool canCancel)
: base(new[] { eventObject }, canCancel)
{
}
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData)
: base(new[] { eventObject })
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData, bool canCancel)
: base(new[] { eventObject }, canCancel)
{
if (packageMetaData == null) throw new ArgumentNullException("packageMetaData");
_packageMetaData = packageMetaData;
}
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData)
: this(eventObject, packageMetaData, true)
{
}
public MetaData PackageMetaData
{
get { return _packageMetaData; }
+4 -2
View File
@@ -95,8 +95,10 @@ namespace Umbraco.Core.Models
get { return _allowedTemplates; }
set
{
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector,
Ps.Value.TemplateComparer);
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector, Ps.Value.TemplateComparer);
if (_allowedTemplates.Any(x => x.Id == _defaultTemplate) == false)
DefaultTemplateId = 0;
}
}
File diff suppressed because it is too large Load Diff
@@ -20,6 +20,12 @@ namespace Umbraco.Core.Persistence.Repositories
var name = Name;
// cater for instances where node has no name.
if(string.IsNullOrWhiteSpace(name))
{
return _numPos;
}
if (name[name.Length - 1] != ')')
return _numPos = -1;
@@ -106,7 +112,7 @@ namespace Umbraco.Core.Persistence.Repositories
}
}
return uniqueing ? string.Concat(nodeName, " (", uniqueNumber.ToString(), ")") : nodeName;
return uniqueing || string.IsNullOrWhiteSpace(nodeName) ? string.Concat(nodeName, " (", uniqueNumber.ToString(), ")") : nodeName;
}
}
}
@@ -18,6 +18,8 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
return Constants.PropertyEditors.MultipleTextstringAlias.Equals(propertyType.PropertyEditorAlias);
}
private static readonly string[] NewLineDelimiters = { "\r\n", "\r", "\n" };
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
// data is (both in database and xml):
@@ -53,7 +55,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
// Fall back on normal behaviour
if (values.Any() == false)
{
return sourceString.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
return sourceString.Split(NewLineDelimiters, StringSplitOptions.None);
}
return values.ToArray();
@@ -401,9 +401,10 @@ namespace Umbraco.Core.Publishing
content.Name, content.Id));
}
// if newest is published, unpublish
if (content.Published)
content.ChangePublishedState(PublishedState.Unpublished);
// make sure we dirty .Published and always unpublish
// the version we have here could be the newest, !Published
content.ChangePublishedState(PublishedState.Published);
content.ChangePublishedState(PublishedState.Unpublished);
_logger.Info<PublishingStrategy>(
string.Format("Content '{0}' with Id '{1}' has been unpublished.",
+14
View File
@@ -116,5 +116,19 @@ namespace Umbraco.Core.Scoping
Enlisted[key] = enlistedOfT;
return enlistedOfT.Item;
}
public T GetEnlisted<T>(string key)
{
var enlistedObjects = _enlisted;
if (enlistedObjects == null) return default (T);
IEnlistedObject enlisted;
if (enlistedObjects.TryGetValue(key, out enlisted) == false)
return default (T);
var enlistedAs = enlisted as EnlistedObject<T>;
if (enlistedAs == null) throw new InvalidOperationException("An item with the key exists, but with a different type.");
return enlistedAs.Item;
}
}
}
+39 -7
View File
@@ -692,7 +692,7 @@ namespace Umbraco.Core.Services
totalChildren = 0;
return Enumerable.Empty<IContent>();
}
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", contentPath[0]), TextColumnType.NVarchar));
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", contentPath[0].Path), TextColumnType.NVarchar));
}
@@ -737,7 +737,7 @@ namespace Umbraco.Core.Services
totalChildren = 0;
return Enumerable.Empty<IContent>();
}
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", contentPath[0]), TextColumnType.NVarchar));
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", contentPath[0].Path), TextColumnType.NVarchar));
}
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
@@ -884,8 +884,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentRepository(uow);
var query = Query<IContent>.Builder.Where(x => x.Published && x.ExpireDate <= DateTime.Now);
return repository.GetByQuery(query);
var query = Query<IContent>.Builder.Where(x => x.ExpireDate <= DateTime.Now);
return repository.GetByQuery(query).Where(x => x.HasPublishedVersion);
}
}
@@ -912,13 +912,11 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentRepository(uow);
var query = Query<IContent>.Builder.Where(x => x.Path.Contains(Constants.System.RecycleBinContent.ToInvariantString()));
var query = Query<IContent>.Builder.Where(x => x.Path.StartsWith(Constants.System.RecycleBinContentPathPrefix));
return repository.GetByQuery(query);
}
}
/// <summary>
/// Checks whether an <see cref="IContent"/> item has any children
/// </summary>
@@ -1344,6 +1342,40 @@ namespace Umbraco.Core.Services
return content;
}
public void DeleteBlueprintsOfTypes(IEnumerable<int> contentTypeIds, int userId = 0)
{
using (new WriteLock(Locker))
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateContentBlueprintRepository(uow);
var contentTypeIdsA = contentTypeIds.ToArray();
var query = new Query<IContent>();
if (contentTypeIdsA.Length > 0)
{
query.Where(x => contentTypeIdsA.Contains(x.ContentTypeId));
}
var blueprints = repository.GetByQuery(query).Select(x =>
{
((Content) x).IsBlueprint = true;
return x;
}).ToArray();
foreach (var blueprint in blueprints)
{
repository.Delete(blueprint);
}
uow.Events.Dispatch(DeletedBlueprint, this, new DeleteEventArgs<IContent>(blueprints), "DeletedBlueprint");
uow.Commit();
}
}
public void DeleteBlueprintsOfType(int contentTypeId, int userId = 0)
{
DeleteBlueprintsOfTypes(new[] {contentTypeId}, userId);
}
/// <summary>
/// Saves a single <see cref="IContent"/> object
/// </summary>
@@ -920,7 +920,9 @@ namespace Umbraco.Core.Services
var deletedContentTypes = new List<IContentType> { contentType };
deletedContentTypes.AddRange(GetDescendants(contentType));
_contentService.DeleteContentOfTypes(deletedContentTypes.Select(x => x.Id), userId);
var ids = deletedContentTypes.Select(x => x.Id).ToArray();
_contentService.DeleteContentOfTypes(ids, userId);
_contentService.DeleteBlueprintsOfTypes(ids);
repository.Delete(contentType);
deleteEventArgs.DeletedEntities = deletedContentTypes.DistinctBy(x => x.Id);
+3 -1
View File
@@ -101,7 +101,9 @@ namespace Umbraco.Core.Services
IContent GetBlueprintById(Guid id);
void SaveBlueprint(IContent content, int userId = 0);
void DeleteBlueprint(IContent content, int userId = 0);
IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0);
IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0);
void DeleteBlueprintsOfType(int contentTypeId, int userId = 0);
void DeleteBlueprintsOfTypes(IEnumerable<int> contentTypeIds, int userId = 0);
/// <summary>
/// Gets all XML entries found in the cmsContentXml table based on the given path
+9 -9
View File
@@ -389,7 +389,7 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.Level == level && x.Path.StartsWith("-21") == false);
var query = Query<IMedia>.Builder.Where(x => x.Level == level && x.Path.StartsWith(Constants.System.RecycleBinMediaPathPrefix) == false);
return repository.GetByQuery(query);
}
}
@@ -440,7 +440,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
public IEnumerable<IMedia> GetAncestors(IMedia media)
{
var ids = media.Path.Split(',').Where(x => x != "-1" && x != media.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray();
var ids = media.Path.Split(',').Where(x => x != Constants.System.RootString && x != media.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray();
if (ids.Any() == false)
return new List<IMedia>();
@@ -609,7 +609,7 @@ namespace Umbraco.Core.Services
totalChildren = 0;
return Enumerable.Empty<IMedia>();
}
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", mediaPath[0]), TextColumnType.NVarchar));
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", mediaPath[0].Path), TextColumnType.NVarchar));
}
IQuery<IMedia> filterQuery = null;
if (filter.IsNullOrWhiteSpace() == false)
@@ -673,7 +673,7 @@ namespace Umbraco.Core.Services
/// <returns>Parent <see cref="IMedia"/> object</returns>
public IMedia GetParent(IMedia media)
{
if (media.ParentId == -1 || media.ParentId == -21)
if (media.ParentId == Constants.System.Root || media.ParentId == Constants.System.RecycleBinMedia)
return null;
return GetById(media.ParentId);
@@ -703,7 +703,7 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.ParentId == -1);
var query = Query<IMedia>.Builder.Where(x => x.ParentId == Constants.System.Root);
return repository.GetByQuery(query);
}
}
@@ -717,7 +717,7 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.Path.Contains("-21"));
var query = Query<IMedia>.Builder.Where(x => x.Path.StartsWith(Constants.System.RecycleBinMediaPathPrefix));
return repository.GetByQuery(query);
}
}
@@ -767,7 +767,7 @@ namespace Umbraco.Core.Services
using (new WriteLock(Locker))
{
//This ensures that the correct method is called if this method is used to Move to recycle bin.
if (parentId == -21)
if (parentId == Constants.System.RecycleBinMedia)
{
MoveToRecycleBin(media, userId);
return;
@@ -868,7 +868,7 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.Delete(media);
deleteEventArgs.CanCancel = false;
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
Audit(uow, AuditType.Delete, "Delete Media performed by user", userId, media.Id);
@@ -1003,7 +1003,7 @@ namespace Umbraco.Core.Services
recycleBinEventArgs.RecycleBinEmptiedSuccessfully = success;
uow.Events.Dispatch(EmptiedRecycleBin, this, recycleBinEventArgs);
Audit(uow, AuditType.Delete, "Empty Media Recycle Bin performed by user", 0, -21);
Audit(uow, AuditType.Delete, "Empty Media Recycle Bin performed by user", 0, Constants.System.RecycleBinMedia);
uow.Commit();
}
}
+1 -1
View File
@@ -695,7 +695,7 @@ namespace Umbraco.Core.Services
IQuery<IMember> filterQuery = null;
if (filter.IsNullOrWhiteSpace() == false)
{
filterQuery = Query<IMember>.Builder.Where(x => x.Name.Contains(filter) || x.Username.Contains(filter));
filterQuery = Query<IMember>.Builder.Where(x => x.Name.Contains(filter) || x.Username.Contains(filter) || x.Email.Contains(filter));
}
var repository = RepositoryFactory.CreateMemberRepository(uow);
@@ -1748,9 +1748,10 @@ namespace Umbraco.Core.Services
internal InstallationSummary InstallPackage(string packageFilePath, int userId = 0, bool raiseEvents = false)
{
var metaData = GetPackageMetaData(packageFilePath);
if (raiseEvents)
{
var metaData = GetPackageMetaData(packageFilePath);
{
if (ImportingPackage.IsRaisedEventCancelled(new ImportPackageEventArgs<string>(packageFilePath, metaData), this))
{
var initEmpty = new InstallationSummary().InitEmpty();
@@ -1762,7 +1763,7 @@ namespace Umbraco.Core.Services
if (raiseEvents)
{
ImportedPackage.RaiseEvent(new ImportPackageEventArgs<InstallationSummary>(installationSummary, false), this);
ImportedPackage.RaiseEvent(new ImportPackageEventArgs<InstallationSummary>(installationSummary, metaData, false), this);
}
return installationSummary;
@@ -70,7 +70,7 @@ namespace Umbraco.Core.Strings
{
foreach (var node in _umbracoSettings.RequestHandler.CharCollection)
{
if(string.IsNullOrEmpty(node.Char) == false)
if (string.IsNullOrEmpty(node.Char) == false)
_urlReplaceCharacters[node.Char] = node.Replacement;
}
}
@@ -109,7 +109,7 @@ namespace Umbraco.Core.Strings
private void EnsureNotFrozen()
{
if (_frozen)
throw new InvalidOperationException("Cannot configure the helper once it is frozen.");
throw new InvalidOperationException("Cannot configure the helper once it is frozen.");
}
/// <summary>
@@ -176,7 +176,7 @@ namespace Umbraco.Core.Strings
}).WithConfig(CleanStringType.Alias, new Config
{
PreFilter = ApplyUrlReplaceCharacters,
IsTerm = (c, leading) => leading
IsTerm = (c, leading) => leading
? char.IsLetter(c) // only letters
: (char.IsLetterOrDigit(c) || c == '_'), // letter, digit or underscore
StringType = CleanStringType.Ascii | CleanStringType.UmbracoCase,
@@ -215,12 +215,12 @@ namespace Umbraco.Core.Strings
return new Config
{
PreFilter = PreFilter,
PostFilter = PostFilter,
PostFilter = PostFilter,
IsTerm = IsTerm,
StringType = StringType,
BreakTermsOnUpper = BreakTermsOnUpper,
CutAcronymOnNonUpper = CutAcronymOnNonUpper,
GreedyAcronyms = GreedyAcronyms,
CutAcronymOnNonUpper = CutAcronymOnNonUpper,
GreedyAcronyms = GreedyAcronyms,
Separator = Separator
};
}
@@ -338,9 +338,9 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Gets the JavaScript code defining client-side short string services.
/// </summary>
public string GetShortStringServicesJavaScript(string controllerPath)
{
return string.Format(SssjsFormat,
_umbracoSettings.Content.ForceSafeAliases ? "true" : "false", controllerPath);
{
return string.Format(SssjsFormat,
_umbracoSettings.Content.ForceSafeAliases ? "true" : "false", controllerPath);
}
#endregion
@@ -467,7 +467,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Cleans a string.
/// </summary>
/// <param name="text">The text to clean.</param>
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// strings are cleaned up to camelCase and Ascii.</param>
/// <returns>The clean string.</returns>
/// <remarks>The string is cleaned in the context of the default culture.</remarks>
@@ -480,7 +480,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Cleans a string, using a specified separator.
/// </summary>
/// <param name="text">The text to clean.</param>
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// strings are cleaned up to camelCase and Ascii.</param>
/// <param name="separator">The separator.</param>
/// <returns>The clean string.</returns>
@@ -494,7 +494,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Cleans a string in the context of a specified culture.
/// </summary>
/// <param name="text">The text to clean.</param>
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// strings are cleaned up to camelCase and Ascii.</param>
/// <param name="culture">The culture.</param>
/// <returns>The clean string.</returns>
@@ -507,7 +507,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// Cleans a string in the context of a specified culture, using a specified separator.
/// </summary>
/// <param name="text">The text to clean.</param>
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
/// strings are cleaned up to camelCase and Ascii.</param>
/// <param name="separator">The separator.</param>
/// <param name="culture">The culture.</param>
@@ -554,7 +554,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
text = Utf8ToAsciiConverter.ToAsciiString(text);
break;
case CleanStringType.TryAscii:
const char ESC = (char) 27;
const char ESC = (char)27;
var ctext = Utf8ToAsciiConverter.ToAsciiString(text, ESC);
if (ctext.Contains(ESC) == false) text = ctext;
break;
@@ -568,8 +568,8 @@ function validateSafeAlias(input, value, immediate, callback) {{
// apply post-filter
if (config.PostFilter != null)
text = config.PostFilter(text);
text = config.PostFilter(text);
return text;
}
@@ -839,7 +839,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
{
term = term.Substring(i);
term.CopyTo(0, output, opos, term.Length);
opos += term.Length;
opos += term.Length;
}
break;
@@ -914,21 +914,22 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// <returns>The filtered string.</returns>
public virtual string ReplaceMany(string text, IDictionary<string, string> replacements)
{
// be safe
if (text == null)
{
throw new ArgumentNullException("text");
}
if (replacements == null)
{
throw new ArgumentNullException("replacements");
}
// Have done various tests, implementing my own "super fast" state machine to handle
// replacement of many items, or via regexes, but on short strings and not too
// many replacements (which prob. is going to be our case) nothing can beat this...
// (at least with safe and checked code -- we don't want unsafe/unchecked here)
foreach (KeyValuePair<string, string> item in replacements)
{
text = text.Replace(item.Key, item.Value);
}
// Note that it will do chained-replacements ie replaced items can be replaced
// in turn by another replacement (ie the order of replacements is important)
return replacements.Aggregate(text, (current, kvp) => current.Replace(kvp.Key, kvp.Value));
return text;
}
/// <summary>
@@ -940,15 +941,22 @@ function validateSafeAlias(input, value, immediate, callback) {{
/// <returns>The filtered string.</returns>
public virtual string ReplaceMany(string text, char[] chars, char replacement)
{
// be safe
if (text == null)
{
throw new ArgumentNullException("text");
}
if (chars == null)
{
throw new ArgumentNullException("chars");
}
// see note above
for (int i = 0; i < chars.Length; i++)
{
text = text.Replace(chars[i], replacement);
}
return chars.Aggregate(text, (current, c) => current.Replace(c, replacement));
return text;
}
#endregion
@@ -55,7 +55,7 @@ namespace Umbraco.Core.Sync
if (newApplicationUrl)
{
appContext._umbracoApplicationDomains.Add(applicationUrl);
LogHelper.Info(typeof(ApplicationUrlHelper), $"New ApplicationUrl detected: {applicationUrl}");
LogHelper.Info(typeof(ApplicationUrlHelper), string.Format("New ApplicationUrl detected: {0}", applicationUrl));
}
}
@@ -169,4 +169,4 @@ namespace Umbraco.Core.Sync
return url.TrimEnd('/');
}
}
}
}
+3 -2
View File
@@ -43,8 +43,8 @@
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.4\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
@@ -1547,6 +1547,7 @@
<Compile Include="ReadLock.cs" />
<Compile Include="TypeFinder.cs" />
<Compile Include="TypeHelper.cs" />
<Compile Include="Collections\CompositeTypeTypeKey.cs" />
<Compile Include="Udi.cs" />
<Compile Include="UdiDefinitionAttribute.cs" />
<Compile Include="UdiEntityType.cs" />
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.4" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
@@ -3,43 +3,24 @@ using System.Collections.Generic;
using System.Data.SqlServerCe;
using System.IO;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Jobs;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Migrations.Initial;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Tests.Benchmarks.Config;
using Umbraco.Tests.TestHelpers;
using ILogger = Umbraco.Core.Logging.ILogger;
namespace Umbraco.Tests.Benchmarks
{
[Config(typeof(Config))]
[QuickRunWithMemoryDiagnoserConfig]
public class BulkInsertBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
//Add(ExecutionValidator.FailOnError);
//The 'quick and dirty' settings, so it runs a little quicker
// see benchmarkdotnet FAQ
Add(Job.Default
.WithLaunchCount(1) // benchmark process will be launched only once
.WithIterationTime(100) // 100ms per iteration
.WithWarmupCount(3) // 3 warmup iteration
.WithTargetCount(3)); // 3 target iteration
}
}
private static byte[] _initDbBytes = null;
[Setup]
[GlobalSetup]
public void Setup()
{
var logger = new DebugDiagnosticsLogger();
@@ -51,8 +32,8 @@ namespace Umbraco.Tests.Benchmarks
SetupSqlCe(path, logger);
SetupSqlServer(logger);
}
}
private void SetupSqlServer(ILogger logger)
{
@@ -75,7 +56,7 @@ namespace Umbraco.Tests.Benchmarks
[lastNotifiedDate] [datetime] NOT NULL,
[isActive] [bit] NOT NULL,
[isMaster] [bit] NOT NULL,
CONSTRAINT [PK_umbracoServer] PRIMARY KEY CLUSTERED
CONSTRAINT [PK_umbracoServer] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
@@ -87,7 +68,7 @@ namespace Umbraco.Tests.Benchmarks
var dbName = string.Concat("Umb", Guid.NewGuid(), ".sdf");
AppDomain.CurrentDomain.SetData("DataDirectory", path);
var sqlCeConnectionString = $"Datasource=|DataDirectory|\\{dbName};Flush Interval=1;";
_dbFile = Path.Combine(path, dbName);
//only create the db one time
@@ -107,12 +88,12 @@ namespace Umbraco.Tests.Benchmarks
var creation = new DatabaseSchemaCreation(_dbSqlCe, logger, _sqlCeSyntax);
creation.InitializeDatabaseSchema();
}
_initDbBytes = File.ReadAllBytes(_dbFile);
_initDbBytes = File.ReadAllBytes(_dbFile);
}
else
{
File.WriteAllBytes(_dbFile, _initDbBytes);
}
}
//create the db
_dbSqlCe = new UmbracoDatabase(
@@ -138,7 +119,7 @@ namespace Umbraco.Tests.Benchmarks
return data;
}
[Cleanup]
[GlobalCleanup]
public void Cleanup()
{
_dbSqlCe.Dispose();
@@ -0,0 +1,153 @@
using BenchmarkDotNet.Attributes;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.Collections;
namespace Umbraco.Tests.Benchmarks
{
[MemoryDiagnoser]
public class ConcurrentDictionaryBenchmarks
{
private static readonly ConcurrentDictionary<CompositeTypeTypeKey, bool> AssignableTypeCache = new ConcurrentDictionary<CompositeTypeTypeKey, bool>();
private static object input = new Bar();
private static Type source = typeof(Bar);
private static Type target = typeof(Foo);
[Benchmark(Baseline = true)]
public bool GetCachedCanAssignFactory()
{
return AssignableTypeCache.GetOrAdd(new CompositeTypeTypeKey(source, target), k =>
{
var ksource = k.Type1;
var ktarget = k.Type2;
return ktarget.IsAssignableFrom(ksource) && typeof(IConvertible).IsAssignableFrom(ksource);
});
}
[Benchmark]
public bool GetCachedCanAssignNoFactory()
{
// This method is 10% faster
var key = new CompositeTypeTypeKey(source, target);
bool canConvert;
if (AssignableTypeCache.TryGetValue(key, out canConvert))
{
return canConvert;
}
// "is" is faster than "IsAssignableFrom"
if (input is IConvertible && target.IsAssignableFrom(source))
{
return AssignableTypeCache[key] = true;
}
return AssignableTypeCache[key] = false;
}
private class Foo : IConvertible
{
public TypeCode GetTypeCode()
{
return TypeCode.Object;
}
public bool ToBoolean(IFormatProvider provider)
{
throw new NotImplementedException();
}
public byte ToByte(IFormatProvider provider)
{
throw new NotImplementedException();
}
public char ToChar(IFormatProvider provider)
{
throw new NotImplementedException();
}
public DateTime ToDateTime(IFormatProvider provider)
{
throw new NotImplementedException();
}
public decimal ToDecimal(IFormatProvider provider)
{
throw new NotImplementedException();
}
public double ToDouble(IFormatProvider provider)
{
throw new NotImplementedException();
}
public short ToInt16(IFormatProvider provider)
{
throw new NotImplementedException();
}
public int ToInt32(IFormatProvider provider)
{
throw new NotImplementedException();
}
public long ToInt64(IFormatProvider provider)
{
throw new NotImplementedException();
}
public sbyte ToSByte(IFormatProvider provider)
{
throw new NotImplementedException();
}
public float ToSingle(IFormatProvider provider)
{
throw new NotImplementedException();
}
public string ToString(IFormatProvider provider)
{
throw new NotImplementedException();
}
public object ToType(Type conversionType, IFormatProvider provider)
{
if (conversionType == typeof(Foo))
{
return new Foo();
}
throw new NotImplementedException();
}
public ushort ToUInt16(IFormatProvider provider)
{
throw new NotImplementedException();
}
public uint ToUInt32(IFormatProvider provider)
{
throw new NotImplementedException();
}
public ulong ToUInt64(IFormatProvider provider)
{
throw new NotImplementedException();
}
}
private class Bar : Foo
{
}
}
}
@@ -0,0 +1,33 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Horology;
using BenchmarkDotNet.Jobs;
using System;
namespace Umbraco.Tests.Benchmarks.Config
{
/// <summary>
/// Configures the benchmark to run with less warmup and a shorter iteration time than the standard benchmark.
/// </summary>
public class QuickRunConfigAttribute : Attribute, IConfigSource
{
/// <summary>
/// Initializes a new instance of the <see cref="QuickRunConfigAttribute"/> class.
/// </summary>
public QuickRunConfigAttribute()
{
Config = (ManualConfig) ManualConfig.CreateEmpty()
.With(Job.Default.WithLaunchCount(1) // benchmark process will be launched only once
.WithIterationTime(new TimeInterval(100, TimeUnit.Millisecond)) // 100ms per iteration
.WithWarmupCount(3) // 3 warmup iteration
.WithTargetCount(3)); // 3 target iteration
}
/// <summary>
/// Gets the manual configuration.
/// </summary>
protected ManualConfig Config { get; }
/// <inheritdoc/>
IConfig IConfigSource.Config => Config;
}
}
@@ -0,0 +1,20 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
namespace Umbraco.Tests.Benchmarks.Config
{
/// <summary>
/// Configures the benchmark to run with less warmup and a shorter iteration time than the standard benchmark,
/// and include memory usage diagnosis.
/// </summary>
public class QuickRunWithMemoryDiagnoserConfigAttribute : QuickRunConfigAttribute
{
/// <summary>
/// Initializes a new instance of the <see cref="QuickRunWithMemoryDiagnoserConfigAttribute"/> class.
/// </summary>
public QuickRunWithMemoryDiagnoserConfigAttribute()
{
Config.Add(new MemoryDiagnoser());
}
}
}
@@ -1,25 +1,16 @@
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Diagnosers;
namespace Umbraco.Tests.Benchmarks
{
/// <summary>
/// Want to check what is faster OfType or Cast when a enurable all has the same items
/// </summary>
[Config(typeof(Config))]
[MemoryDiagnoser]
public class LinqCastBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
}
}
public LinqCastBenchmarks()
{
_array = new List<object>();
@@ -1,47 +1,19 @@
using System;
using System.Collections.Generic;
using System.Data.SqlServerCe;
using System.Diagnostics;
using System.IO;
using System.Linq.Expressions;
using System.Threading;
using System.Xml;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Validators;
using Moq;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.Migrations.Initial;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Tests.TestHelpers;
using ILogger = Umbraco.Core.Logging.ILogger;
namespace Umbraco.Tests.Benchmarks
{
[Config(typeof(Config))]
[MemoryDiagnoser]
public class ModelToSqlExpressionHelperBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
}
}
public ModelToSqlExpressionHelperBenchmarks()
{
var contentMapper = new ContentMapper(_syntaxProvider);
@@ -51,7 +23,7 @@ namespace Umbraco.Tests.Benchmarks
mappingResolver.Setup(resolver => resolver.ResolveMapperByType(It.IsAny<Type>())).Returns(contentMapper);
_mappingResolver = mappingResolver.Object;
}
private readonly ISqlSyntaxProvider _syntaxProvider = new SqlCeSyntaxProvider();
private readonly CachedExpression _cachedExpression;
private readonly MappingResolver _mappingResolver;
@@ -62,18 +34,15 @@ namespace Umbraco.Tests.Benchmarks
for (int i = 0; i < 100; i++)
{
var a = i;
var b = i*10;
var b = i * 10;
Expression<Func<IContent, bool>> predicate = content =>
content.Path.StartsWith("-1") && content.Published && (content.ContentTypeId == a || content.ContentTypeId == b);
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _mappingResolver);
var result = modelToSqlExpressionHelper.Visit(predicate);
}
}
[Benchmark()]
public void WithCachedExpression()
{
@@ -83,7 +52,7 @@ namespace Umbraco.Tests.Benchmarks
var b = i * 10;
Expression<Func<IContent, bool>> predicate = content =>
content.Path.StartsWith("-1") && content.Published && (content.ContentTypeId == a || content.ContentTypeId == b);
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _mappingResolver);
//wrap it!
@@ -92,6 +61,5 @@ namespace Umbraco.Tests.Benchmarks
var result = modelToSqlExpressionHelper.Visit(_cachedExpression);
}
}
}
}
+1 -11
View File
@@ -6,17 +6,7 @@ namespace Umbraco.Tests.Benchmarks
{
public static void Main(string[] args)
{
var switcher = new BenchmarkSwitcher(new[]
{
typeof(BulkInsertBenchmarks),
typeof(ModelToSqlExpressionHelperBenchmarks),
typeof(XmlBenchmarks),
typeof(LinqCastBenchmarks),
//typeof(DeepCloneBenchmarks),
typeof(XmlPublishedContentInitBenchmarks),
});
switcher.Run(args);
new BenchmarkSwitcher(typeof(Program).Assembly).Run(args);
}
}
}
@@ -0,0 +1,138 @@
using BenchmarkDotNet.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Tests.Benchmarks.Config;
namespace Umbraco.Tests.Benchmarks
{
[QuickRunWithMemoryDiagnoserConfig]
public class StringReplaceManyBenchmarks
{
/*
short text, short replacement:
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
--------------------------------------------- |---------:|----------:|----------:|-------:|---------:|-------:|----------:|
'String.ReplaceMany w/chars - Aggregate' | 236.0 ns | 40.92 ns | 2.312 ns | 1.00 | 0.00 | 0.0461 | 200 B |
'String.ReplaceMany w/chars - For Loop' | 166.7 ns | 70.51 ns | 3.984 ns | 0.71 | 0.01 | 0.0420 | 180 B |
'String.ReplaceMany w/dictionary - Aggregate' | 606.5 ns | 342.94 ns | 19.377 ns | 2.57 | 0.07 | 0.0473 | 212 B |
'String.ReplaceMany w/dictionary - For Each' | 571.8 ns | 232.33 ns | 13.127 ns | 2.42 | 0.05 | 0.0458 | 212 B |
long text, short replacement:
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
--------------------------------------------- |----------:|----------:|----------:|-------:|---------:|-------:|----------:|
'String.ReplaceMany w/chars - Aggregate' | 5.771 us | 9.963 us | 0.5630 us | 1.00 | 0.00 | 1.6798 | 6.94 KB |
'String.ReplaceMany w/chars - For Loop' | 4.962 us | 2.121 us | 0.1199 us | 0.87 | 0.08 | 1.6840 | 6.92 KB |
'String.ReplaceMany w/dictionary - Aggregate' | 14.514 us | 8.189 us | 0.4627 us | 2.53 | 0.22 | 1.6447 | 6.96 KB |
'String.ReplaceMany w/dictionary - For Each' | 15.445 us | 24.745 us | 1.3981 us | 2.69 | 0.30 | 1.5696 | 6.96 KB |
short text, long replacements dictionary:
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
--------------------------------------------- |-----------:|-----------:|----------:|-------:|---------:|-------:|----------:|
'String.ReplaceMany w/chars - Aggregate' | 257.0 ns | 200.0 ns | 11.30 ns | 1.00 | 0.00 | 0.0452 | 200 B |
'String.ReplaceMany w/chars - For Loop' | 182.4 ns | 221.0 ns | 12.49 ns | 0.71 | 0.05 | 0.0425 | 180 B |
'String.ReplaceMany w/dictionary - Aggregate' | 7,273.8 ns | 2,747.1 ns | 155.22 ns | 28.34 | 1.12 | 0.0714 | 464 B |
'String.ReplaceMany w/dictionary - For Each' | 6,981.0 ns | 5,500.7 ns | 310.80 ns | 27.20 | 1.38 | 0.0775 | 464 B |
long text, long replacements dictionary:
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
--------------------------------------------- |-----------:|-----------:|-----------:|-------:|---------:|-------:|----------:|
'String.ReplaceMany w/chars - Aggregate' | 4.868 us | 3.420 us | 0.1932 us | 1.00 | 0.00 | 1.6816 | 6.94 KB |
'String.ReplaceMany w/chars - For Loop' | 4.958 us | 2.633 us | 0.1487 us | 1.02 | 0.04 | 1.6791 | 6.92 KB |
'String.ReplaceMany w/dictionary - Aggregate' | 181.309 us | 210.177 us | 11.8754 us | 37.29 | 2.32 | 5.3571 | 24.28 KB |
'String.ReplaceMany w/dictionary - For Each' | 174.567 us | 113.733 us | 6.4262 us | 35.90 | 1.57 | 5.8594 | 24.28 KB |
*/
// don't use constants
// ReSharper disable ConvertToConstant.Local
// input text for ReplaceMany
private static readonly string Text;
// replaced chars for ReplaceMany with chars
private static readonly char[] ReplacedChars = { ',', '.', ':', '&', '#' };
// replacement char for ReplaceMany with chars
private static readonly char ReplacementChar = '*';
// replacements for ReplaceMany with dictionary
private static readonly IDictionary<string, string> Replacements;
// ReSharper restore ConvertToConstant.Local
static StringReplaceManyBenchmarks()
{
// pick what you want to benchmark
// short
Text = "1,2.3:4&5#6";
// long
//Text = "Sed ut perspiciatis unde omnis iste natus &error sit voluptatem accusantium doloremque l:audantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et &quasi architecto beatae vitae ::dicta sunt explicabo. Nemo enim ipsam volupta:tem quia voluptas sit aspernatur aut o&dit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciun&t. Neque porro quisquam est, qui dolorem: ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut e:nim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi co&&nsequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse: quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?";
// short
Replacements = new Dictionary<string, string>
{
{ ",", "*" },
{ ".", "*" },
{ ":", "*" },
{ "&", "*" },
{ "#", "*" },
};
// long
//Replacements = new Dictionary<string, string>();
//for (var i = 2; i < 100; i++)
// Replacements[Convert.ToChar(i).ToString()] = "*";
}
// this is what v7 originally did
[Benchmark(Description = "String.ReplaceMany w/chars - Aggregate", Baseline = true)]
public string ReplaceManyAggregate()
{
var result = Text;
return ReplacedChars.Aggregate(result, (current, c) => current.Replace(c, ReplacementChar));
}
[Benchmark(Description = "String.ReplaceMany w/chars - For Loop")]
public string ReplaceManyForLoop()
{
var result = Text;
// ReSharper disable once LoopCanBeConvertedToQuery
// ReSharper disable once ForCanBeConvertedToForeach
for (var i = 0; i < ReplacedChars.Length; i++)
{
result = result.Replace(ReplacedChars[i], ReplacementChar);
}
return result;
}
// this is what v7 originally did
[Benchmark(Description = "String.ReplaceMany w/dictionary - Aggregate")]
public string ReplaceManyDictionaryAggregate()
{
return Replacements.Aggregate(Text, (current, kvp) => current.Replace(kvp.Key, kvp.Value));
}
[Benchmark(Description = "String.ReplaceMany w/dictionary - For Each")]
public string ReplaceManyDictionaryForEach()
{
var result = Text;
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var item in Replacements)
{
result = result.Replace(item.Key, item.Value);
}
return result;
}
}
}
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using Umbraco.Core;
namespace Umbraco.Tests.Benchmarks
{
[MemoryDiagnoser]
public class TryConvertToBenchmarks
{
private static readonly List<string> List = new List<string>() { "hello", "world", "awesome" };
private static readonly string Date = "Saturday 10, November 2012";
[Benchmark(Description = "List<string> to IEnumerable<string>")]
public IEnumerable<string> TryConvertToEnumerable()
{
return List.TryConvertTo<IEnumerable<string>>().Result;
}
[Benchmark(Description = "Int to Double")]
public double TryConvertToDouble()
{
return 1.TryConvertTo<double>().Result;
}
[Benchmark(Description = "Float to Decimal")]
public decimal TryConvertToDecimal()
{
return 1F.TryConvertTo<decimal>().Result;
}
[Benchmark(Description = "String to Boolean")]
public bool TryConvertToBoolean()
{
return "1".TryConvertTo<bool>().Result;
}
[Benchmark(Description = "String to DateTime")]
public DateTime TryConvertToDateTime()
{
return Date.TryConvertTo<DateTime>().Result;
}
}
}
@@ -9,11 +9,12 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Umbraco.Tests.Benchmarks</RootNamespace>
<AssemblyName>Umbraco.Tests.Benchmarks</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -38,38 +39,55 @@
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="BenchmarkDotNet, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.0.9.9\lib\net45\BenchmarkDotNet.dll</HintPath>
<Reference Include="BenchmarkDotNet, Version=0.10.12.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.0.10.12\lib\net46\BenchmarkDotNet.dll</HintPath>
</Reference>
<Reference Include="BenchmarkDotNet.Core, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Core.0.9.9\lib\net45\BenchmarkDotNet.Core.dll</HintPath>
<Reference Include="BenchmarkDotNet.Core, Version=0.10.12.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Core.0.10.12\lib\net46\BenchmarkDotNet.Core.dll</HintPath>
</Reference>
<Reference Include="BenchmarkDotNet.Diagnostics.Windows, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Diagnostics.Windows.0.9.9\lib\net45\BenchmarkDotNet.Diagnostics.Windows.dll</HintPath>
</Reference>
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.9.9\lib\net45\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.10.12.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.10.12\lib\net46\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
</Reference>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
<Reference Include="Microsoft.CodeAnalysis, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Diagnostics.Tracing.TraceEvent, Version=1.0.41.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.41\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll</HintPath>
</Reference>
<Reference Include="Microsoft.DotNet.InternalAbstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.DotNet.InternalAbstractions.1.0.0\lib\net451\Microsoft.DotNet.InternalAbstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.DotNet.PlatformAbstractions, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.DotNet.PlatformAbstractions.1.1.1\lib\net451\Microsoft.DotNet.PlatformAbstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Registry, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.4.3.0\lib\net46\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.1.1309.919, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.1.1309.0919\lib\net40\Moq.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
@@ -77,13 +95,52 @@
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.FileVersionInfo, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.StackTrace, Version=4.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Numerics" />
<Reference Include="System.Reflection.Metadata, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.3.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
<Reference Include="System.Reflection.Metadata, Version=1.4.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.0.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net46\System.Security.Cryptography.Algorithms.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net46\System.Security.Cryptography.X509Certificates.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Text.Encoding.CodePages, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Thread, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -91,20 +148,38 @@
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XmlDocument, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XPath, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XPath.XDocument, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ConcurrentDictionaryBenchmarks.cs" />
<Compile Include="Config\QuickRunConfigAttribute.cs" />
<Compile Include="Config\QuickRunWithMemoryDiagnoserConfigAttribute.cs" />
<Compile Include="LinqCastBenchmarks.cs" />
<Compile Include="ModelToSqlExpressionHelperBenchmarks.cs" />
<Compile Include="BulkInsertBenchmarks.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StringReplaceManyBenchmarks.cs" />
<Compile Include="TryConvertToBenchmarks.cs" />
<Compile Include="XmlBenchmarks.cs" />
<Compile Include="XmlPublishedContentInitBenchmarks.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
<None Include="_TraceEventProgrammersGuide.docx" />
<None Include="app.config" />
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
@@ -120,10 +195,6 @@
<Name>Umbraco.Web</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="TraceEvent.ReadMe.txt" />
<Content Include="TraceEvent.ReleaseNotes.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
+8 -31
View File
@@ -1,42 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Jobs;
using Umbraco.Tests.Benchmarks.Config;
namespace Umbraco.Tests.Benchmarks
{
[Config(typeof(Config))]
[QuickRunWithMemoryDiagnoserConfig]
public class XmlBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
//Add(ExecutionValidator.FailOnError);
//The 'quick and dirty' settings, so it runs a little quicker
// see benchmarkdotnet FAQ
Add(Job.Default
.WithLaunchCount(1) // benchmark process will be launched only once
.WithIterationTime(100) // 100ms per iteration
.WithWarmupCount(3) // 3 warmup iteration
.WithTargetCount(3)); // 3 target iteration
}
}
[Setup]
[GlobalSetup]
public void Setup()
{
var templateId = 0;
var xmlText = @"<?xml version=""1.0"" encoding=""utf-8""?>
<!DOCTYPE root[
<!DOCTYPE root[
<!ELEMENT Home ANY>
<!ATTLIST Home id ID #REQUIRED>
<!ELEMENT CustomDocument ANY>
@@ -49,7 +26,7 @@ namespace Umbraco.Tests.Benchmarks
<umbracoNaviHide>1</umbracoNaviHide>
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
<content><![CDATA[<div>This is some content</div>]]></content>
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
@@ -70,7 +47,7 @@ namespace Umbraco.Tests.Benchmarks
_xml.LoadXml(xmlText);
}
[Cleanup]
[GlobalCleanup]
public void Cleanup()
{
_xml = null;
@@ -90,7 +67,7 @@ namespace Umbraco.Tests.Benchmarks
public void XmlWithNavigation()
{
var elt = _xml.DocumentElement;
var id = NavigateElementRoute(elt, new[] {"home", "sub1", "sub2"});
var id = NavigateElementRoute(elt, new[] { "home", "sub1", "sub2" });
if (id <= 0) Console.WriteLine("ERR");
}
@@ -120,4 +97,4 @@ namespace Umbraco.Tests.Benchmarks
return found ? int.Parse(elt.GetAttribute("id")) : -1;
}
}
}
}
@@ -3,37 +3,17 @@ using System.Collections.Generic;
using System.Linq;
using System.Xml;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Jobs;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Tests.Benchmarks.Config;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
namespace Umbraco.Tests.Benchmarks
{
[Config(typeof(Config))]
[QuickRunWithMemoryDiagnoserConfig]
public class XmlPublishedContentInitBenchmarks
{
private class Config : ManualConfig
{
public Config()
{
Add(new MemoryDiagnoser());
//The 'quick and dirty' settings, so it runs a little quicker
// see benchmarkdotnet FAQ
Add(Job.Default
.WithLaunchCount(1) // benchmark process will be launched only once
.WithIterationTime(100) // 100ms per iteration
.WithWarmupCount(3) // 3 warmup iteration
.WithTargetCount(3)); // 3 target iteration
}
}
public XmlPublishedContentInitBenchmarks()
{
_xml10 = Build(10);
@@ -281,7 +261,7 @@ namespace Umbraco.Tests.Benchmarks
var nodes = xmlNode.SelectNodes(dataXPath);
contentType = GetPublishedContentType(PublishedItemType.Content, docTypeAlias);
var propertyNodes = new Dictionary<string, XmlNode>();
if (nodes != null)
foreach (XmlNode n in nodes)
@@ -307,8 +287,8 @@ namespace Umbraco.Tests.Benchmarks
private static PublishedContentType GetPublishedContentType(PublishedItemType type, string alias)
{
return new PublishedContentType(alias, new string[] {},
new List<PublishedPropertyType>(Enumerable.Range(0, 10).Select(x => new PublishedPropertyType("prop" + x, 0, "test", initConverters:false))));
return new PublishedContentType(alias, new string[] { },
new List<PublishedPropertyType>(Enumerable.Range(0, 10).Select(x => new PublishedPropertyType("prop" + x, 0, "test", initConverters: false))));
}
}
@@ -1,16 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845dcd8080cc91" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
@@ -27,6 +30,10 @@
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
@@ -36,45 +43,25 @@
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
<assemblyIdentity name="BenchmarkDotNet.Core" publicKeyToken="aa0ca2f9092cefc4" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-0.10.12.0" newVersion="0.10.12.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
</configuration>
+50 -29
View File
@@ -1,40 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BenchmarkDotNet" version="0.9.9" targetFramework="net45" />
<package id="BenchmarkDotNet.Core" version="0.9.9" targetFramework="net45" />
<package id="BenchmarkDotNet" version="0.10.12" targetFramework="net46" />
<package id="BenchmarkDotNet.Core" version="0.10.12" targetFramework="net46" />
<package id="BenchmarkDotNet.Diagnostics.Windows" version="0.9.9" targetFramework="net45" />
<package id="BenchmarkDotNet.Toolchains.Roslyn" version="0.9.9" targetFramework="net45" />
<package id="BenchmarkDotNet.Toolchains.Roslyn" version="0.10.12" targetFramework="net46" />
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.Common" version="1.3.2" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.CSharp" version="1.3.2" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.Common" version="2.4.0" targetFramework="net46" />
<package id="Microsoft.CodeAnalysis.CSharp" version="2.4.0" targetFramework="net46" />
<package id="Microsoft.Diagnostics.Tracing.TraceEvent" version="1.0.41" targetFramework="net45" />
<package id="Microsoft.DotNet.InternalAbstractions" version="1.0.0" targetFramework="net46" />
<package id="Microsoft.DotNet.PlatformAbstractions" version="1.1.1" targetFramework="net46" />
<package id="Microsoft.SqlServer.Compact" version="4.0.8854.1" targetFramework="net45" />
<package id="Microsoft.Win32.Registry" version="4.3.0" targetFramework="net46" />
<package id="Moq" version="4.1.1309.0919" targetFramework="net45" />
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
<package id="System.Collections" version="4.0.11" targetFramework="net45" />
<package id="System.Collections.Concurrent" version="4.0.12" targetFramework="net45" />
<package id="System.Collections.Immutable" version="1.2.0" targetFramework="net45" />
<package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="net45" />
<package id="System.Diagnostics.Tools" version="4.0.1" targetFramework="net45" />
<package id="System.Dynamic.Runtime" version="4.0.11" targetFramework="net45" />
<package id="System.Globalization" version="4.0.11" targetFramework="net45" />
<package id="System.Linq" version="4.1.0" targetFramework="net45" />
<package id="System.Linq.Expressions" version="4.1.0" targetFramework="net45" />
<package id="System.Reflection" version="4.1.0" targetFramework="net45" />
<package id="System.Reflection.Metadata" version="1.3.0" targetFramework="net45" />
<package id="System.AppContext" version="4.3.0" targetFramework="net46" />
<package id="System.Collections" version="4.3.0" targetFramework="net46" />
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net46" />
<package id="System.Collections.Immutable" version="1.3.1" targetFramework="net46" />
<package id="System.Console" version="4.3.0" targetFramework="net46" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net46" />
<package id="System.Diagnostics.FileVersionInfo" version="4.3.0" targetFramework="net46" />
<package id="System.Diagnostics.StackTrace" version="4.3.0" targetFramework="net46" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net46" />
<package id="System.Dynamic.Runtime" version="4.3.0" targetFramework="net46" />
<package id="System.Globalization" version="4.3.0" targetFramework="net46" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net46" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net46" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net46" />
<package id="System.Linq" version="4.3.0" targetFramework="net46" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net46" />
<package id="System.Reflection" version="4.3.0" targetFramework="net46" />
<package id="System.Reflection.Metadata" version="1.4.2" targetFramework="net46" />
<package id="System.Reflection.Primitives" version="4.0.1" targetFramework="net45" />
<package id="System.Resources.ResourceManager" version="4.0.1" targetFramework="net45" />
<package id="System.Runtime" version="4.1.0" targetFramework="net45" />
<package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net45" />
<package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net45" />
<package id="System.Runtime.Numerics" version="4.0.1" targetFramework="net45" />
<package id="System.Text.Encoding" version="4.0.11" targetFramework="net45" />
<package id="System.Text.Encoding.Extensions" version="4.0.11" targetFramework="net45" />
<package id="System.Threading" version="4.0.11" targetFramework="net45" />
<package id="System.Threading.Tasks" version="4.0.11" targetFramework="net45" />
<package id="System.Threading.Tasks.Extensions" version="4.0.0" targetFramework="net45" />
<package id="System.Threading.Tasks.Parallel" version="4.0.1" targetFramework="net45" />
<package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="net45" />
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="net45" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net46" />
<package id="System.Runtime" version="4.3.0" targetFramework="net46" />
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net46" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net46" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net46" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net46" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net46" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net46" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net46" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net46" />
<package id="System.Text.Encoding.CodePages" version="4.3.0" targetFramework="net46" />
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net46" />
<package id="System.Threading" version="4.3.0" targetFramework="net46" />
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net46" />
<package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net46" />
<package id="System.Threading.Tasks.Parallel" version="4.3.0" targetFramework="net46" />
<package id="System.Threading.Thread" version="4.3.0" targetFramework="net46" />
<package id="System.ValueTuple" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XPath" version="4.3.0" targetFramework="net46" />
<package id="System.Xml.XPath.XDocument" version="4.3.0" targetFramework="net46" />
</packages>
+2 -2
View File
@@ -161,9 +161,9 @@ namespace Umbraco.Tests
var obj = new MyTestObject();
var result = obj.TryConvertTo<object>();
Assert.AreEqual(obj, result.Result);
Assert.AreEqual(obj, result.Result);
}
private CultureInfo savedCulture;
/// <summary>
@@ -332,6 +332,9 @@ namespace Umbraco.Tests.Persistence.Repositories
var contentType = (IContentType)MockedContentTypes.CreateSimpleContentType2("test", "Test", propertyGroupName: "testGroup");
Assert.AreEqual(4, contentType.PropertyTypes.Count());
// remove all templates - since they are not saved, they would break the (wtf) mapping code
contentType.AllowedTemplates = new ITemplate[0];
// there is NO mapping from display to contentType, but only from save
// to contentType, so if we want to test, let's to it properly!
@@ -24,7 +24,9 @@ namespace Umbraco.Tests.Persistence.Repositories
[TestCase("Alpha (10)", "Alpha (2)", +1)] // this is the real stuff
[TestCase("Kilo", "Golf (2)", +1)]
[TestCase("Kilo (1)", "Golf (2)", +1)]
public void ComparerTest(string name1, string name2, int expected)
[TestCase("", "", 0)]
[TestCase(null, null, 0)]
public void ComparerTest(string name1, string name2, int expected)
{
var comparer = new SimilarNodeName.Comparer();
@@ -76,7 +78,9 @@ namespace Umbraco.Tests.Persistence.Repositories
[TestCase(0, "Alpha", "Alpha (3)")]
[TestCase(0, "Kilo (1)", "Kilo (1) (1)")] // though... we might consider "Kilo (2)"
[TestCase(6, "Kilo (1)", "Kilo (1)")] // because of the id
public void Test(int nodeId, string nodeName, string expected)
[TestCase(0, "", " (1)")]
[TestCase(0, null, " (1)")]
public void Test(int nodeId, string nodeName, string expected)
{
var names = new[]
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 KiB

After

Width:  |  Height:  |  Size: 386 KiB

@@ -1,3 +1,188 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbTour
@restrict E
@scope
@description
<b>Added in Umbraco 7.8</b>. The tour component is a global component and is already added to the umbraco markup.
In the Umbraco UI the tours live in the "Help drawer" which opens when you click the Help-icon in the bottom left corner of Umbraco.
You can easily add you own tours to the Help-drawer or show and start tours from
anywhere in the Umbraco backoffice. To see a real world example of a custom tour implementation, install <a href="https://our.umbraco.org/projects/starter-kits/the-starter-kit/">The Starter Kit</a> in Umbraco 7.8
<h1><b>Extending the help drawer with custom tours</b></h1>
The easiet way to add new tours to Umbraco is through the Help-drawer. All it requires is a my-tour.json file.
Place the file in <i>App_Plugins/{MyPackage}/backoffice/tours/{my-tour}.json</i> and it will automatically be
picked up by Umbraco and shown in the Help-drawer.
<h3><b>The tour object</b></h3>
The tour object consist of two parts - The overall tour configuration and a list of tour steps. We have split up the tour object for a better overview.
<pre>
// The tour config object
{
"name": "My Custom Tour", // (required)
"alias": "myCustomTour", // A unique tour alias (required)
"group": "My Custom Group" // Used to group tours in the help drawer
"groupOrder": 200 // Control the order of tour groups
"allowDisable": // Adds a "Don't" show this tour again"-button to the intro step
"requiredSections":["content", "media", "mySection"] // Sections that the tour will access while running, if the user does not have access to the required tour sections, the tour will not load.
"steps": [] // tour steps - see next example
}
</pre>
<pre>
// A tour step object
{
"title": "Title",
"content": "<p>Step content</p>",
"type": "intro" // makes the step an introduction step,
"element": "[data-element='my-table-row']", // the highlighted element
"event": "click" // forces the user to click the UI to go to next step
"eventElement": "[data-element='my-table-row'] [data-element='my-tour-button']" // specify an element to click inside a highlighted element
"elementPreventClick": false // prevents user interaction in the highlighted element
"backdropOpacity": 0.4 // the backdrop opacity
"view": "" // add a custom view
"customProperties" : {} // add any custom properties needed for the custom view
}
</pre>
<h1><b>Adding tours to other parts of the Umbraco backoffice</b></h1>
It is also possible to add a list of custom tours to other parts of the Umbraco backoffice,
as an example on a Dashboard in a Custom section. You can then use the {@link umbraco.services.tourService tourService} to start and stop tours but you don't have to register them as part of the tour service.
<h1><b>Using the tour service</b></h1>
<h3>Markup example - show custom tour</h3>
<pre>
<div ng-controller="My.TourController as vm">
<div>{{vm.tour.name}}</div>
<button type="button" ng-click="vm.startTour()">Start tour</button>
<!-- This button will be clicked in the tour -->
<button data-element="my-tour-button" type="button">Click me</button>
</div>
</pre>
<h3>Controller example - show custom tour</h3>
<pre>
(function () {
"use strict";
function TourController(tourService) {
var vm = this;
vm.tour = {
"name": "My Custom Tour",
"alias": "myCustomTour",
"steps": [
{
"title": "Welcome to My Custom Tour",
"content": "",
"type": "intro"
},
{
"element": "[data-element='my-tour-button']",
"title": "Click the button",
"content": "Click the button",
"event": "click"
}
]
};
vm.startTour = startTour;
function startTour() {
tourService.startTour(vm.tour);
}
}
angular.module("umbraco").controller("My.TourController", TourController);
})();
</pre>
<h1><b>Custom step views</b></h1>
In some cases you will need a custom view for one of your tour steps.
This could be for validation or for running any other custom logic for that step.
We have added a couple of helper components to make it easier to get the step scaffolding to look like a regular tour step.
In the following example you see how to run some custom logic before a step goes to the next step.
<h3>Markup example - custom step view</h3>
<pre>
<div ng-controller="My.TourStep as vm">
<umb-tour-step on-close="model.endTour()">
<umb-tour-step-header
title="model.currentStep.title">
</umb-tour-step-header>
<umb-tour-step-content
content="model.currentStep.content">
<!-- Add any custom content here -->
</umb-tour-step-content>
<umb-tour-step-footer class="flex justify-between items-center">
<umb-tour-step-counter
current-step="model.currentStepIndex + 1"
total-steps="model.steps.length">
</umb-tour-step-counter>
<div>
<umb-button
size="xs"
button-style="success"
type="button"
action="vm.initNextStep()"
label="Next">
</umb-button>
</div>
</umb-tour-step-footer>
</umb-tour-step>
</div>
</pre>
<h3>Controller example - custom step view</h3>
<pre>
(function () {
"use strict";
function StepController() {
var vm = this;
vm.initNextStep = initNextStep;
function initNextStep() {
// run logic here before going to the next step
$scope.model.nextStep();
}
}
angular.module("umbraco").controller("My.TourStep", StepController);
})();
</pre>
<h3>Related services</h3>
<ul>
<li>{@link umbraco.services.tourService tourService}</li>
</ul>
@param {string} model (<code>binding</code>): Tour object
**/
(function () {
'use strict';
@@ -215,6 +215,8 @@
$scope.page.buttonGroupState = "success";
}, function(err) {
$scope.page.buttonGroupState = 'error';
});
}
@@ -30,80 +30,6 @@
});
}
/**
* @ngdoc method
* @name umbraco.services.tourService#registerTour
* @methodOf umbraco.services.tourService
*
* @description
* Registers a tour in the service
* @param {Object} tour The tour you want to register in the service
* @param {String} tour.name The tour name
* @param {String} tour.alias The tour alias
* @param {Array} tour.steps Array of tour steps
* @param {String} tour.step.title Step title
* @param {DomElement} tour.step.content Step content (pass in any HTML markup)
* @param {DomElement} tour.step.element Highlight a DOM-element
* @param {Boolean} tour.step.elementPreventClick Adds invisible layer on top of highligted element to prevent all clicks and interaction with it
* @param {Number} tour.step.backdropOpacity Sets the backdrop opacity (default 0.4)
*/
function registerTour(newTour) {
validateTour(newTour);
validateTourRegistration(newTour);
tours.push(newTour);
eventsService.emit("appState.tour.updatedTours", tours);
}
/**
* @ngdoc method
* @name umbraco.services.tourService#registerTours
* @methodOf umbraco.services.tourService
*
* @description
* Registers an array of tours in the service
* @param {Array} tours The tours to register in the service
*/
function registerTours(newTours) {
angular.forEach(newTours, function(newTour){
validateTour(newTour);
validateTourRegistration(newTour);
tours.push(newTour);
});
eventsService.emit("appState.tour.updatedTours", tours);
}
/**
* @ngdoc method
* @name umbraco.services.tourService#unregisterTour
* @methodOf umbraco.services.tourService
*
* @description
* Unregisters a tour in the service
* @param {String} tourAlias The tour alias of the tour you want to unregister
*/
function unregisterTour(tourAlias) {
tours = tours.filter(function( obj ) {
return obj.alias !== tourAlias;
});
eventsService.emit("appState.tour.updatedTours", tours);
}
/**
* @ngdoc method
* @name umbraco.services.tourService#unregisterTourGroup
* @methodOf umbraco.services.tourService
*
* @description
* Unregisters a tour in the service
* @param {String} tourGroupName The name of the tour group you want to unregister
*/
function unregisterTourGroup(tourGroup) {
tours = tours.filter(function( obj ) {
return obj.group !== tourGroup;
});
eventsService.emit("appState.tour.updatedTours", tours);
}
/**
* Method to return all of the tours as a new instance
*/
@@ -286,6 +212,9 @@
throw "Tour " + tour.alias + " is missing tour steps";
}
if (tour.requiredSections.length === 0) {
throw "Tour " + tour.alias + " is missing the required sections";
}
}
/**
@@ -334,10 +263,6 @@
var service = {
registerAllTours: registerAllTours,
registerTour: registerTour,
registerTours: registerTours,
unregisterTour: unregisterTour,
unregisterTourGroup: unregisterTourGroup,
startTour: startTour,
endTour: endTour,
disableTour: disableTour,
@@ -353,4 +278,4 @@
angular.module("umbraco.services").factory("tourService", tourService);
})();
})();
@@ -14,7 +14,6 @@ function SearchController($scope, searchService, $log, $location, navigationServ
$scope.isSearching = false;
$scope.selectedResult = -1;
$scope.navigateResults = function (ev) {
//38: up 40: down, 13: enter
@@ -34,24 +33,37 @@ function SearchController($scope, searchService, $log, $location, navigationServ
}
};
var group = undefined;
var groupNames = [];
var groupIndex = -1;
var itemIndex = -1;
$scope.selectedItem = undefined;
$scope.clearSearch = function () {
$scope.searchTerm = null;
};
function iterateResults(up) {
//default group
if (!group) {
group = $scope.groups[0];
for (var g in $scope.groups) {
if ($scope.groups.hasOwnProperty(g)) {
groupNames.push(g);
}
}
//Sorting to match the groups order
groupNames.sort();
group = $scope.groups[groupNames[0]];
groupIndex = 0;
}
if (up) {
if (itemIndex === 0) {
if (groupIndex === 0) {
gotoGroup($scope.groups.length - 1, true);
gotoGroup(Object.keys($scope.groups).length - 1, true);
} else {
gotoGroup(groupIndex - 1, true);
}
@@ -62,7 +74,7 @@ function SearchController($scope, searchService, $log, $location, navigationServ
if (itemIndex < group.results.length - 1) {
gotoItem(itemIndex + 1);
} else {
if (groupIndex === $scope.groups.length - 1) {
if (groupIndex === Object.keys($scope.groups).length - 1) {
gotoGroup(0);
} else {
gotoGroup(groupIndex + 1);
@@ -73,7 +85,7 @@ function SearchController($scope, searchService, $log, $location, navigationServ
function gotoGroup(index, up) {
groupIndex = index;
group = $scope.groups[groupIndex];
group = $scope.groups[groupNames[groupIndex]];
if (up) {
gotoItem(group.results.length - 1);
@@ -95,6 +107,13 @@ function SearchController($scope, searchService, $log, $location, navigationServ
$scope.hasResults = false;
if ($scope.searchTerm) {
if (newVal !== null && newVal !== undefined && newVal !== oldVal) {
//Resetting for brand new search
group = undefined;
groupNames = [];
groupIndex = -1;
itemIndex = -1;
$scope.isSearching = true;
navigationService.showSearch();
$scope.selectedItem = undefined;
@@ -114,7 +133,7 @@ function SearchController($scope, searchService, $log, $location, navigationServ
var filtered = {};
_.each(result, function (value, key) {
if (value.results.length > 0) {
filtered[key] = value;
filtered[key] = value;
}
});
$scope.groups = filtered;
+10 -1
View File
@@ -20,8 +20,17 @@ app.run(['userService', '$log', '$rootScope', '$location', 'queryStrings', 'navi
assetsService._loadInitAssets().then(function() {
//Register all of the tours on the server
tourService.registerAllTours().then(function (dashboards) {
tourService.registerAllTours().then(function () {
appReady(data);
// Auto start intro tour
tourService.getTourByAlias("umbIntroIntroduction").then(function (introTour) {
// start intro tour if it hasn't been completed or disabled
if (introTour && introTour.disabled !== true && introTour.completed !== true) {
tourService.startTour(introTour);
}
});
}, function(){
appReady(data);
});
@@ -18,7 +18,7 @@
<div class="control-group">
<label class="control-label" for="email">Email</label>
<div class="controls">
<input type="email" id="email" name="email" placeholder="you@example.com" required ng-model="installer.current.model.email" val-email />
<input type="email" id="email" name="email" placeholder="you@example.com" val-email required ng-model="installer.current.model.email" />
<small class="inline-help">Your email will be used as your login</small>
</div>
</div>
@@ -240,6 +240,7 @@
.umb-tree .umb-tree-node-checked i:before {
/*check box*/
content: "\e165" !important;
font-family: inherit;
}
a.umb-options {
@@ -1,4 +1,4 @@
<form novalidate name="insertMacroForm" ng-submit="submitForm()" ng-controller="Umbraco.Dialogs.InsertMacroController" val-form-manager>
<form novalidate name="insertMacroForm" ng-controller="Umbraco.Dialogs.InsertMacroController" val-form-manager>
<div class="umb-panel">
<div class="umb-panel-footer">
@@ -6,8 +6,8 @@
<a href class="btn btn-link" ng-click="close()">
<localize key="cancel" />
</a>
<button type="submit" class="btn btn-primary">
<localize key="buttons_select"/>
<button type="button" ng-click="submitForm()" class="btn btn-primary">
<localize key="buttons_select" />
</button>
</div>
</div>
@@ -11,7 +11,7 @@
vm.initNextStep = initNextStep;
function initNextStep() {
if(element.val().toLowerCase() === 'my home page') {
if(element.val().toLowerCase() === 'home page') {
$scope.model.nextStep();
} else {
vm.error = true;
@@ -28,19 +28,10 @@ function startUpDynamicContentController($timeout, dashboardResource, assetsServ
vm.startTour = startTour;
function onInit() {
// load tours
tourService.getGroupedTours().then(function(groupedTours) {
vm.tours = groupedTours;
});
// get intro tour
tourService.getTourByAlias("umbIntroIntroduction").then(function (introTour) {
// start intro tour if it hasn't been completed or disabled
if (introTour && introTour.disabled !== true && introTour.completed !== true) {
tourService.startTour(introTour);
}
});
}
function startTour(tour) {
@@ -8,7 +8,7 @@
<a href="" ng-click="createMediaType()" umb-auto-focus>
<i class="large icon-item-arrangement"></i>
<span class="menu-label">
<localize key="general_new">New</localize>&nbsp;
<localize key="general_new">New</localize>
<localize key="content_mediatype">Media type</localize>
</span>
</a>
@@ -261,7 +261,7 @@ angular.module("umbraco")
$scope.openEditorOverlay = function(event, area, index, key) {
$scope.editorOverlay = {
view: "itempicker",
filter: false,
filter: area.$allowedEditors.length > 15,
title: localizationService.localize("grid_insertControl"),
availableItems: area.$allowedEditors,
event: event,
@@ -860,6 +860,14 @@ angular.module("umbraco")
gridService.getGridEditors().then(function (response) {
$scope.availableEditors = response.data;
//Localize the grid editor names
angular.forEach($scope.availableEditors, function (value, key) {
//If no translation is provided, keep using the editor name from the manifest
if (localizationService.dictionary.hasOwnProperty("grid_" + value.alias)) {
value.name = localizationService.localize("grid_" + value.alias);
}
});
$scope.contentReady = true;
// *********************************************
@@ -77,14 +77,14 @@ function includePropsPreValsController($rootScope, $scope, localizationService,
// Return a helper with preserved width of cells
var fixHelper = function (e, ui) {
var h = ui.clone();
h.children().each(function () {
$(this).width($(this).width());
ui.children().each(function () {
$(this).width($(this).width());
});
h.css("background-color", "lightgray");
return h;
var row = ui.clone();
row.css("background-color", "lightgray");
return row;
};
$scope.sortableOptions = {
@@ -96,6 +96,10 @@ function includePropsPreValsController($rootScope, $scope, localizationService,
cursor: 'move',
items: '> tr',
tolerance: 'pointer',
forcePlaceholderSize: true,
start: function(e, ui){
ui.placeholder.height(ui.item.height());
},
update: function (e, ui) {
// Get the new and old index for the moved element (using the text as the identifier)
@@ -20,7 +20,7 @@
<td style="width:100px;"></td>
</tr>
</thead>
<tbody ui-sortable="sortableOptions">
<tbody ui-sortable="sortableOptions" ng-model="model.value">
<tr ng-repeat="val in model.value">
<td>
<i class="icon icon-navigation handle"></i>
@@ -31,6 +31,7 @@
vm.disableUser = disableUser;
vm.enableUser = enableUser;
vm.unlockUser = unlockUser;
vm.changeAvatar = changeAvatar;
vm.clearAvatar = clearAvatar;
vm.save = save;
@@ -356,7 +357,7 @@
});
}
$scope.changeAvatar = function (files, event) {
function changeAvatar(files, event) {
if (files && files.length > 0) {
upload(files[0]);
}
@@ -190,7 +190,7 @@
<a href=""
class="umb-user-group-preview__action"
ngf-select ng-model="filesHolder"
ngf-change="changeAvatar($files, $event)"
ngf-change="model.changeAvatar($files, $event)"
ngf-multiple="false"
ngf-pattern="{{model.acceptedFileTypes}}"
ngf-max-size="{{ model.maxFileSize }}">
@@ -1,7 +1,7 @@
(function () {
"use strict";
function UsersController($scope, $timeout, $location, usersResource, userGroupsResource, userService, localizationService, contentEditingHelper, usersHelper, formHelper, notificationsService, dateHelper) {
function UsersController($scope, $timeout, $location, $routeParams, usersResource, userGroupsResource, userService, localizationService, contentEditingHelper, usersHelper, formHelper, notificationsService, dateHelper) {
var vm = this;
var localizeSaving = localizationService.localize("general_saving");
@@ -124,6 +124,13 @@
vm.usersOptions.orderBy = "Name";
vm.usersOptions.orderDirection = "Ascending";
if ($routeParams.create) {
setUsersViewState("createUser");
}
else if ($routeParams.invite) {
setUsersViewState("inviteUser");
}
// Get users
getUsers();
@@ -168,6 +175,17 @@
if (state === "createUser") {
clearAddUserForm();
$location.search("create", "true");
$location.search("invite", null);
}
else if (state === "inviteUser") {
$location.search("create", null);
$location.search("invite", "true");
}
else if (state === "overview") {
$location.search("create", null);
$location.search("invite", null);
}
vm.usersViewState = state;
+7 -4
View File
@@ -116,8 +116,8 @@
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.4\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core.Mvc, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency-Mvc5.1.8.0.0\lib\net45\ClientDependency.Core.Mvc.dll</HintPath>
@@ -332,8 +332,8 @@
<Name>umbraco.providers</Name>
</ProjectReference>
<Reference Include="System.Xml.Linq" />
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.8.100, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.8\lib\Umbraco.ModelsBuilder.dll</HintPath>
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.10.102, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.10\lib\Umbraco.ModelsBuilder.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -1027,6 +1027,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<DevelopmentServerPort>7800</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7800</IISUrl>
<DevelopmentServerPort>7800</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7800</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
@@ -848,6 +848,12 @@
<key alias="template">Šablona</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -830,6 +830,12 @@ Vennlig hilsen Umbraco roboten
<key alias="template">Mal</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Sett inn element</key>
<key alias="chooseLayout">Velg layout</key>
<key alias="addRows">Legg til rad</key>
@@ -995,6 +995,12 @@
<key alias="template">範本</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">選擇內容類別</key>
<key alias="chooseLayout">選擇排列方式</key>
<key alias="addRows">新增一行</key>
@@ -5,6 +5,15 @@
"group": "Getting Started",
"groupOrder": 100,
"allowDisable": true,
"requiredSections": [
"content",
"media",
"settings",
"developer",
"users",
"member",
"forms"
],
"steps": [
{
"title": "Welcome to Umbraco - The Friendly CMS",
@@ -25,7 +34,6 @@
"content": "Each area in Umbraco is called a <b>Section</b>. Right now you are in the Content section, when you want to go to another section simply click on the appropriate icon in the main menu and you'll be there in no time.",
"backdropOpacity": 0.6
},
{
"element": "#tree",
"elementPreventClick": true,
@@ -88,6 +96,15 @@
"alias": "umbIntroCreateDocType",
"group": "Getting Started",
"groupOrder": 100,
"requiredSections": [
"content",
"media",
"settings",
"developer",
"users",
"member",
"forms"
],
"steps": [
{
"title": "Create your first Document Type",
@@ -117,7 +134,7 @@
{
"element": "[data-element='editor-name-field']",
"title": "Enter a name",
"content": "<p>Your Document Type needs a name. Enter <code>My Home Page</code> in the field and click <b>Next</b>.",
"content": "<p>Your Document Type needs a name. Enter <code>Home Page</code> in the field and click <b>Next</b>.",
"view": "doctypename"
},
{
@@ -203,6 +220,15 @@
"alias": "umbIntroCreateContent",
"group": "Getting Started",
"groupOrder": 100,
"requiredSections": [
"content",
"media",
"settings",
"developer",
"users",
"member",
"forms"
],
"steps": [
{
"title": "Creating your first content node",
@@ -253,6 +279,15 @@
"alias": "umbIntroRenderInTemplate",
"group": "Getting Started",
"groupOrder": 100,
"requiredSections": [
"content",
"media",
"settings",
"developer",
"users",
"member",
"forms"
],
"steps": [
{
"title": "Render your content in a template",
@@ -299,6 +334,15 @@
"alias": "umbIntroViewHomePage",
"group": "Getting Started",
"groupOrder": 100,
"requiredSections": [
"content",
"media",
"settings",
"developer",
"users",
"member",
"forms"
],
"steps": [
{
"title": "View your Umbraco site",
@@ -339,6 +383,15 @@
"alias": "umbIntroMediaSection",
"group": "Getting Started",
"groupOrder": 100,
"requiredSections": [
"content",
"media",
"settings",
"developer",
"users",
"member",
"forms"
],
"steps": [
{
"title": "How to use the media library",
@@ -368,7 +421,8 @@
{
"element": "[data-element='editor-media'] [data-element='editor-name-field']",
"title": "Enter a name",
"content": "<p>Enter <code>My Images</code> in the field.</p>"
"content": "<p>Enter <code>My Images</code> in the field.</p>",
"view": "foldername"
},
{
"element": "[data-element='editor-media'] [data-element='button-save']",
@@ -391,6 +445,7 @@
},
{
"element": "[data-element='editor-media'] [data-element='property-umbracoFile']",
"elementPreventClick": true,
"title": "The uploaded image",
"content": "<p>Here you can see the image you have uploaded.</p>"
},
@@ -417,6 +472,7 @@
},
{
"element": "[data-element='editor-container']",
"elementPreventClick": true,
"title": "Using media items",
"content": "You can reference a media item directly in a template by using the path or try adding a Media Picker to a document type property so you can select media items from the content section."
}
@@ -248,7 +248,7 @@ img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|al
thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],
-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],
-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],
dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],
param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]]]>
</validElements>
@@ -248,7 +248,7 @@ img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|al
thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],
-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],
-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],
dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],
param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]]]>
</validElements>
@@ -271,4 +271,4 @@ param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|cla
}
</config>
</customConfig>
</tinymceConfig>
</tinymceConfig>
+2 -2
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.4" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency-Mvc5" version="1.8.0.0" targetFramework="net45" />
<package id="dotless" version="1.5.2" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
@@ -36,5 +36,5 @@
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
<package id="System.Reflection.Metadata" version="1.0.21" targetFramework="net45" />
<package id="Umbraco.ModelsBuilder" version="3.0.8" targetFramework="net45" />
<package id="Umbraco.ModelsBuilder" version="3.0.10" targetFramework="net45" />
</packages>
@@ -43,6 +43,7 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="robots" content="noindex, nofollow">
<meta name="pinterest" content="nopin" />
<title ng-bind="$root.locationTitle">Umbraco</title>
@@ -11,6 +11,7 @@
<header>Macro</header>
<usercontrol>/create/simple.ascx</usercontrol>
<tasks>
<create assembly="umbraco" type="macroTasks" />
<delete assembly="umbraco" type="macroTasks" />
</tasks>
</nodeType>
@@ -11,6 +11,7 @@
<header>Macro</header>
<usercontrol>/create/simple.ascx</usercontrol>
<tasks>
<create assembly="umbraco" type="macroTasks" />
<delete assembly="umbraco" type="macroTasks" />
</tasks>
</nodeType>
@@ -252,7 +252,7 @@
<key alias="documentTypeWithoutTemplate">Dokumenttype uden skabelon</key>
<key alias="newFolder">Ny mappe</key>
<key alias="newDataType">Ny datatype</key>
<key alias="newJavascriptFile">Ny javascript fil</key>
<key alias="newJavascriptFile">Ny JavaScript-fil</key>
<key alias="newEmptyPartialView">Ny tom partial view</key>
<key alias="newFolder">Ny mappe</key>
<key alias="newPartialViewMacro">Ny partial view makro</key>
@@ -1219,6 +1219,12 @@ Mange hilsner fra Umbraco robotten
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Vælg indholdstype</key>
<key alias="chooseLayout">Vælg layout</key>
<key alias="addRows">Tilføj række</key>
@@ -850,6 +850,12 @@ Wenn Sie sich für Runway entscheiden, können Sie optional Blöcke nutzen, die
<key alias="template">Vorlage</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Element hinzufügen</key>
<key alias="addRows">Zeilenlayout auswählen</key>
<key alias="addElement">Element mit &lt;i class="icon icon-add blue"&gt;&lt;/i&gt; hinzufügen</key>
@@ -1506,6 +1506,12 @@ To manage your website, simply open the Umbraco back office and start adding con
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -1954,7 +1960,7 @@ To manage your website, simply open the Umbraco back office and start adding con
</body>
</html>]]>
</key>
<key alias="invite">Invite</key>
</area>
<area alias="validation">
@@ -1512,6 +1512,12 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="template">Template</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -1958,6 +1964,7 @@ To manage your website, simply open the Umbraco back office and start adding con
</body>
</html>]]>
</key>
<key alias="invite">Invite</key>
</area>
<area alias="validation">
<key alias="validation">Validation</key>
@@ -754,6 +754,12 @@
<key alias="template">Plantilla</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Insertar control</key>
<key alias="chooseLayout">Choose layout</key>
<key alias="addRows">Añade más filas</key>
@@ -1201,6 +1201,12 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choisissez le type de contenu</key>
<key alias="chooseLayout">Choisissez une mise en page</key>
<key alias="addRows">Ajouter une ligne</key>
@@ -745,6 +745,12 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="template">תבנית</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -732,6 +732,12 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i
<key alias="template">Template</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -976,6 +976,12 @@ Runwayをインストールして作られた新しいウェブサイトがど
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">挿入するアイテムを選択する</key>
<key alias="addLayout">レイアウトを選択</key>
<key alias="addRows">行の追加</key>
@@ -727,6 +727,12 @@
<key alias="template">템플릿</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -1039,6 +1039,12 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
<key alias="template">Sjabloon</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Item toevoegen</key>
<key alias="chooseLayout">Kies de indeling</key>
<key alias="addRows">Kies een indeling voor deze pagina om content toe te kunnen voegen</key>
@@ -1274,6 +1274,12 @@ Naciśnij przycisk <strong>instaluj</strong>, aby zainstalować bazę danych Umb
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Wybierz typ treści</key>
<key alias="chooseLayout">Wybierz układ</key>
<key alias="addRows">Dodaj wiersz</key>
@@ -715,6 +715,12 @@ Você pode publicar esta página e todas suas sub-páginas ao selecionar <em>pub
<key alias="template">Modelo</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Choose type of content</key>
<key alias="chooseLayout">Choose a layout</key>
<key alias="addRows">Add a row</key>
@@ -667,6 +667,12 @@
<key alias="text">Текст</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="addElement">Добавить содержимое</key>
<key alias="dropElement">Сбросить содержимое</key>
<key alias="addGridLayout">Добавить шаблон сетки</key>
@@ -780,6 +780,12 @@
<key alias="template">Sidmall</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Lägg till</key>
<key alias="chooseLayout">Choose layout</key>
<key alias="addRows">Lägg till rad</key>
@@ -930,6 +930,12 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="template">Template</key>
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">Insert control</key>
<key alias="addRows">Choose a layout for the page</key>
<key alias="addElement"><![CDATA[To start, click the <i class="icon icon-add blue"></i> below and add your first element]]></key>
@@ -1230,6 +1230,12 @@
</area>
<area alias="grid">
<key alias="rte">Rich Text Editor</key>
<key alias="media">Image</key>
<key alias="macro">Macro</key>
<key alias="embed">Embed</key>
<key alias="headline">Headline</key>
<key alias="quote">Quote</key>
<key alias="insertControl">选择内容类别</key>
<key alias="chooseLayout">选择一项布局</key>
<key alias="addRows">添加一行</key>
@@ -1,6 +1,6 @@
using System;
using System.Linq;
using System.Web.Script.Serialization;
using System.Web;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Cache;
@@ -83,36 +83,28 @@ namespace Umbraco.Web.Cache
public override void Refresh(string jsonPayload)
{
ClearCache(DeserializeFromJsonPayload(jsonPayload));
ClearCache();
base.Refresh(jsonPayload);
}
public override void Refresh(int id)
{
ClearCache(FromMemberGroup(ApplicationContext.Current.Services.MemberGroupService.GetById(id)));
ClearCache();
base.Refresh(id);
}
public override void Remove(int id)
{
ClearCache(FromMemberGroup(ApplicationContext.Current.Services.MemberGroupService.GetById(id)));
ClearCache();
base.Remove(id);
}
private void ClearCache(params JsonPayload[] payloads)
private void ClearCache()
{
if (payloads == null) return;
var memberGroupCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<IMemberGroup>();
payloads.ForEach(payload =>
{
if (payload != null && memberGroupCache)
{
memberGroupCache.Result.ClearCacheByKeySearch(string.Format("{0}.{1}", typeof(IMemberGroup).FullName, payload.Name));
memberGroupCache.Result.ClearCacheItem(RepositoryBase.GetCacheIdKey<IMemberGroup>(payload.Id));
}
});
// Since we cache by group name, it could be problematic when renaming to
// previously existing names - see http://issues.umbraco.org/issue/U4-10846.
// To work around this, just clear all the cache items
ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.ClearCache<IMemberGroup>();
}
}
}
}
@@ -1,11 +1,7 @@
using System;
using System.Linq;
using System.Web.Mvc;
using System.Web.Security;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.member;
using Umbraco.Core;
using Umbraco.Core.Security;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
@@ -21,6 +17,13 @@ namespace Umbraco.Web.Controllers
return CurrentUmbracoPage();
}
// U4-10762 Server error with "Register Member" snippet (Cannot save member with empty name)
// If name field is empty, add the email address instead
if (string.IsNullOrEmpty(model.Name) && string.IsNullOrEmpty(model.Email) == false)
{
model.Name = model.Email;
}
MembershipCreateStatus status;
var member = Members.RegisterMember(model, out status, model.LoginOnSuccess);
@@ -36,7 +39,6 @@ namespace Umbraco.Web.Controllers
return Redirect(model.RedirectUrl);
}
//redirect to current page by default
return RedirectToCurrentUmbracoPage();
case MembershipCreateStatus.InvalidUserName:
ModelState.AddModelError((model.UsernameIsEmail || model.Username == null)
+24 -7
View File
@@ -7,13 +7,10 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi.Filters;
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.Editors
{
[PluginController("UmbracoApi")]
[UmbracoApplicationAuthorize(Constants.Applications.Content)]
public class TourController : UmbracoAuthorizedJsonController
{
public IEnumerable<BackOfficeTourFile> GetTours()
@@ -24,7 +21,7 @@ namespace Umbraco.Web.Editors
return result;
var filters = TourFilterResolver.Current.Filters.ToList();
//get all filters that will be applied to all tour aliases
var aliasOnlyFilters = filters.Where(x => x.PluginName == null && x.TourFileName == null).ToList();
@@ -65,8 +62,28 @@ namespace Umbraco.Web.Editors
}
}
}
//Get all allowed sections for the current user
var allowedSections = UmbracoContext.Current.Security.CurrentUser.AllowedSections.ToList();
return result.OrderBy(x => x.FileName, StringComparer.InvariantCultureIgnoreCase);
var toursToBeRemoved = new List<BackOfficeTourFile>();
//Checking to see if the user has access to the required tour sections, else we remove the tour
foreach (var backOfficeTourFile in result)
{
foreach (var tour in backOfficeTourFile.Tours)
{
foreach (var toursRequiredSection in tour.RequiredSections)
{
if (allowedSections.Contains(toursRequiredSection) == false)
{
toursToBeRemoved.Add(backOfficeTourFile);
break;
}
}
}
}
return result.Except(toursToBeRemoved).OrderBy(x => x.FileName, StringComparer.InvariantCultureIgnoreCase);
}
private void TryParseTourFile(string tourFile,
@@ -80,7 +97,7 @@ namespace Umbraco.Web.Editors
//get the filters specific to this file
var fileFilters = filters.Where(x => x.TourFileName != null && x.TourFileName.IsMatch(fileName)).ToList();
//If there is any filter applied to match the file only (no tour alias) then ignore the file entirely
var isFileFiltered = fileFilters.Any(x => x.TourAlias == null);
if (isFileFiltered) return;
@@ -118,4 +135,4 @@ namespace Umbraco.Web.Editors
}
}
}
}
}
@@ -50,6 +50,18 @@ namespace Umbraco.Web
/// <returns></returns>
IEnumerable<IPublishedContent> TypedSearch(string term, bool useWildCards = true, string searchProvider = null);
/// <summary>
/// Searches content
/// </summary>
/// <param name="skip"></param>
/// <param name="take"></param>
/// <param name="totalRecords"></param>
/// <param name="term"></param>
/// <param name="useWildCards"></param>
/// <param name="searchProvider"></param>
/// <returns></returns>
IEnumerable<IPublishedContent> TypedSearch(int skip, int take, out int totalRecords, string term, bool useWildCards = true, string searchProvider = null);
/// <summary>
/// Searhes content
/// </summary>
@@ -57,5 +69,16 @@ namespace Umbraco.Web
/// <param name="searchProvider"></param>
/// <returns></returns>
IEnumerable<IPublishedContent> TypedSearch(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null);
/// <summary>
/// Searhes content
/// </summary>
/// <param name="totalrecords"></param>
/// <param name="criteria"></param>
/// <param name="searchProvider"></param>
/// <param name="skip"></param>
/// <param name="take"></param>
/// <returns></returns>
IEnumerable<IPublishedContent> TypedSearch(int skip, int take, out int totalrecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null);
}
}
+4 -1
View File
@@ -1,4 +1,5 @@
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models
{
@@ -18,6 +19,8 @@ namespace Umbraco.Web.Models
public int GroupOrder { get; set; }
[DataMember(Name = "allowDisable")]
public bool AllowDisable { get; set; }
[DataMember(Name = "requiredSections")]
public List<string> RequiredSections { get; set; }
[DataMember(Name = "steps")]
public BackOfficeTourStep[] Steps { get; set; }
}
@@ -65,6 +65,8 @@ namespace Umbraco.Web.Models.Mapping
if (source.DefaultTemplate != null)
dest.SetDefaultTemplate(applicationContext.Services.FileService.GetTemplate(source.DefaultTemplate));
else
dest.SetDefaultTemplate(null);
ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext);
});
@@ -204,10 +204,24 @@ namespace Umbraco.Web.Models.Mapping
var allContentPermissions = applicationContext.Services.UserService.GetPermissions(@group, true)
.ToDictionary(x => x.EntityId, x => x);
var contentEntities = allContentPermissions.Keys.Count == 0
? new IUmbracoEntity[0]
: applicationContext.Services.EntityService.GetAll(UmbracoObjectTypes.Document, allContentPermissions.Keys.ToArray());
IEnumerable<IUmbracoEntity> contentEntities;
if (allContentPermissions.Keys.Count == 0)
{
contentEntities = new IUmbracoEntity[0];
}
else
{
// a group can end up with way more than 2000 assigned permissions,
// so we need to break them into groups in order to avoid breaking
// the entity service due to too many Sql parameters.
var list = new List<IUmbracoEntity>();
contentEntities = list;
var entityService = applicationContext.Services.EntityService;
foreach (var idGroup in allContentPermissions.Keys.InGroupsOf(2000))
list.AddRange(entityService.GetAll(UmbracoObjectTypes.Document, idGroup.ToArray()));
}
var allAssignedPermissions = new List<AssignedContentPermissions>();
foreach (var entity in contentEntities)
@@ -376,8 +390,8 @@ namespace Umbraco.Web.Models.Mapping
};
}
private IEnumerable<EntityBasic> GetStartNodeValues(int[] startNodeIds,
ILocalizedTextService textService, IEntityService entityService, UmbracoObjectTypes objectType,
private IEnumerable<EntityBasic> GetStartNodeValues(int[] startNodeIds,
ILocalizedTextService textService, IEntityService entityService, UmbracoObjectTypes objectType,
string localizedKey)
{
if (startNodeIds.Length > 0)
@@ -392,7 +406,7 @@ namespace Umbraco.Web.Models.Mapping
return startNodes;
}
return Enumerable.Empty<EntityBasic>();
}
}
private void MapUserGroupBasic(ServiceContext services, dynamic group, UserGroupBasic display)
{
+1 -1
View File
@@ -30,7 +30,7 @@ namespace Umbraco.Web.Models.Trees
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
internal MenuItem Add(IAction action, string name)
{
var item = new MenuItem(action);
var item = new MenuItem(action, name);
DetectLegacyActionMenu(action.GetType(), item);
+39 -22
View File
@@ -1,6 +1,5 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
@@ -13,8 +12,10 @@ namespace Umbraco.Web.Mvc
/// <summary>
/// Allows for Model Binding any IPublishedContent or IRenderModel
/// </summary>
public class RenderModelBinder : DefaultModelBinder, IModelBinder, IModelBinderProvider
public class RenderModelBinder : DefaultModelBinder, IModelBinderProvider
{
public static RenderModelBinder Instance = new RenderModelBinder();
/// <summary>
/// Binds the model to a value by using the specified controller context and binding context.
/// </summary>
@@ -132,10 +133,30 @@ namespace Umbraco.Web.Mvc
return null;
}
public class ModelBindingArgs : EventArgs
{
public ModelBindingArgs(Type sourceType, Type modelType, StringBuilder message)
{
SourceType = sourceType;
ModelType = modelType;
Message = message;
}
public bool SourceIsContent;
public bool ViewModelIsContent;
public Type SourceType { get; set; }
public Type ModelType { get; set; }
public StringBuilder Message { get; private set; }
public bool Restart { get; set; }
}
public static event EventHandler<ModelBindingArgs> ModelBindingException;
private static void ThrowModelBindingException(bool sourceContent, bool modelContent, Type sourceType, Type modelType)
{
var msg = new StringBuilder();
// prepare message
msg.Append("Cannot bind source");
if (sourceContent) msg.Append(" content");
msg.Append(" type ");
@@ -146,28 +167,24 @@ namespace Umbraco.Web.Mvc
msg.Append(modelType.FullName);
msg.Append(".");
// compare FullName for the time being because when upgrading ModelsBuilder,
// Umbraco does not know about the new attribute type - later on, can compare
// on type directly (ie after v7.4.2).
var sourceAttr = sourceType.Assembly.CustomAttributes.FirstOrDefault(x =>
x.AttributeType.FullName == "Umbraco.ModelsBuilder.PureLiveAssemblyAttribute");
var modelAttr = modelType.Assembly.CustomAttributes.FirstOrDefault(x =>
x.AttributeType.FullName == "Umbraco.ModelsBuilder.PureLiveAssemblyAttribute");
// raise event, to give model factories a chance at reporting
// the error with more details, and optionally request that
// the application restarts.
// bah.. names are App_Web_all.generated.cs.8f9494c4.jjuvxz55 so they ARE different, fuck!
// we cannot compare purely on type.FullName 'cos we might be trying to map Sub to Main = fails!
if (sourceAttr != null && modelAttr != null
&& sourceType.Assembly.GetName().Version.Revision != modelType.Assembly.GetName().Version.Revision)
var args = new ModelBindingArgs(sourceType, modelType, msg);
if (ModelBindingException != null)
ModelBindingException(Instance, args);
if (args.Restart)
{
msg.Append(" Types come from two PureLive assemblies with different versions,");
msg.Append(" this usually indicates that the application is in an unstable state.");
msg.Append(" The application is restarting now, reload the page and it should work.");
var context = HttpContext.Current;
if (context == null)
AppDomain.Unload(AppDomain.CurrentDomain);
else
ApplicationContext.Current.RestartApplicationPool(new HttpContextWrapper(context));
}
msg.Append(" The application is restarting now.");
var context = HttpContext.Current;
if (context == null)
AppDomain.Unload(AppDomain.CurrentDomain);
else
ApplicationContext.Current.RestartApplicationPool(new HttpContextWrapper(context));
}
throw new ModelBindingException(msg.ToString());
}
@@ -47,7 +47,6 @@ using System.Security;
[assembly: InternalsVisibleTo("Umbraco.Forms.Core.Providers")]
[assembly: InternalsVisibleTo("Umbraco.Forms.Web")]
[assembly: InternalsVisibleTo("Umbraco.Headless")]
//allow custom unit-testing code to access internals through custom adapters
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")] // backwards compat.

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