Compare commits
525 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1607e51270 | |||
| 2f31175db5 | |||
| 044b43f6e1 | |||
| 9178e7afcf | |||
| b18945e630 | |||
| 4640cf56d1 | |||
| eae1ce7012 | |||
| e900711180 | |||
| 93f4d65227 | |||
| a4c0342bda | |||
| 095633ba27 | |||
| c63156fcd8 | |||
| c59a226d56 | |||
| 0c25c36af0 | |||
| 84a90884e3 | |||
| d29b7311fa | |||
| 17b59cc20f | |||
| 4423571eaa | |||
| e76c42f874 | |||
| 151c35bc47 | |||
| 84265a9716 | |||
| 6618388973 | |||
| 527f98189a | |||
| 78c289a559 | |||
| 646abb3aea | |||
| 2af59471a2 | |||
| 090f89e5b6 | |||
| 4870afd2d3 | |||
| 80257b6684 | |||
| 8f3a0b6919 | |||
| 9fd2f34343 | |||
| e774717346 | |||
| 7cd540c37e | |||
| 83595ecaf5 | |||
| f2819f61e5 | |||
| 2107e9d9e3 | |||
| c623b448ba | |||
| 8bb49f57e8 | |||
| da0b1c2f23 | |||
| a288fc62eb | |||
| 82e50ccd3a | |||
| 15b0dc9f29 | |||
| 8057d09fc2 | |||
| 8877100bf0 | |||
| 41c96e6e26 | |||
| abdd117264 | |||
| 6272dac698 | |||
| 7a4b5fa796 | |||
| c962132ee0 | |||
| 0780979469 | |||
| a42e568fdf | |||
| e62661cc6a | |||
| 6841b2ac61 | |||
| f7f4276485 | |||
| bb9e23ca3e | |||
| 7d5d69e2e3 | |||
| ee75158dd0 | |||
| c022397d86 | |||
| d104525a50 | |||
| b0a64aa4b5 | |||
| ca86385269 | |||
| ef4322a9b3 | |||
| 4ab1c51327 | |||
| e007a37c36 | |||
| 2f67008987 | |||
| 1672e284c5 | |||
| 60ce36a7f2 | |||
| 72e2cacc87 | |||
| 4285102422 | |||
| abbcf0e26b | |||
| 347b25472f | |||
| b745948dc6 | |||
| 8007c8869f | |||
| b51a328ead | |||
| f3b8f2eb5f | |||
| de4628f450 | |||
| b0a64655b4 | |||
| 48d88ec8fa | |||
| 7ca151a3fa | |||
| 363c8fab2c | |||
| 8d4fd9d1cf | |||
| 24071eb3b1 | |||
| 62ffbe7cf0 | |||
| f2d6b47e47 | |||
| f3541908c7 | |||
| 4e57e1cc18 | |||
| 410afffaa9 | |||
| 936e94789d | |||
| 468a56e5de | |||
| 468ec8824a | |||
| cad913b7a1 | |||
| 382103d99d | |||
| cbb6b9bca0 | |||
| a1b90a50cd | |||
| 9ea5855073 | |||
| 4a37433042 | |||
| 91469812d3 | |||
| 68a8eb7f3f | |||
| 2e7baabb94 | |||
| 57745fe71d | |||
| de6f9236e7 | |||
| a00c59e8b5 | |||
| 05c2da807f | |||
| 0fd8ca43d6 | |||
| 87f09b2ee6 | |||
| e466878925 | |||
| 319acc199e | |||
| 2a982f21a7 | |||
| 3ff455f11d | |||
| 41ad1bf27b | |||
| f49d939a2d | |||
| 7e1e83b493 | |||
| 42959a1db5 | |||
| a1cd22208b | |||
| c3116d5df7 | |||
| b0b874212e | |||
| 19086ab3a1 | |||
| 069594c3ac | |||
| 0bc4c7e2aa | |||
| 83294b6594 | |||
| e0c89eb1ea | |||
| 9ad8e6a876 | |||
| 14b58386e5 | |||
| e26cbccfe0 | |||
| 7dc06c1bea | |||
| effa984bdc | |||
| fa058f348d | |||
| 9284269428 | |||
| d7f2041ee9 | |||
| 9f6e6e4701 | |||
| 34ba3f3351 | |||
| dcfb8b94d8 | |||
| 0876004d9a | |||
| d3ad61835a | |||
| ad882ab5be | |||
| 774f333c70 | |||
| bba58ea0c0 | |||
| d0d4885812 | |||
| ce11a377e6 | |||
| c6443c477f | |||
| eb94572361 | |||
| fd8317493e | |||
| 22ff1bcaa0 | |||
| c3be9004f6 | |||
| 11fa015b64 | |||
| f5f3676a56 | |||
| f69f68e2b5 | |||
| 3858656015 | |||
| a5ec5f46ac | |||
| ea70e18a91 | |||
| 0cfd5773c3 | |||
| b15def99c7 | |||
| 8c8b6984c2 | |||
| dc7b83ca6c | |||
| fcf9dcd803 | |||
| 070fa11f8c | |||
| 7e9f55f517 | |||
| 3556043b55 | |||
| 8c70578764 | |||
| 5cb2dd0036 | |||
| a9713dc6fc | |||
| b32e7d4ccc | |||
| 8d4958e395 | |||
| 9883757704 | |||
| 0310782d7d | |||
| c81e14758d | |||
| 9b33c94437 | |||
| 2a30fd238e | |||
| 3cb4128c0f | |||
| 79958e0fe0 | |||
| f238f9fcea | |||
| 7c545410cc | |||
| dcf5fff3f0 | |||
| 1dc88658e8 | |||
| e17f75a18a | |||
| 88c20c7c5f | |||
| bd9adffaa5 | |||
| 0ce059d5bd | |||
| 773ef1d168 | |||
| 1f7de81cd2 | |||
| fef9e3fde0 | |||
| e849d2d0d0 | |||
| 9a6123579f | |||
| 591a881283 | |||
| 1554d52ea9 | |||
| 6f55b84c65 | |||
| 43f369f96f | |||
| aed476de0a | |||
| 9e2c7d16a6 | |||
| 680d97c630 | |||
| 89347b359b | |||
| 8053cea92d | |||
| ae07f34215 | |||
| 50335723b0 | |||
| 6f1bd3fd71 | |||
| 91e658c41c | |||
| 6939cc757e | |||
| 2baec8a129 | |||
| 93a1fc1eba | |||
| 5d694a73a3 | |||
| af369fa6c7 | |||
| 901036535d | |||
| 5d6cbee196 | |||
| 9e9ae09ec2 | |||
| 58697eaa04 | |||
| ce58ad91b5 | |||
| e49d14d687 | |||
| e010ff2a8c | |||
| 00cec3267c | |||
| 4bfb2d219b | |||
| 80c61110df | |||
| 8e47f91ba5 | |||
| 31f6bd4c02 | |||
| 3e5744dbb7 | |||
| cb0d8320e6 | |||
| 53d9b65e64 | |||
| df0fe62fca | |||
| 483a2c7c02 | |||
| 084fde885a | |||
| 50a5679b5c | |||
| 2c248791e1 | |||
| 6b6a7fe231 | |||
| 6fd197d1bf | |||
| 00aa59c9c6 | |||
| 06254ba462 | |||
| 684cb19a7c | |||
| 9c5da12653 | |||
| 83f229abc6 | |||
| 3405a1f600 | |||
| 8be02ff7b0 | |||
| c371f00315 | |||
| 0ccf798f14 | |||
| 6ca94074f3 | |||
| 8236eee7a6 | |||
| 8bdeca6374 | |||
| e37bbdfcf4 | |||
| dac882ce9f | |||
| 2dc11f6fa1 | |||
| fe2e689865 | |||
| ece5fecf12 | |||
| b21dea84d9 | |||
| 492b0aadc8 | |||
| b399630202 | |||
| b9b1fc3a70 | |||
| 1d52f59657 | |||
| 78f6b8d8bc | |||
| 0afee71e9e | |||
| ffa7b922e8 | |||
| e6de9e0004 | |||
| 08aff2654a | |||
| cd0fdae47b | |||
| 0f3a76809b | |||
| 4f88da2c26 | |||
| 4ce0553630 | |||
| b1b285b673 | |||
| c773714e2d | |||
| 2a90478ba7 | |||
| 77162e4b51 | |||
| 93756a62f4 | |||
| 2343004be1 | |||
| d6fe350a4a | |||
| 23321f8ac9 | |||
| 71902f3b9b | |||
| 13b544521d | |||
| 2cf8c1207d | |||
| ab8653d3de | |||
| 748a3c167e | |||
| 5b93b35882 | |||
| b29ee4df60 | |||
| d8fe3c6faf | |||
| 9260f943ff | |||
| dcdaa8d62d | |||
| 9b7a9fc988 | |||
| 62485157ad | |||
| 4ce7b089ca | |||
| 9e91098ebd | |||
| 49356b31a1 | |||
| 507c2353e9 | |||
| d02139bbcd | |||
| 8a19b97900 | |||
| 981fad1ec8 | |||
| 019147c1a1 | |||
| 782d6100f0 | |||
| e17690fbed | |||
| d7d1b3f2a0 | |||
| 5b19d5e0d8 | |||
| 7c21889239 | |||
| 52d35c06eb | |||
| 52c3ea24d5 | |||
| 03756ab894 | |||
| 8e35d904cb | |||
| 9808492509 | |||
| 81788338e3 | |||
| 3ffe1517e0 | |||
| 641e74b747 | |||
| 49c316e13d | |||
| 5235053523 | |||
| af6d2df823 | |||
| bbe80d882a | |||
| 408ec17201 | |||
| a4ef487fab | |||
| 8208f8de51 | |||
| e8ea7f9d29 | |||
| e431a41fc1 | |||
| 1f5c9d2e1b | |||
| 372f981d33 | |||
| 6f03e221c6 | |||
| 90a5adec8f | |||
| 62939385a0 | |||
| d4729e1483 | |||
| 9de35f0202 | |||
| 773d249d36 | |||
| d12a492cb6 | |||
| ef0b521083 | |||
| 6261447923 | |||
| d18881c8ad | |||
| 89596dbe0b | |||
| 358536ffaa | |||
| 4592f8e8d8 | |||
| 0038d173a2 | |||
| 68e6ad76fb | |||
| 6462329494 | |||
| 2fdd1c0bd2 | |||
| 891bea81bf | |||
| f71577f86e | |||
| e3e88b3679 | |||
| 5dc993890d | |||
| a2025c14b1 | |||
| 34f811c128 | |||
| 7e4c284abb | |||
| 664d0c5160 | |||
| eb26fb901f | |||
| 3141b04376 | |||
| 201fb5dc01 | |||
| 15e668c056 | |||
| a42f425971 | |||
| 3f4774855e | |||
| 28f995cea6 | |||
| cfb14d7089 | |||
| ef4d41c80a | |||
| 584e47f51f | |||
| 66e40fcbb0 | |||
| 4ed236249a | |||
| 00a4287945 | |||
| 92d52bf99b | |||
| 2e611c20d4 | |||
| ae10f3d21f | |||
| 7a9b392f69 | |||
| 493d71dba9 | |||
| 55d4e4072a | |||
| f687b34c14 | |||
| 507517c1ad | |||
| ae8cfb2b23 | |||
| 9048252826 | |||
| e76819a570 | |||
| 87c311d6e7 | |||
| 86d8eae984 | |||
| 6aac216763 | |||
| b7c3fb7f30 | |||
| a0a3b7e9c9 | |||
| d98db5e6bc | |||
| 48adc4c98d | |||
| 79d4562cb1 | |||
| f48263e5a2 | |||
| 63196d7e53 | |||
| 72a0d614af | |||
| 4f8bb7fb51 | |||
| 1c883be16b | |||
| 73d681d674 | |||
| 8daa558997 | |||
| b78fd0f6ac | |||
| 831eb3ef5e | |||
| fa68bee762 | |||
| 796700b4fe | |||
| ab09042fdc | |||
| 041d4a4a8b | |||
| ee79d7ecdc | |||
| e33456d168 | |||
| df2c104002 | |||
| f265fa683c | |||
| 12093ae7ea | |||
| 6a980e64eb | |||
| 37071ada78 | |||
| 3c7e820773 | |||
| 203837aa84 | |||
| 5fe63c2c1a | |||
| 2c1d85989f | |||
| d518ab908e | |||
| bc32ff31d4 | |||
| 7804677f2b | |||
| 27c884f4eb | |||
| a966f63bbd | |||
| 76f9e6baee | |||
| 49f17be9df | |||
| 8a114a105e | |||
| 5f9865cc73 | |||
| b891b18b20 | |||
| bc461b1646 | |||
| b0eeaecf1c | |||
| 2708f11fcd | |||
| c59ac4ee0e | |||
| a03aa9cbab | |||
| 89b714c960 | |||
| d9b0b0112e | |||
| 6640039cdf | |||
| 70deffd418 | |||
| f31d5b12da | |||
| 7fd6155807 | |||
| 043c677ddc | |||
| f634d9f8b1 | |||
| db637d9c31 | |||
| 24b521881c | |||
| 0b3a38ec8f | |||
| 330673bef9 | |||
| 661ff0e726 | |||
| e1c45fda9a | |||
| b45a4a18f2 | |||
| 1456e7028a | |||
| b38ee33e5a | |||
| 903a9f93c3 | |||
| b08376651a | |||
| 75514c7c42 | |||
| ea6f561c96 | |||
| 053544a578 | |||
| 4308718c88 | |||
| 1b59ca0412 | |||
| 282cc0c722 | |||
| 4584abaa72 | |||
| c1ca0c9c2f | |||
| 27c260cd03 | |||
| 73a5c55547 | |||
| b8831c253e | |||
| b2d3e75566 | |||
| cb526170e2 | |||
| 93237bfdb8 | |||
| 1c39c741b6 | |||
| ec2589f517 | |||
| 2ca6e8be9a | |||
| b9d1a776cb | |||
| 5eb609d8a0 | |||
| 4d5069726b | |||
| 0da8644e77 | |||
| e643189b10 | |||
| 97716d5570 | |||
| 5517252200 | |||
| 92a5c31ce6 | |||
| 345c038e8b | |||
| 59defa6b11 | |||
| 7e0d7ebbd4 | |||
| c13d4ed235 | |||
| a47b5035fe | |||
| f6be389f4f | |||
| 252f0fe88e | |||
| 387faca71e | |||
| 6c172702be | |||
| 62cda02ded | |||
| 3e2a6424bd | |||
| c0f695bcf9 | |||
| 2e1e2e4325 | |||
| 1316bb5d5b | |||
| fe97860694 | |||
| 98b4aa6bae | |||
| eb7f4e74f2 | |||
| 4a9e326267 | |||
| 67edc6cf9a | |||
| e740838ef7 | |||
| dec44b1288 | |||
| 98a0729549 | |||
| 97868593f8 | |||
| dcdfb074af | |||
| a36b1097c5 | |||
| e268a05f6e | |||
| fb7d22dca8 | |||
| bac53bc241 | |||
| ce690acda0 | |||
| cb8157dfca | |||
| 4c7c6e37d1 | |||
| 116e53e07d | |||
| a74c4433f7 | |||
| 2ccf74a921 | |||
| f3a81d82be | |||
| 5451d28fe4 | |||
| db57268440 | |||
| ac265067e8 | |||
| 5330830362 | |||
| 4b6b24b2f5 | |||
| 7d5d89e9cb | |||
| ab85cbf599 | |||
| c6937618c2 | |||
| ef84d63982 | |||
| 280a7445f4 | |||
| 5ae8a47f4b | |||
| bc148d08fa | |||
| 57a1e73383 | |||
| c7b9a57795 | |||
| eb1edf94d3 | |||
| c0b230a95e | |||
| 607c2cc8e7 | |||
| 48d3a3defd | |||
| 8509285aae | |||
| 2413e9951f | |||
| 1a444fd703 | |||
| bd68a140ba | |||
| 7b34211bb1 | |||
| fa78223229 | |||
| 39c19dc1d4 | |||
| 7b4b6357cb | |||
| 4454290820 | |||
| d94cd9dc8d | |||
| 8c07af9505 | |||
| d32fb44187 | |||
| dd38480ce2 | |||
| 08e8e3918e | |||
| 7a3591d1bd | |||
| 59ab7f5c8d | |||
| c2b2182182 | |||
| 66b656f058 | |||
| c8f7ecabf4 | |||
| 9137249510 | |||
| 841074fc27 | |||
| 64f477f90e | |||
| 813741bc3d | |||
| 7c72e70967 | |||
| 75b74a6687 | |||
| 7dcb4435d8 |
+11
-5
@@ -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
|
||||
@@ -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
|
||||
@@ -29,7 +29,7 @@
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.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)" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.7.8")]
|
||||
[assembly: AssemblyInformationalVersion("7.7.8")]
|
||||
[assembly: AssemblyFileVersion("7.7.12")]
|
||||
[assembly: AssemblyInformationalVersion("7.7.12")]
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Xml.Linq;
|
||||
using ClientDependency.Core.CompositeFiles.Providers;
|
||||
using ClientDependency.Core.Config;
|
||||
using Semver;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -24,10 +28,74 @@ namespace Umbraco.Core.Configuration
|
||||
_logger = logger;
|
||||
_fileName = IOHelper.MapPath(string.Format("{0}/ClientDependency.config", SystemDirectories.Config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the version number in ClientDependency.config to a hashed value for the version and the DateTime.Day
|
||||
/// </summary>
|
||||
/// <param name="version">The <see cref="SemVersion">version</see> of Umbraco we're upgrading to</param>
|
||||
/// <param name="date">A <see cref="DateTime">date</see> value to use in the hash to prevent this method from updating the version on each startup</param>
|
||||
/// <param name="dateFormat">Allows the developer to specify the <see cref="string">date precision</see> for the hash (i.e. "yyyyMMdd" would be a precision for the day)</param>
|
||||
/// <returns>Boolean to indicate succesful update of the ClientDependency.config file</returns>
|
||||
public bool UpdateVersionNumber(SemVersion version, DateTime date, string dateFormat)
|
||||
{
|
||||
var byteContents = Encoding.Unicode.GetBytes(version + date.ToString(dateFormat));
|
||||
|
||||
//This is a way to convert a string to a long
|
||||
//see https://www.codeproject.com/Articles/34309/Convert-String-to-bit-Integer
|
||||
//We could much more easily use MD5 which would create us an INT but since that is not compliant with
|
||||
//hashing standards we have to use SHA
|
||||
int intHash;
|
||||
using (var hash = SHA256.Create())
|
||||
{
|
||||
var bytes = hash.ComputeHash(byteContents);
|
||||
|
||||
var longResult = new[] { 0, 8, 16, 24 }
|
||||
.Select(i => BitConverter.ToInt64(bytes, i))
|
||||
.Aggregate((x, y) => x ^ y);
|
||||
|
||||
//CDF requires an INT, and although this isn't fail safe, it will work for our purposes. We are not hashing for crypto purposes
|
||||
//so there could be some collisions with this conversion but it's not a problem for our purposes
|
||||
//It's also important to note that the long.GetHashCode() implementation in .NET is this: return (int) this ^ (int) (this >> 32);
|
||||
//which means that this value will not change per appdomain like some GetHashCode implementations.
|
||||
intHash = longResult.GetHashCode();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var clientDependencyConfigXml = XDocument.Load(_fileName, LoadOptions.PreserveWhitespace);
|
||||
if (clientDependencyConfigXml.Root != null)
|
||||
{
|
||||
|
||||
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
|
||||
|
||||
//Set the new version to the hashcode of now
|
||||
var oldVersion = versionAttribute.Value;
|
||||
var newVersion = Math.Abs(intHash).ToString();
|
||||
|
||||
//don't update if it's the same version
|
||||
if (oldVersion == newVersion)
|
||||
return false;
|
||||
|
||||
versionAttribute.SetValue(newVersion);
|
||||
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
_logger.Info<ClientDependencyConfiguration>(string.Format("Updated version number from {0} to {1}", oldVersion, newVersion));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the version number in ClientDependency.config to a random value to avoid stale caches
|
||||
/// </summary>
|
||||
/// <seealso cref="UpdateVersionNumber(SemVersion, DateTime, string)" />
|
||||
[Obsolete("Use the UpdateVersionNumber method specifying the version, date and dateFormat instead")]
|
||||
public bool IncreaseVersionNumber()
|
||||
{
|
||||
try
|
||||
@@ -107,4 +175,4 @@ namespace Umbraco.Core.Configuration
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.7.8");
|
||||
private static readonly Version Version = new Version("7.7.12");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
@@ -132,7 +132,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public IMemberGroup GetByName(string name)
|
||||
{
|
||||
return IsolatedCache.GetCacheItem<IMemberGroup>(
|
||||
string.Format("{0}.{1}", typeof (IMemberGroup).FullName, name),
|
||||
string.Format("{0}.{1}", typeof(IMemberGroup).FullName, name),
|
||||
() =>
|
||||
{
|
||||
var qry = new Query<IMemberGroup>().Where(group => group.Name.Equals(name));
|
||||
@@ -140,7 +140,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return result.FirstOrDefault();
|
||||
},
|
||||
//cache for 5 mins since that is the default in the RuntimeCacheProvider
|
||||
TimeSpan.FromMinutes(5),
|
||||
TimeSpan.FromMinutes(5),
|
||||
//sliding is true
|
||||
true);
|
||||
}
|
||||
@@ -337,4 +337,4 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </summary>
|
||||
internal static event TypedEventHandler<IMemberGroupRepository, SaveEventArgs<IMemberGroup>> SavedMemberGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -176,6 +176,12 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// <returns></returns>
|
||||
internal Attempt<object> TryConvertValueToCrlType(object value)
|
||||
{
|
||||
var jv = value as JValue;
|
||||
if (jv != null)
|
||||
{
|
||||
value = value.ToString();
|
||||
}
|
||||
|
||||
//this is a custom check to avoid any errors, if it's a string and it's empty just make it null
|
||||
var s = value as string;
|
||||
if (s != null)
|
||||
@@ -391,4 +397,4 @@ namespace Umbraco.Core.PropertyEditors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,12 +40,13 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
|
||||
//TODO: Change all singleton access to use ctor injection in v8!!!
|
||||
//TODO: That would mean that property value converters would need to be request lifespan, hrm....
|
||||
bool isDebug = HttpContext.Current != null && HttpContext.Current.IsDebuggingEnabled;
|
||||
var gridConfig = UmbracoConfig.For.GridConfig(
|
||||
ApplicationContext.Current.ProfilingLogger.Logger,
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache,
|
||||
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)),
|
||||
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config)),
|
||||
HttpContext.Current.IsDebuggingEnabled);
|
||||
isDebug);
|
||||
|
||||
var sections = GetArray(obj, "sections");
|
||||
foreach (var section in sections.Cast<JObject>())
|
||||
@@ -112,4 +113,4 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1344,6 +1344,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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -1531,6 +1531,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,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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -6,6 +6,10 @@ using System.Threading;
|
||||
using System.Web.UI.WebControls;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
@@ -155,16 +159,151 @@ namespace Umbraco.Tests
|
||||
Assert.AreEqual("Hello world", result.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Test]
|
||||
public virtual void CanConvertObjectToSameObject()
|
||||
{
|
||||
var obj = new MyTestObject();
|
||||
var result = obj.TryConvertTo<object>();
|
||||
|
||||
Assert.AreEqual(obj, result.Result);
|
||||
Assert.AreEqual(obj, result.Result);
|
||||
}
|
||||
|
||||
private CultureInfo savedCulture;
|
||||
|
||||
[Test]
|
||||
public void ConvertToIntegerTest()
|
||||
{
|
||||
var conv = "100".TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
conv = "100.000".TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
conv = "100,000".TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
// oops
|
||||
conv = "100.001".TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
conv = 100m.TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
conv = 100.000m.TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
// oops
|
||||
conv = 100.001m.TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertToDecimalTest()
|
||||
{
|
||||
var conv = "100".TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = "100.000".TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = "100,000".TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = "100.001".TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100.001m, conv.Result);
|
||||
|
||||
conv = 100m.TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = 100.000m.TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = 100.001m.TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100.001m, conv.Result);
|
||||
|
||||
conv = 100.TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertToNullableDecimalTest()
|
||||
{
|
||||
var conv = "100".TryConvertTo<decimal?>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = "100.000".TryConvertTo<decimal?>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = "100,000".TryConvertTo<decimal?>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = "100.001".TryConvertTo<decimal?>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100.001m, conv.Result);
|
||||
|
||||
conv = 100m.TryConvertTo<decimal?>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = 100.000m.TryConvertTo<decimal?>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = 100.001m.TryConvertTo<decimal?>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100.001m, conv.Result);
|
||||
|
||||
conv = 100.TryConvertTo<decimal?>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertToDateTimeTest()
|
||||
{
|
||||
var conv = "2016-06-07".TryConvertTo<DateTime>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(new DateTime(2016, 6, 7), conv.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertToNullableDateTimeTest()
|
||||
{
|
||||
var conv = "2016-06-07".TryConvertTo<DateTime?>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(new DateTime(2016, 6, 7), conv.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Value_Editor_Can_Convert_Decimal_To_Decimal_Clr_Type()
|
||||
{
|
||||
var valueEditor = new PropertyValueEditor
|
||||
{
|
||||
ValueType = PropertyEditorValueTypes.Decimal
|
||||
};
|
||||
|
||||
var result = valueEditor.TryConvertValueToCrlType(12.34d);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(12.34d, result.Result);
|
||||
}
|
||||
|
||||
private CultureInfo _savedCulture;
|
||||
|
||||
/// <summary>
|
||||
/// Run once before each test in derived test fixtures.
|
||||
@@ -172,10 +311,13 @@ namespace Umbraco.Tests
|
||||
[SetUp]
|
||||
public void TestSetup()
|
||||
{
|
||||
savedCulture = Thread.CurrentThread.CurrentCulture;
|
||||
_savedCulture = Thread.CurrentThread.CurrentCulture;
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB"); // make sure the dates parse correctly
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = SettingsForTests.GetDefault();
|
||||
ShortStringHelperResolver.Current = new ShortStringHelperResolver(new DefaultShortStringHelper(settings).WithDefaultConfig());
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run once after each test in derived test fixtures.
|
||||
@@ -183,9 +325,9 @@ namespace Umbraco.Tests
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = savedCulture;
|
||||
return;
|
||||
}
|
||||
Thread.CurrentThread.CurrentCulture = _savedCulture;
|
||||
ShortStringHelperResolver.Reset();
|
||||
}
|
||||
|
||||
private class MyTestObject
|
||||
{
|
||||
@@ -195,4 +337,4 @@ namespace Umbraco.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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[]
|
||||
{
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TryConvertToTests
|
||||
{
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
var settings = SettingsForTests.GetDefault();
|
||||
ShortStringHelperResolver.Current = new ShortStringHelperResolver(new DefaultShortStringHelper(settings).WithDefaultConfig());
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
ShortStringHelperResolver.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertToIntegerTest()
|
||||
{
|
||||
var conv = "100".TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
conv = "100.000".TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
conv = "100,000".TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
// oops
|
||||
conv = "100.001".TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
conv = 100m.TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
conv = 100.000m.TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
|
||||
// oops
|
||||
conv = 100.001m.TryConvertTo<int>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100, conv.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertToDecimalTest()
|
||||
{
|
||||
var conv = "100".TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = "100.000".TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = "100,000".TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = "100.001".TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100.001m, conv.Result);
|
||||
|
||||
conv = 100m.TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = 100.000m.TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
|
||||
conv = 100.001m.TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100.001m, conv.Result);
|
||||
|
||||
conv = 100.TryConvertTo<decimal>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(100m, conv.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertToDateTimeTest()
|
||||
{
|
||||
var conv = "2016-06-07".TryConvertTo<DateTime>();
|
||||
Assert.IsTrue(conv);
|
||||
Assert.AreEqual(new DateTime(2016, 6, 7), conv.Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,7 +231,6 @@
|
||||
<Compile Include="Services\CachedDataTypeServiceTests.cs" />
|
||||
<Compile Include="TestHelpers\Entities\MockedPropertyTypes.cs" />
|
||||
<Compile Include="TestHelpers\Entities\MockedUserGroup.cs" />
|
||||
<Compile Include="TryConvertToTests.cs" />
|
||||
<Compile Include="UdiTests.cs" />
|
||||
<Compile Include="UmbracoExamine\RandomIdRAMDirectory.cs" />
|
||||
<Compile Include="UmbracoExamine\UmbracoContentIndexerTests.cs" />
|
||||
|
||||
@@ -185,6 +185,8 @@
|
||||
|
||||
$scope.page.buttonGroupState = "success";
|
||||
|
||||
}, function(err) {
|
||||
$scope.page.buttonGroupState = 'error';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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,12 +33,14 @@ function SearchController($scope, searchService, $log, $location, navigationServ
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var group = undefined;
|
||||
var groupIndex = -1;
|
||||
var itemIndex = -1;
|
||||
$scope.selectedItem = undefined;
|
||||
|
||||
$scope.clearSearch = function () {
|
||||
$scope.searchTerm = null;
|
||||
};
|
||||
|
||||
function iterateResults(up) {
|
||||
//default group
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
|
||||
.nested-content__item--active:not(.nested-content__item--single)
|
||||
{
|
||||
background: #f8f8f8;
|
||||
background: @gray-10;
|
||||
}
|
||||
|
||||
.nested-content__item.ui-sortable-placeholder
|
||||
{
|
||||
background: #f8f8f8;
|
||||
border: 1px dashed #d9d9d9;
|
||||
background: @gray-10;
|
||||
border-bottom: 1px dashed @purple-l3;
|
||||
visibility: visible !important;
|
||||
height: 55px;
|
||||
margin-top: -1px;
|
||||
@@ -56,7 +56,7 @@
|
||||
.nested-content__header-bar
|
||||
{
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px dashed #e0e0e0;
|
||||
border-bottom: 1px dashed @purple-l3;
|
||||
text-align: right;
|
||||
cursor: pointer;
|
||||
background-color: white;
|
||||
@@ -113,8 +113,8 @@
|
||||
.nested-content__icon--active
|
||||
{
|
||||
color: white;
|
||||
background: #2e8aea;
|
||||
border-color: #2e8aea;
|
||||
background: @turquoise-d1;
|
||||
border-color: @turquoise-d1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
|
||||
.nested-content__content
|
||||
{
|
||||
border-bottom: 1px dashed #e0e0e0;
|
||||
border-bottom: 1px dashed @purple-l3;
|
||||
}
|
||||
|
||||
.nested-content__content .umb-control-group {
|
||||
@@ -165,7 +165,7 @@
|
||||
clear: both;
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
background: #f8f8f8;
|
||||
background: @gray-10;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -36,9 +36,14 @@
|
||||
|
||||
<umb-load-indicator ng-if="isSearching"></umb-load-indicator>
|
||||
|
||||
<umb-empty-state ng-if="!hasResults && !isSearching"
|
||||
position="center">
|
||||
<umb-empty-state ng-if="!hasResults && !isSearching" position="center">
|
||||
<localize key="general_searchNoResult"></localize>
|
||||
<br />
|
||||
<button type="button" class="btn umb-button__button btn-info umb-button--" ng-click="clearSearch()" hotkey="" hotkey-when-hidden="">
|
||||
<span class="umb-button__content">
|
||||
<localize key="general_clearSearch" class="ng-isolate-scope ng-scope ng-binding">Clear Search</localize>
|
||||
</span>
|
||||
</button>
|
||||
</umb-empty-state>
|
||||
|
||||
<ul class="umb-tree" ng-if="!isSearching && hasResults">
|
||||
|
||||
@@ -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>
|
||||
<localize key="general_new">New</localize>
|
||||
<localize key="content_mediatype">Media type</localize>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
+114
-114
@@ -1,46 +1,46 @@
|
||||
function ColorPickerController($scope) {
|
||||
|
||||
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
|
||||
|
||||
if ($scope.isConfigured) {
|
||||
|
||||
for (var key in $scope.model.config.items) {
|
||||
if (!$scope.model.config.items[key].hasOwnProperty("value"))
|
||||
$scope.model.config.items[key] = { value: $scope.model.config.items[key], label: $scope.model.config.items[key] };
|
||||
}
|
||||
|
||||
$scope.model.useLabel = isTrue($scope.model.config.useLabel);
|
||||
initActiveColor();
|
||||
}
|
||||
function ColorPickerController($scope) {
|
||||
|
||||
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
|
||||
|
||||
if ($scope.isConfigured) {
|
||||
|
||||
for (var key in $scope.model.config.items) {
|
||||
if (!$scope.model.config.items[key].hasOwnProperty("value"))
|
||||
$scope.model.config.items[key] = { value: $scope.model.config.items[key], label: $scope.model.config.items[key] };
|
||||
}
|
||||
|
||||
$scope.model.useLabel = isTrue($scope.model.config.useLabel);
|
||||
initActiveColor();
|
||||
}
|
||||
|
||||
$scope.toggleItem = function (color) {
|
||||
|
||||
var currentColor = ($scope.model.value && $scope.model.value.hasOwnProperty("value"))
|
||||
? $scope.model.value.value
|
||||
: $scope.model.value;
|
||||
|
||||
$scope.toggleItem = function (color) {
|
||||
|
||||
var currentColor = $scope.model.value.hasOwnProperty("value")
|
||||
? $scope.model.value.value
|
||||
: $scope.model.value;
|
||||
|
||||
var newColor;
|
||||
if (currentColor === color.value) {
|
||||
// deselect
|
||||
$scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
|
||||
newColor = "";
|
||||
}
|
||||
else {
|
||||
if (currentColor === color.value) {
|
||||
// deselect
|
||||
$scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
|
||||
newColor = "";
|
||||
}
|
||||
else {
|
||||
// select
|
||||
$scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
|
||||
$scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
|
||||
newColor = color.value;
|
||||
}
|
||||
|
||||
// this is required to re-validate
|
||||
$scope.propertyForm.modelValue.$setViewValue(newColor);
|
||||
};
|
||||
}
|
||||
|
||||
// this is required to re-validate
|
||||
$scope.propertyForm.modelValue.$setViewValue(newColor);
|
||||
};
|
||||
|
||||
// Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected)
|
||||
$scope.validateMandatory = function () {
|
||||
var isValid = !$scope.model.validation.mandatory || (
|
||||
$scope.model.value != null
|
||||
&& $scope.model.value != ""
|
||||
&& (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "")
|
||||
$scope.validateMandatory = function () {
|
||||
var isValid = !$scope.model.validation.mandatory || (
|
||||
$scope.model.value != null
|
||||
&& $scope.model.value != ""
|
||||
&& (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "")
|
||||
);
|
||||
return {
|
||||
isValid: isValid,
|
||||
@@ -48,83 +48,83 @@ function ColorPickerController($scope) {
|
||||
errorKey: "required"
|
||||
};
|
||||
}
|
||||
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
|
||||
|
||||
// A color is active if it matches the value and label of the model.
|
||||
// If the model doesn't store the label, ignore the label during the comparison.
|
||||
$scope.isActiveColor = function (color) {
|
||||
|
||||
// no value
|
||||
if (!$scope.model.value)
|
||||
return false;
|
||||
|
||||
// Complex color (value and label)?
|
||||
if (!$scope.model.value.hasOwnProperty("value"))
|
||||
return $scope.model.value === color.value;
|
||||
|
||||
return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
|
||||
};
|
||||
|
||||
// Finds the color best matching the model's color,
|
||||
// and sets the model color to that one. This is useful when
|
||||
// either the value or label was changed on the data type.
|
||||
function initActiveColor() {
|
||||
|
||||
// no value
|
||||
if (!$scope.model.value)
|
||||
return;
|
||||
|
||||
// Complex color (value and label)?
|
||||
if (!$scope.model.value.hasOwnProperty("value"))
|
||||
return;
|
||||
|
||||
var modelColor = $scope.model.value.value;
|
||||
var modelLabel = $scope.model.value.label;
|
||||
|
||||
// Check for a full match or partial match.
|
||||
var foundItem = null;
|
||||
|
||||
// Look for a fully matching color.
|
||||
for (var key in $scope.model.config.items) {
|
||||
var item = $scope.model.config.items[key];
|
||||
if (item.value == modelColor && item.label == modelLabel) {
|
||||
foundItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for a color with a matching value.
|
||||
if (!foundItem) {
|
||||
for (var key in $scope.model.config.items) {
|
||||
var item = $scope.model.config.items[key];
|
||||
if (item.value == modelColor) {
|
||||
foundItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look for a color with a matching label.
|
||||
if (!foundItem) {
|
||||
for (var key in $scope.model.config.items) {
|
||||
var item = $scope.model.config.items[key];
|
||||
if (item.label == modelLabel) {
|
||||
foundItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If a match was found, set it as the active color.
|
||||
if (foundItem) {
|
||||
$scope.model.value.value = foundItem.value;
|
||||
$scope.model.value.label = foundItem.label;
|
||||
}
|
||||
}
|
||||
|
||||
// figures out if a value is trueish enough
|
||||
function isTrue(bool) {
|
||||
return !!bool && bool !== "0" && angular.lowercase(bool) !== "false";
|
||||
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
|
||||
|
||||
// A color is active if it matches the value and label of the model.
|
||||
// If the model doesn't store the label, ignore the label during the comparison.
|
||||
$scope.isActiveColor = function (color) {
|
||||
|
||||
// no value
|
||||
if (!$scope.model.value)
|
||||
return false;
|
||||
|
||||
// Complex color (value and label)?
|
||||
if (!$scope.model.value.hasOwnProperty("value"))
|
||||
return $scope.model.value === color.value;
|
||||
|
||||
return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
|
||||
};
|
||||
|
||||
// Finds the color best matching the model's color,
|
||||
// and sets the model color to that one. This is useful when
|
||||
// either the value or label was changed on the data type.
|
||||
function initActiveColor() {
|
||||
|
||||
// no value
|
||||
if (!$scope.model.value)
|
||||
return;
|
||||
|
||||
// Complex color (value and label)?
|
||||
if (!$scope.model.value.hasOwnProperty("value"))
|
||||
return;
|
||||
|
||||
var modelColor = $scope.model.value.value;
|
||||
var modelLabel = $scope.model.value.label;
|
||||
|
||||
// Check for a full match or partial match.
|
||||
var foundItem = null;
|
||||
|
||||
// Look for a fully matching color.
|
||||
for (var key in $scope.model.config.items) {
|
||||
var item = $scope.model.config.items[key];
|
||||
if (item.value == modelColor && item.label == modelLabel) {
|
||||
foundItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for a color with a matching value.
|
||||
if (!foundItem) {
|
||||
for (var key in $scope.model.config.items) {
|
||||
var item = $scope.model.config.items[key];
|
||||
if (item.value == modelColor) {
|
||||
foundItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look for a color with a matching label.
|
||||
if (!foundItem) {
|
||||
for (var key in $scope.model.config.items) {
|
||||
var item = $scope.model.config.items[key];
|
||||
if (item.label == modelLabel) {
|
||||
foundItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If a match was found, set it as the active color.
|
||||
if (foundItem) {
|
||||
$scope.model.value.value = foundItem.value;
|
||||
$scope.model.value.label = foundItem.label;
|
||||
}
|
||||
}
|
||||
|
||||
// figures out if a value is trueish enough
|
||||
function isTrue(bool) {
|
||||
return !!bool && bool !== "0" && angular.lowercase(bool) !== "false";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
// *********************************************
|
||||
|
||||
+10
-6
@@ -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)
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
@@ -257,7 +257,7 @@ angular.module("umbraco")
|
||||
|
||||
|
||||
editor.on('ObjectResized', function (e) {
|
||||
var qs = "?width=" + e.width + "&height=" + e.height;
|
||||
var qs = "?width=" + e.width + "&height=" + e.height + "&mode=max";
|
||||
var srcAttr = $(e.target).attr("src");
|
||||
var path = srcAttr.split("?")[0];
|
||||
$(e.target).attr("data-mce-src", path + qs);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
@@ -1023,9 +1023,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7780</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7712</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7780</IISUrl>
|
||||
<IISUrl>http://localhost:7712</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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
@@ -37,5 +37,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>
|
||||
|
||||
|
||||
@@ -250,7 +250,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>
|
||||
@@ -1215,6 +1215,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 <i class="icon icon-add blue"></i> hinzufügen</key>
|
||||
|
||||
@@ -604,6 +604,7 @@
|
||||
<key alias="rights">Permissions</key>
|
||||
<key alias="search">Search</key>
|
||||
<key alias="searchNoResult">Sorry, we can not find what you are looking for</key>
|
||||
<key alias="clearSearch">Clear search</key>
|
||||
<key alias="noItemsInList">No items have been added</key>
|
||||
<key alias="server">Server</key>
|
||||
<key alias="show">Show</key>
|
||||
@@ -1505,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>
|
||||
@@ -1953,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">
|
||||
|
||||
@@ -604,6 +604,7 @@
|
||||
<key alias="rights">Permissions</key>
|
||||
<key alias="search">Search</key>
|
||||
<key alias="searchNoResult">Sorry, we can not find what you are looking for</key>
|
||||
<key alias="clearSearch">Clear search</key>
|
||||
<key alias="noItemsInList">No items have been added</key>
|
||||
<key alias="server">Server</key>
|
||||
<key alias="show">Show</key>
|
||||
@@ -1500,6 +1501,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>
|
||||
@@ -1946,6 +1953,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>
|
||||
|
||||
@@ -117,6 +117,7 @@ namespace Umbraco.Web.Cache
|
||||
LegacyMediaPickerPropertyConverter.ClearCaches();
|
||||
SliderValueConverter.ClearCaches();
|
||||
MediaPickerPropertyConverter.ClearCaches();
|
||||
MultiNodeTreePickerPropertyConverter.ClearCaches();
|
||||
|
||||
|
||||
base.Refresh(jsonPayload);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -45,8 +45,9 @@ namespace Umbraco.Web.Install.Controllers
|
||||
if (ApplicationContext.Current.IsUpgrading)
|
||||
{
|
||||
// Update ClientDependency version
|
||||
var clientDependencyConfig = new ClientDependencyConfiguration(ApplicationContext.Current.ProfilingLogger.Logger);
|
||||
var clientDependencyUpdated = clientDependencyConfig.IncreaseVersionNumber();
|
||||
var clientDependencyConfig = new ClientDependencyConfiguration(_umbracoContext.Application.ProfilingLogger.Logger);
|
||||
var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber(
|
||||
UmbracoVersion.GetSemanticVersion(), DateTime.UtcNow, "yyyyMMdd");
|
||||
// Delete ClientDependency temp directories to make sure we get fresh caches
|
||||
var clientDependencyTempFilesDeleted = clientDependencyConfig.ClearTempFiles(HttpContext);
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -201,10 +201,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)
|
||||
@@ -229,7 +243,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
});
|
||||
|
||||
//Important! Currently we are never mapping to multiple UserDisplay objects but if we start doing that
|
||||
// this will cause an N+1 and we'll need to change how this works.
|
||||
// this will cause an N+1 and we'll need to change how this works.
|
||||
config.CreateMap<IUser, UserDisplay>()
|
||||
.ForMember(detail => detail.Avatars, opt => opt.MapFrom(user => user.GetCurrentUserAvatarUrls(applicationContext.Services.UserService, applicationContext.ApplicationCache.RuntimeCache)))
|
||||
.ForMember(detail => detail.Username, opt => opt.MapFrom(user => user.Username))
|
||||
@@ -253,7 +267,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
"media/mediaRoot")))
|
||||
.ForMember(
|
||||
detail => detail.StartContentIds,
|
||||
opt => opt.MapFrom(user => GetStartNodeValues(
|
||||
opt => opt.MapFrom(user => GetStartNodeValues(
|
||||
user.StartContentIds.ToArray(),
|
||||
applicationContext.Services.TextService,
|
||||
applicationContext.Services.EntityService,
|
||||
@@ -261,7 +275,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
"content/contentRoot")))
|
||||
.ForMember(
|
||||
detail => detail.StartMediaIds,
|
||||
opt => opt.MapFrom(user => GetStartNodeValues(
|
||||
opt => opt.MapFrom(user => GetStartNodeValues(
|
||||
user.StartMediaIds.ToArray(),
|
||||
applicationContext.Services.TextService,
|
||||
applicationContext.Services.EntityService,
|
||||
@@ -328,7 +342,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
//the best we can do here is to return the user's first user group as a IUserType object
|
||||
//but we should attempt to return any group that is the built in ones first
|
||||
var groups = user.Groups.ToArray();
|
||||
detail.UserGroups = user.Groups.Select(x => x.Alias).ToArray();
|
||||
detail.UserGroups = user.Groups.Select(x => x.Alias).ToArray();
|
||||
|
||||
if (groups.Length == 0)
|
||||
{
|
||||
@@ -369,8 +383,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)
|
||||
@@ -385,7 +399,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
return startNodes;
|
||||
}
|
||||
return Enumerable.Empty<EntityBasic>();
|
||||
}
|
||||
}
|
||||
|
||||
private void MapUserGroupBasic(ServiceContext services, dynamic group, UserGroupBasic display)
|
||||
{
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -85,6 +85,9 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
/// </returns>
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
if (source == null)
|
||||
return null;
|
||||
|
||||
if (IsMultipleDataType(propertyType.DataTypeId, propertyType.PropertyEditorAlias))
|
||||
{
|
||||
var nodeIds =
|
||||
|
||||
+78
-35
@@ -8,16 +8,18 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Web.Extensions;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
@@ -32,6 +34,20 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
[PropertyValueCache(PropertyCacheValue.XPath, PropertyCacheLevel.Content)]
|
||||
public class MultiNodeTreePickerPropertyConverter : PropertyValueConverterBase
|
||||
{
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
|
||||
//TODO: Remove this ctor in v8 since the other one will use IoC
|
||||
public MultiNodeTreePickerPropertyConverter()
|
||||
: this(ApplicationContext.Current.Services.DataTypeService)
|
||||
{ }
|
||||
|
||||
public MultiNodeTreePickerPropertyConverter(IDataTypeService dataTypeService)
|
||||
: base()
|
||||
{
|
||||
if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
|
||||
_dataTypeService = dataTypeService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The properties to exclude.
|
||||
/// </summary>
|
||||
@@ -125,6 +141,24 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
|
||||
var umbHelper = new UmbracoHelper(UmbracoContext.Current);
|
||||
|
||||
Func<object, IPublishedContent> contentFetcher;
|
||||
|
||||
switch (GetPublishedContentType(propertyType.DataTypeId))
|
||||
{
|
||||
case PublishedItemType.Media:
|
||||
contentFetcher = umbHelper.TypedMedia;
|
||||
break;
|
||||
|
||||
case PublishedItemType.Member:
|
||||
contentFetcher = umbHelper.TypedMember;
|
||||
break;
|
||||
|
||||
case PublishedItemType.Content:
|
||||
default:
|
||||
contentFetcher = umbHelper.TypedContent;
|
||||
break;
|
||||
}
|
||||
|
||||
if (propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditors.MultiNodeTreePickerAlias))
|
||||
{
|
||||
var nodeIds = (int[])source;
|
||||
@@ -133,14 +167,9 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
var multiNodeTreePicker = new List<IPublishedContent>();
|
||||
|
||||
var objectType = UmbracoObjectTypes.Unknown;
|
||||
|
||||
foreach (var nodeId in nodeIds)
|
||||
{
|
||||
var multiNodeTreePickerItem =
|
||||
GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Document, umbHelper.TypedContent)
|
||||
?? GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Media, umbHelper.TypedMedia)
|
||||
?? GetPublishedContent(nodeId, ref objectType, UmbracoObjectTypes.Member, umbHelper.TypedMember);
|
||||
var multiNodeTreePickerItem = contentFetcher(nodeId);
|
||||
|
||||
if (multiNodeTreePickerItem != null)
|
||||
{
|
||||
@@ -163,14 +192,9 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
var multiNodeTreePicker = new List<IPublishedContent>();
|
||||
|
||||
var objectType = UmbracoObjectTypes.Unknown;
|
||||
|
||||
foreach (var udi in udis)
|
||||
{
|
||||
var multiNodeTreePickerItem =
|
||||
GetPublishedContent(udi, ref objectType, UmbracoObjectTypes.Document, umbHelper.TypedContent)
|
||||
?? GetPublishedContent(udi, ref objectType, UmbracoObjectTypes.Media, umbHelper.TypedMedia)
|
||||
?? GetPublishedContent(udi, ref objectType, UmbracoObjectTypes.Member, umbHelper.TypedMember);
|
||||
var multiNodeTreePickerItem = contentFetcher(udi);
|
||||
if (multiNodeTreePickerItem != null)
|
||||
{
|
||||
multiNodeTreePicker.Add(multiNodeTreePickerItem);
|
||||
@@ -186,31 +210,50 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
return source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get an IPublishedContent instance based on ID and content type
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The content node ID</param>
|
||||
/// <param name="actualType">The type of content being requested</param>
|
||||
/// <param name="expectedType">The type of content expected/supported by <paramref name="contentFetcher"/></param>
|
||||
/// <param name="contentFetcher">A function to fetch content of type <paramref name="expectedType"/></param>
|
||||
/// <returns>The requested content, or null if either it does not exist or <paramref name="actualType"/> does not match <paramref name="expectedType"/></returns>
|
||||
private IPublishedContent GetPublishedContent<T>(T nodeId, ref UmbracoObjectTypes actualType, UmbracoObjectTypes expectedType, Func<T, IPublishedContent> contentFetcher)
|
||||
private PublishedItemType GetPublishedContentType(int dataTypeId)
|
||||
{
|
||||
// is the actual type supported by the content fetcher?
|
||||
if (actualType != UmbracoObjectTypes.Unknown && actualType != expectedType)
|
||||
{
|
||||
// no, return null
|
||||
return null;
|
||||
}
|
||||
// GetPreValuesCollectionByDataTypeId is cached at repository level;
|
||||
// still, the collection is deep-cloned so this is kinda expensive,
|
||||
// better to cache here + trigger refresh in DataTypeCacheRefresher
|
||||
// e.g. https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs#L116-L119
|
||||
|
||||
// attempt to get the content
|
||||
var content = contentFetcher(nodeId);
|
||||
if (content != null)
|
||||
return Storages.GetOrAdd(dataTypeId, id =>
|
||||
{
|
||||
// if we found the content, assign the expected type to the actual type so we don't have to keep looking for other types of content
|
||||
actualType = expectedType;
|
||||
}
|
||||
return content;
|
||||
var preValue = _dataTypeService
|
||||
.GetPreValuesCollectionByDataTypeId(id)
|
||||
.PreValuesAsDictionary
|
||||
.FirstOrDefault(x => string.Equals(x.Key, "startNode", StringComparison.InvariantCultureIgnoreCase))
|
||||
.Value;
|
||||
|
||||
if (preValue != null && string.IsNullOrWhiteSpace(preValue.Value) == false)
|
||||
{
|
||||
var data = JsonConvert.DeserializeAnonymousType(preValue.Value, new { type = string.Empty });
|
||||
if (data != null)
|
||||
{
|
||||
switch (data.type.ToUpperInvariant())
|
||||
{
|
||||
case "MEDIA":
|
||||
return PublishedItemType.Media;
|
||||
|
||||
case "MEMBER":
|
||||
return PublishedItemType.Member;
|
||||
|
||||
case "CONTENT":
|
||||
default:
|
||||
return PublishedItemType.Content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PublishedItemType.Content;
|
||||
});
|
||||
}
|
||||
|
||||
private static readonly ConcurrentDictionary<int, PublishedItemType> Storages = new ConcurrentDictionary<int, PublishedItemType>();
|
||||
|
||||
internal static void ClearCaches()
|
||||
{
|
||||
Storages.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.XPath;
|
||||
@@ -224,14 +225,54 @@ namespace Umbraco.Web
|
||||
{
|
||||
var doc = cache.GetById(id);
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ConcurrentDictionary<Guid, int> _guidToIntLoopkup = new ConcurrentDictionary<Guid, int>();
|
||||
|
||||
private IPublishedContent TypedDocumentById(Guid id, ContextualPublishedCache cache)
|
||||
{
|
||||
// todo: in v8, implement in a more efficient way
|
||||
var legacyXml = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema;
|
||||
var xpath = legacyXml ? "//node [@key=$guid]" : "//* [@key=$guid]";
|
||||
var doc = cache.GetSingleByXPath(xpath, new XPathVariable("guid", id.ToString()));
|
||||
{
|
||||
// Check if the loopkup is empty, if so populate it [LK]
|
||||
if (_guidToIntLoopkup.Count == 0)
|
||||
{
|
||||
// TODO: Remove the debug profile logger
|
||||
using (ApplicationContext.Current.ProfilingLogger.DebugDuration<PublishedContentQuery>("Populate GUID/INT lookup"))
|
||||
{
|
||||
// NOTE, using the `@nodeTypeAlias` attribute in the XPath as this was support in both legacy & new schemas
|
||||
var tmpNodes = cache.GetXPathNavigator().Select("//*[@nodeTypeAlias]");
|
||||
foreach (XPathNavigator tmpNode in tmpNodes)
|
||||
{
|
||||
int tmpNodeId;
|
||||
Guid tmpNodeKey;
|
||||
if (int.TryParse(tmpNode.GetAttribute("id", string.Empty), out tmpNodeId)
|
||||
&& Guid.TryParse(tmpNode.GetAttribute("key", string.Empty), out tmpNodeKey))
|
||||
{
|
||||
_guidToIntLoopkup[tmpNodeKey] = tmpNodeId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IPublishedContent doc;
|
||||
|
||||
// Check if the lookup contains the GUID/INT value
|
||||
int nodeId;
|
||||
if (_guidToIntLoopkup.TryGetValue(id, out nodeId) == false)
|
||||
{
|
||||
// If not, then we perform an inefficient XPath for the GUID
|
||||
|
||||
// todo: in v8, implement in a more efficient way
|
||||
doc = cache.GetSingleByXPath("//*[@key=$guid]", new XPathVariable("guid", id.ToString()));
|
||||
|
||||
// When we have the node, we add the GUID/INT value to the lookup
|
||||
if (doc != null)
|
||||
_guidToIntLoopkup[id] = doc.Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise we have the node id (INT) and can perform an efficient retrieval
|
||||
doc = cache.GetById(nodeId);
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
@@ -422,4 +463,4 @@ namespace Umbraco.Web
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Web.Cache;
|
||||
using UmbracoExamine;
|
||||
@@ -24,7 +25,12 @@ namespace Umbraco.Web.Search
|
||||
/// </summary>
|
||||
public sealed class ExamineEvents : ApplicationEventHandler
|
||||
{
|
||||
/// <summary>
|
||||
// the default enlist priority is 100
|
||||
// enlist with a lower priority to ensure that anything "default" runs after us
|
||||
// but greater that SafeXmlReaderWriter priority which is 60
|
||||
private const int EnlistPriority = 80;
|
||||
|
||||
/// <summary>
|
||||
/// Once the application has started we should bind to all events and initialize the providers.
|
||||
/// </summary>
|
||||
/// <param name="httpApplication"></param>
|
||||
@@ -447,11 +453,11 @@ namespace Umbraco.Web.Search
|
||||
|
||||
private static void ReIndexForMember(IMember member)
|
||||
{
|
||||
ExamineManager.Instance.ReIndexNode(
|
||||
member.ToXml(), IndexTypes.Member,
|
||||
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
|
||||
//ensure that only the providers are flagged to listen execute
|
||||
.Where(x => x.EnableDefaultEventHandler));
|
||||
var actions = DeferedActions.Get(ApplicationContext.Current.ScopeProvider);
|
||||
if (actions != null)
|
||||
actions.Add(new DeferedReIndexForMember(member));
|
||||
else
|
||||
DeferedReIndexForMember.Execute(member);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -479,19 +485,11 @@ namespace Umbraco.Web.Search
|
||||
|
||||
private static void ReIndexForMedia(IMedia sender, bool isMediaPublished)
|
||||
{
|
||||
var xml = sender.ToXml();
|
||||
//add an icon attribute to get indexed
|
||||
xml.Add(new XAttribute("icon", sender.ContentType.Icon));
|
||||
|
||||
ExamineManager.Instance.ReIndexNode(
|
||||
xml, IndexTypes.Media,
|
||||
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
|
||||
|
||||
//Index this item for all indexers if the media is not trashed, otherwise if the item is trashed
|
||||
// then only index this for indexers supporting unpublished media
|
||||
|
||||
.Where(x => isMediaPublished || (x.SupportUnpublishedContent))
|
||||
.Where(x => x.EnableDefaultEventHandler));
|
||||
var actions = DeferedActions.Get(ApplicationContext.Current.ScopeProvider);
|
||||
if (actions != null)
|
||||
actions.Add(new DeferedReIndexForMedia(sender, isMediaPublished));
|
||||
else
|
||||
DeferedReIndexForMedia.Execute(sender, isMediaPublished);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -504,15 +502,11 @@ namespace Umbraco.Web.Search
|
||||
/// </param>
|
||||
private static void DeleteIndexForEntity(int entityId, bool keepIfUnpublished)
|
||||
{
|
||||
ExamineManager.Instance.DeleteFromIndex(
|
||||
entityId.ToString(CultureInfo.InvariantCulture),
|
||||
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
|
||||
|
||||
//if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
|
||||
// otherwise if keepIfUnpublished == false then remove from all indexes
|
||||
|
||||
.Where(x => keepIfUnpublished == false || x.SupportUnpublishedContent == false)
|
||||
.Where(x => x.EnableDefaultEventHandler));
|
||||
var actions = DeferedActions.Get(ApplicationContext.Current.ScopeProvider);
|
||||
if (actions != null)
|
||||
actions.Add(new DeferedDeleteIndex(entityId, keepIfUnpublished));
|
||||
else
|
||||
DeferedDeleteIndex.Execute(entityId, keepIfUnpublished);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -524,22 +518,171 @@ namespace Umbraco.Web.Search
|
||||
/// </param>
|
||||
private static void ReIndexForContent(IContent sender, bool isContentPublished)
|
||||
{
|
||||
var xml = sender.ToXml();
|
||||
//add an icon attribute to get indexed
|
||||
xml.Add(new XAttribute("icon", sender.ContentType.Icon));
|
||||
|
||||
ExamineManager.Instance.ReIndexNode(
|
||||
xml, IndexTypes.Content,
|
||||
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
|
||||
|
||||
//Index this item for all indexers if the content is published, otherwise if the item is not published
|
||||
// then only index this for indexers supporting unpublished content
|
||||
|
||||
.Where(x => isContentPublished || (x.SupportUnpublishedContent))
|
||||
.Where(x => x.EnableDefaultEventHandler));
|
||||
var actions = DeferedActions.Get(ApplicationContext.Current.ScopeProvider);
|
||||
if (actions != null)
|
||||
actions.Add(new DeferedReIndexForContent(sender, isContentPublished));
|
||||
else
|
||||
DeferedReIndexForContent.Execute(sender, isContentPublished);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
private class DeferedActions
|
||||
{
|
||||
private readonly List<DeferedAction> _actions = new List<DeferedAction>();
|
||||
|
||||
public static DeferedActions Get(IScopeProvider scopeProvider)
|
||||
{
|
||||
var scopeContext = scopeProvider.Context;
|
||||
if (scopeContext == null) return null;
|
||||
|
||||
return scopeContext.Enlist("examineEvents",
|
||||
() => new DeferedActions(), // creator
|
||||
(completed, actions) => // action
|
||||
{
|
||||
if (completed) actions.Execute();
|
||||
}, EnlistPriority);
|
||||
}
|
||||
|
||||
public void Add(DeferedAction action)
|
||||
{
|
||||
_actions.Add(action);
|
||||
}
|
||||
|
||||
private void Execute()
|
||||
{
|
||||
foreach (var action in _actions)
|
||||
action.Execute();
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class DeferedAction
|
||||
{
|
||||
public virtual void Execute()
|
||||
{ }
|
||||
}
|
||||
|
||||
private class DeferedReIndexForContent : DeferedAction
|
||||
{
|
||||
private readonly IContent _content;
|
||||
private readonly bool _isPublished;
|
||||
|
||||
public DeferedReIndexForContent(IContent content, bool isPublished)
|
||||
{
|
||||
_content = content;
|
||||
_isPublished = isPublished;
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
Execute(_content, _isPublished);
|
||||
}
|
||||
|
||||
public static void Execute(IContent content, bool isPublished)
|
||||
{
|
||||
var xml = content.ToXml();
|
||||
//add an icon attribute to get indexed
|
||||
xml.Add(new XAttribute("icon", content.ContentType.Icon));
|
||||
|
||||
ExamineManager.Instance.ReIndexNode(
|
||||
xml, IndexTypes.Content,
|
||||
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
|
||||
|
||||
//Index this item for all indexers if the content is published, otherwise if the item is not published
|
||||
// then only index this for indexers supporting unpublished content
|
||||
|
||||
.Where(x => isPublished || (x.SupportUnpublishedContent))
|
||||
.Where(x => x.EnableDefaultEventHandler));
|
||||
}
|
||||
}
|
||||
|
||||
private class DeferedReIndexForMedia : DeferedAction
|
||||
{
|
||||
private readonly IMedia _media;
|
||||
private readonly bool _isPublished;
|
||||
|
||||
public DeferedReIndexForMedia(IMedia media, bool isPublished)
|
||||
{
|
||||
_media = media;
|
||||
_isPublished = isPublished;
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
Execute(_media, _isPublished);
|
||||
}
|
||||
|
||||
public static void Execute(IMedia media, bool isPublished)
|
||||
{
|
||||
var xml = media.ToXml();
|
||||
//add an icon attribute to get indexed
|
||||
xml.Add(new XAttribute("icon", media.ContentType.Icon));
|
||||
|
||||
ExamineManager.Instance.ReIndexNode(
|
||||
xml, IndexTypes.Media,
|
||||
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
|
||||
|
||||
//Index this item for all indexers if the media is not trashed, otherwise if the item is trashed
|
||||
// then only index this for indexers supporting unpublished media
|
||||
|
||||
.Where(x => isPublished || (x.SupportUnpublishedContent))
|
||||
.Where(x => x.EnableDefaultEventHandler));
|
||||
}
|
||||
}
|
||||
|
||||
private class DeferedReIndexForMember : DeferedAction
|
||||
{
|
||||
private readonly IMember _member;
|
||||
|
||||
public DeferedReIndexForMember(IMember member)
|
||||
{
|
||||
_member = member;
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
Execute(_member);
|
||||
}
|
||||
|
||||
public static void Execute(IMember member)
|
||||
{
|
||||
ExamineManager.Instance.ReIndexNode(
|
||||
member.ToXml(), IndexTypes.Member,
|
||||
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
|
||||
//ensure that only the providers are flagged to listen execute
|
||||
.Where(x => x.EnableDefaultEventHandler));
|
||||
}
|
||||
}
|
||||
|
||||
private class DeferedDeleteIndex : DeferedAction
|
||||
{
|
||||
private readonly int _id;
|
||||
private readonly bool _keepIfUnpublished;
|
||||
|
||||
public DeferedDeleteIndex(int id, bool keepIfUnpublished)
|
||||
{
|
||||
_id = id;
|
||||
_keepIfUnpublished = keepIfUnpublished;
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
Execute(_id, _keepIfUnpublished);
|
||||
}
|
||||
|
||||
public static void Execute(int id, bool keepIfUnpublished)
|
||||
{
|
||||
ExamineManager.Instance.DeleteFromIndex(
|
||||
id.ToString(CultureInfo.InvariantCulture),
|
||||
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
|
||||
|
||||
//if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
|
||||
// otherwise if keepIfUnpublished == false then remove from all indexes
|
||||
|
||||
.Where(x => keepIfUnpublished == false || x.SupportUnpublishedContent == false)
|
||||
.Where(x => x.EnableDefaultEventHandler));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a content node to XDocument
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
@@ -583,4 +726,4 @@ namespace Umbraco.Web.Search
|
||||
return new XDocument(ExamineXmlExtensions.ToXElement(xNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Umbraco.Web.Trees
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Ensure the noAccess metadata is applied for the root node if in dialog mode and the user doesn't have path access to it
|
||||
/// </summary>
|
||||
@@ -70,12 +70,12 @@ namespace Umbraco.Web.Trees
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract TreeNode GetSingleTreeNode(IUmbracoEntity e, string parentId, FormDataCollection queryStrings);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="TreeNode"/> for the <see cref="IUmbracoEntity"/> and
|
||||
/// Returns a <see cref="TreeNode"/> for the <see cref="IUmbracoEntity"/> and
|
||||
/// attaches some meta data to the node if the user doesn't have start node access to it when in dialog mode
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
@@ -83,13 +83,13 @@ namespace Umbraco.Web.Trees
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
internal TreeNode GetSingleTreeNodeWithAccessCheck(IUmbracoEntity e, string parentId, FormDataCollection queryStrings)
|
||||
{
|
||||
bool hasPathAccess;
|
||||
var entityIsAncestorOfStartNodes = Security.CurrentUser.IsInBranchOfStartNode(e, Services.EntityService, RecycleBinId, out hasPathAccess);
|
||||
if (entityIsAncestorOfStartNodes == false)
|
||||
return null;
|
||||
{
|
||||
bool hasPathAccess;
|
||||
var entityIsAncestorOfStartNodes = Security.CurrentUser.IsInBranchOfStartNode(e, Services.EntityService, RecycleBinId, out hasPathAccess);
|
||||
if (entityIsAncestorOfStartNodes == false)
|
||||
return null;
|
||||
|
||||
var treeNode = GetSingleTreeNode(e, parentId, queryStrings);
|
||||
var treeNode = GetSingleTreeNode(e, parentId, queryStrings);
|
||||
if (hasPathAccess == false)
|
||||
{
|
||||
treeNode.AdditionalData["noAccess"] = true;
|
||||
@@ -98,7 +98,7 @@ namespace Umbraco.Web.Trees
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the
|
||||
/// Returns the
|
||||
/// </summary>
|
||||
protected abstract int RecycleBinId { get; }
|
||||
|
||||
@@ -111,79 +111,69 @@ namespace Umbraco.Web.Trees
|
||||
/// Returns the user's start node for this tree
|
||||
/// </summary>
|
||||
protected abstract int[] UserStartNodes { get; }
|
||||
|
||||
|
||||
protected virtual TreeNodeCollection PerformGetTreeNodes(string id, FormDataCollection queryStrings)
|
||||
{
|
||||
var nodes = new TreeNodeCollection();
|
||||
|
||||
var altStartId = string.Empty;
|
||||
if (queryStrings.HasKey(TreeQueryStringParameters.StartNodeId))
|
||||
altStartId = queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId);
|
||||
var rootIdString = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
var rootIdString = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
var hasAccessToRoot = UserStartNodes.Contains(Constants.System.Root);
|
||||
|
||||
//check if a request has been made to render from a specific start node
|
||||
if (string.IsNullOrEmpty(altStartId) == false && altStartId != "undefined" && altStartId != rootIdString)
|
||||
var startNodeId = queryStrings.HasKey(TreeQueryStringParameters.StartNodeId)
|
||||
? queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId)
|
||||
: string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(startNodeId) == false && startNodeId != "undefined" && startNodeId != rootIdString)
|
||||
{
|
||||
id = altStartId;
|
||||
// request has been made to render from a specific, non-root, start node
|
||||
id = startNodeId;
|
||||
|
||||
//we need to verify that the user has access to view this node, otherwise we'll render an empty tree collection
|
||||
// TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access
|
||||
// ensure that the user has access to that node, otherwise return the empty tree nodes collection
|
||||
// TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access
|
||||
if (HasPathAccess(id, queryStrings) == false)
|
||||
{
|
||||
LogHelper.Warn<ContentTreeControllerBase>("The user " + Security.CurrentUser.Username + " does not have access to the tree node " + id);
|
||||
return new TreeNodeCollection();
|
||||
LogHelper.Warn<ContentTreeControllerBase>("User " + Security.CurrentUser.Username + " does not have access to node with id " + id);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
// So there's an alt id specified, it's not the root node and the user has access to it, great! But there's one thing we
|
||||
// need to consider:
|
||||
// If the tree is being rendered in a dialog view we want to render only the children of the specified id, but
|
||||
// when the tree is being rendered normally in a section and the current user's start node is not -1, then
|
||||
// we want to include their start node in the tree as well.
|
||||
// Therefore, in the latter case, we want to change the id to -1 since we want to render the current user's root node
|
||||
// and the GetChildEntities method will take care of rendering the correct root node.
|
||||
// If it is in dialog mode, then we don't need to change anything and the children will just render as per normal.
|
||||
if (IsDialog(queryStrings) == false && UserStartNodes.Contains(Constants.System.Root) == false)
|
||||
// if the tree is rendered...
|
||||
// - in a dialog: render only the children of the specific start node, nothing to do
|
||||
// - in a section: if the current user's start nodes do not contain the root node, we need
|
||||
// to include these start nodes in the tree too, to provide some context - i.e. change
|
||||
// start node back to root node, and then GetChildEntities method will take care of the rest.
|
||||
if (IsDialog(queryStrings) == false && hasAccessToRoot == false)
|
||||
id = rootIdString;
|
||||
}
|
||||
|
||||
// get child entities - if id is root, but user's start nodes do not contain the
|
||||
// root node, this returns the start nodes instead of root's children
|
||||
var entities = GetChildEntities(id).ToList();
|
||||
nodes.AddRange(entities.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings)).Where(x => x != null));
|
||||
|
||||
// if the user does not have access to the root node, what we have is the start nodes,
|
||||
// but to provide some context we also need to add their topmost nodes when they are not
|
||||
// topmost nodes themselves (level > 1).
|
||||
if (id == rootIdString && hasAccessToRoot == false)
|
||||
{
|
||||
var topNodeIds = entities.Where(x => x.Level > 1).Select(GetTopNodeId).Where(x => x != 0).Distinct().ToArray();
|
||||
if (topNodeIds.Length > 0)
|
||||
{
|
||||
id = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
var topNodes = Services.EntityService.GetAll(UmbracoObjectType, topNodeIds.ToArray());
|
||||
nodes.AddRange(topNodes.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings)).Where(x => x != null));
|
||||
}
|
||||
}
|
||||
|
||||
var entities = GetChildEntities(id).ToList();
|
||||
|
||||
//If we are looking up the root and there is more than one node ...
|
||||
//then we want to lookup those nodes' 'site' nodes and render those so that the
|
||||
//user has some context of where they are in the tree, this is generally for pickers in a dialog.
|
||||
//for any node they don't have access too, we need to add some metadata
|
||||
if (id == rootIdString && entities.Count > 1)
|
||||
{
|
||||
var siteNodeIds = new List<int>();
|
||||
//put into array since we might modify the list
|
||||
foreach (var e in entities.ToArray())
|
||||
{
|
||||
var pathParts = e.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (pathParts.Length < 2)
|
||||
continue; // this should never happen but better to check
|
||||
|
||||
int siteNodeId;
|
||||
if (int.TryParse(pathParts[1], out siteNodeId) == false)
|
||||
continue;
|
||||
|
||||
//we'll look up this
|
||||
siteNodeIds.Add(siteNodeId);
|
||||
}
|
||||
var siteNodes = Services.EntityService.GetAll(UmbracoObjectType, siteNodeIds.ToArray())
|
||||
.DistinctBy(e => e.Id)
|
||||
.ToArray();
|
||||
|
||||
//add site nodes
|
||||
nodes.AddRange(siteNodes.Select(e => GetSingleTreeNodeWithAccessCheck(e, id, queryStrings)).Where(node => node != null));
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
nodes.AddRange(entities.Select(e => GetSingleTreeNodeWithAccessCheck(e, id, queryStrings)).Where(node => node != null));
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly char[] Comma = { ',' };
|
||||
|
||||
private int GetTopNodeId(IUmbracoEntity entity)
|
||||
{
|
||||
int id;
|
||||
var parts = entity.Path.Split(Comma, StringSplitOptions.RemoveEmptyEntries);
|
||||
return parts.Length >= 2 && int.TryParse(parts[1], out id) ? id : 0;
|
||||
}
|
||||
|
||||
protected abstract MenuItemCollection PerformGetMenuForNode(string id, FormDataCollection queryStrings);
|
||||
|
||||
@@ -191,30 +181,27 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
protected IEnumerable<IUmbracoEntity> GetChildEntities(string id)
|
||||
{
|
||||
// use helper method to ensure we support both integer and guid lookups
|
||||
int iid;
|
||||
|
||||
// look up from GUID if it's not an integer
|
||||
if (int.TryParse(id, out iid) == false)
|
||||
// try to parse id as an integer else use GetEntityFromId
|
||||
// which will grok Guids, Udis, etc and let use obtain the id
|
||||
int entityId;
|
||||
if (int.TryParse(id, out entityId) == false)
|
||||
{
|
||||
var idEntity = GetEntityFromId(id);
|
||||
if (idEntity == null)
|
||||
{
|
||||
var entity = GetEntityFromId(id);
|
||||
if (entity == null)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
iid = idEntity.Id;
|
||||
entityId = entity.Id;
|
||||
}
|
||||
|
||||
// if a request is made for the root node but user has no access to
|
||||
// root node, return start nodes instead
|
||||
if (iid == Constants.System.Root && UserStartNodes.Contains(Constants.System.Root) == false)
|
||||
if (entityId == Constants.System.Root && UserStartNodes.Contains(Constants.System.Root) == false)
|
||||
{
|
||||
return UserStartNodes.Length > 0
|
||||
? Services.EntityService.GetAll(UmbracoObjectType, UserStartNodes)
|
||||
: Enumerable.Empty<IUmbracoEntity>();
|
||||
}
|
||||
|
||||
return Services.EntityService.GetChildren(iid, UmbracoObjectType).ToArray();
|
||||
return Services.EntityService.GetChildren(entityId, UmbracoObjectType).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -236,7 +223,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
if (entity == null) return false;
|
||||
return Security.CurrentUser.HasPathAccess(entity, Services.EntityService, RecycleBinId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures the recycle bin is appended when required (i.e. user has access to the root and it's not in dialog mode)
|
||||
@@ -257,7 +244,7 @@ namespace Umbraco.Web.Trees
|
||||
if (queryStrings.HasKey(TreeQueryStringParameters.StartNodeId))
|
||||
altStartId = queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId);
|
||||
|
||||
//check if a request has been made to render from a specific start node
|
||||
//check if a request has been made to render from a specific start node
|
||||
if (string.IsNullOrEmpty(altStartId) == false && altStartId != "undefined" && altStartId != Constants.System.Root.ToString(CultureInfo.InvariantCulture))
|
||||
{
|
||||
id = altStartId;
|
||||
@@ -324,7 +311,7 @@ namespace Umbraco.Web.Trees
|
||||
menu.Items.Add<ActionEmptyTranscan>(ui.Text("actions", "emptyTrashcan"));
|
||||
menu.Items.Add<ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
return PerformGetMenuForNode(id, queryStrings);
|
||||
}
|
||||
@@ -355,8 +342,8 @@ namespace Umbraco.Web.Trees
|
||||
internal IEnumerable<MenuItem> GetAllowedUserMenuItemsForNode(IUmbracoEntity dd)
|
||||
{
|
||||
var actions = ActionsResolver.Current.FromActionSymbols(Security.CurrentUser.GetPermissions(dd.Path, Services.UserService))
|
||||
.ToList();
|
||||
|
||||
.ToList();
|
||||
|
||||
// A user is allowed to delete their own stuff
|
||||
if (dd.CreatorId == Security.GetUserId() && actions.Contains(ActionDelete.Instance) == false)
|
||||
actions.Add(ActionDelete.Instance);
|
||||
@@ -370,12 +357,12 @@ namespace Umbraco.Web.Trees
|
||||
/// <param name="doc">The Document to check permissions against</param>
|
||||
/// <param name="allowedUserOptions">A list of MenuItems that the user has permissions to execute on the current document</param>
|
||||
/// <remarks>By default the user must have Browse permissions to see the node in the Content tree</remarks>
|
||||
/// <returns></returns>
|
||||
/// <returns></returns>
|
||||
internal bool CanUserAccessNode(IUmbracoEntity doc, IEnumerable<MenuItem> allowedUserOptions)
|
||||
{
|
||||
return allowedUserOptions.Select(x => x.Action).OfType<ActionBrowse>().Any();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// this will parse the string into either a GUID or INT
|
||||
/// </summary>
|
||||
@@ -399,11 +386,11 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var guidUdi = idUdi as GuidUdi;
|
||||
if (guidUdi != null)
|
||||
return new Tuple<Guid?, int?>(guidUdi.Guid, null);
|
||||
}
|
||||
return new Tuple<Guid?, int?>(guidUdi.Guid, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an entity via an id that can be either an integer, Guid or UDI
|
||||
@@ -442,11 +429,11 @@ namespace Umbraco.Web.Trees
|
||||
}
|
||||
|
||||
return entity;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private readonly ConcurrentDictionary<string, IUmbracoEntity> _entityCache = new ConcurrentDictionary<string, IUmbracoEntity>();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using System.Net.Http.Formatting;
|
||||
using umbraco;
|
||||
using umbraco.BusinessLogic.Actions;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.Trees;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
@@ -53,6 +56,31 @@ namespace Umbraco.Web.Trees
|
||||
protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
{
|
||||
//Create User
|
||||
var createMenuItem = menu.Items.CreateMenuItem<ActionNew>(Services.TextService.Localize("actions/create"));
|
||||
createMenuItem.Icon = "add";
|
||||
createMenuItem.NavigateToRoute("users/users/overview?subview=users&create=true");
|
||||
menu.Items.Add(createMenuItem);
|
||||
|
||||
//This is the same setting used in the global JS for 'showUserInvite'
|
||||
if (EmailSender.CanSendRequiredEmail)
|
||||
{
|
||||
//Invite User (Action import closest type of action to an invite user)
|
||||
var inviteMenuItem = menu.Items.CreateMenuItem<ActionImport>(Services.TextService.Localize("user/invite"));
|
||||
inviteMenuItem.Icon = "message-unopened";
|
||||
inviteMenuItem.NavigateToRoute("users/users/overview?subview=users&invite=true");
|
||||
|
||||
menu.Items.Add(inviteMenuItem);
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
//There is no context menu options for editing a specific user
|
||||
//Also we no longer list each user in the tree & in theory never hit this
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,8 +105,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="dotless.Core, Version=1.5.2.0, Culture=neutral, PublicKeyToken=96b446c9e63eae34, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\dotless.1.5.2\lib\dotless.Core.dll</HintPath>
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace Umbraco.Web
|
||||
ViewEngines.Engines.Add(new PluginViewEngine());
|
||||
|
||||
//set model binder
|
||||
ModelBinderProviders.BinderProviders.Add(new RenderModelBinder()); // is a provider
|
||||
ModelBinderProviders.BinderProviders.Add(RenderModelBinder.Instance); // is a provider
|
||||
|
||||
////add the profiling action filter
|
||||
//GlobalFilters.Filters.Add(new ProfilingActionFilter());
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user