Compare commits
325 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a099af39c2 | |||
| 118f9b02e2 | |||
| 38778cc7c7 | |||
| ffff9efaa8 | |||
| 7f4abb4893 | |||
| 4d39ce1202 | |||
| 7164f23a98 | |||
| 8b2d1b8eab | |||
| 80394f08fb | |||
| ca1fe5ff2a | |||
| a1037ce43c | |||
| 2cd2f3741d | |||
| e634dba4ea | |||
| d1eb8fd9eb | |||
| 2e91c89c02 | |||
| 8be54ba0cc | |||
| 3da7682415 | |||
| 775892ff5a | |||
| f30b4c8184 | |||
| 319ba5c791 | |||
| 398bc6d767 | |||
| 5d3ef8d97f | |||
| 08a300fbe5 | |||
| 845770c4bb | |||
| 771dc10c85 | |||
| 2ac76202e5 | |||
| a5ecbe96e2 | |||
| 7240b22e48 | |||
| 1f00589cb4 | |||
| 60b14487a9 | |||
| 33bc85a843 | |||
| e6642674d4 | |||
| 8ad5fb3c44 | |||
| 1752d14c57 | |||
| ec4ccba1a7 | |||
| 0244492a89 | |||
| 546cf2c84d | |||
| d354dde774 | |||
| 22c9e9acd9 | |||
| 5dd14723e9 | |||
| 7134e80c44 | |||
| f7196ee8f9 | |||
| fdecd697b7 | |||
| 6c03dac869 | |||
| 6cdb564a9f | |||
| 0da8a8db36 | |||
| a4a9620889 | |||
| 2307424fb6 | |||
| ca124fb662 | |||
| 6787252f9b | |||
| ef3094f8d9 | |||
| a2a20133aa | |||
| bb750d186a | |||
| f2a7dde5ce | |||
| 73e2559a13 | |||
| 80f8a9d01c | |||
| 6f9883d373 | |||
| 41c920a4ec | |||
| 1f79b71738 | |||
| 64fb588556 | |||
| 90cfd004cb | |||
| ad927ec6c1 | |||
| 8a19d28859 | |||
| 7e24af9daf | |||
| 7518b514a7 | |||
| 96c38f50e4 | |||
| e723f1169f | |||
| 914005b2b6 | |||
| 972b903f52 | |||
| 61d072c8d6 | |||
| 8740848aac | |||
| 6766aa9732 | |||
| a57334d1f7 | |||
| 3dea16fad1 | |||
| 1bf4121796 | |||
| 93bebdd50b | |||
| 6a9532f10a | |||
| d88494e90e | |||
| e48f08b657 | |||
| a79e349f3d | |||
| 1c70570078 | |||
| 197dacfae7 | |||
| d8aad718d5 | |||
| 1d7bfc2781 | |||
| 8063717e4c | |||
| 3900b7ebc8 | |||
| 0296c646cb | |||
| 275dbc83dd | |||
| 1cd2dc8a42 | |||
| 60867af1a7 | |||
| 1e129bcc4d | |||
| e5c758bbc1 | |||
| 25780663a6 | |||
| aa327696fe | |||
| 1272a7c74b | |||
| dcbe6726b0 | |||
| ba68da5736 | |||
| fdabd945dc | |||
| 868edee5e6 | |||
| b91d0bb117 | |||
| cc91977e94 | |||
| 90b94f6ffb | |||
| 3c4cf56309 | |||
| b7f6195791 | |||
| 42eb82e6ca | |||
| 93def731ef | |||
| 60805f91d6 | |||
| 048480d5be | |||
| 173d388c12 | |||
| b1285fa7e3 | |||
| e34c857f6c | |||
| 7ff0e6cd4b | |||
| 0683094f84 | |||
| 983b7a85e1 | |||
| d015780b9f | |||
| aeece499bb | |||
| 8465b4e556 | |||
| e280785f48 | |||
| 5e0a59e4b3 | |||
| 30835797ff | |||
| 4077a01a6b | |||
| aed70ae40c | |||
| 6d44628352 | |||
| 7a398d34b1 | |||
| 69c5aeb1b3 | |||
| da545b890b | |||
| 6609bc09f2 | |||
| f06a6f42da | |||
| c9065d96a9 | |||
| 9d4e1362c4 | |||
| d3b69e04e1 | |||
| 0d54e8df89 | |||
| 8f949d0a2f | |||
| d67480e98b | |||
| 5d76ead469 | |||
| 2796100067 | |||
| a132f609d7 | |||
| 7f7456701d | |||
| ffce1a3e6b | |||
| e553f2c671 | |||
| 42c6533e16 | |||
| b0f4cb7d02 | |||
| f809dec874 | |||
| 2477500045 | |||
| d89539a437 | |||
| 4368f15097 | |||
| b90150279b | |||
| ca1b05e30d | |||
| 5c09ba9a2d | |||
| cfa3e3aff1 | |||
| 59ff4a0484 | |||
| b1db99f639 | |||
| ccbb838cef | |||
| b12f60e443 | |||
| 0d5ec8bfd5 | |||
| 5f67e85471 | |||
| d9228c368f | |||
| 8226505e5b | |||
| 41b8de09b7 | |||
| bbf06cd13d | |||
| 639cb17741 | |||
| 4643d34546 | |||
| 50035eae49 | |||
| 2d857a8635 | |||
| e4387b8dae | |||
| 188aca499a | |||
| 3040d362ef | |||
| a57aa07721 | |||
| f2b8e3407b | |||
| 1ec7cd3b89 | |||
| bd77463fa4 | |||
| 368954226a | |||
| 496d51c2a0 | |||
| b01b4f7aa7 | |||
| 49a699c858 | |||
| f68571ef7c | |||
| 6cc1735363 | |||
| d553dfd4b0 | |||
| f3e737720b | |||
| 22cf59345c | |||
| 16a46a4ea4 | |||
| 09d9728fb8 | |||
| c0df3e0202 | |||
| d09e283900 | |||
| 507c6c23b9 | |||
| 3daf936623 | |||
| e93c910347 | |||
| 7139e30296 | |||
| df1940a01c | |||
| aafb5a0285 | |||
| 033f981718 | |||
| 5bd55bdd09 | |||
| 76358e3e13 | |||
| 35c0eb3b0c | |||
| 7fad8ca98b | |||
| a2da27121e | |||
| 23ec07276a | |||
| 96cec0b407 | |||
| 47b94e68e3 | |||
| 0f4b1752e0 | |||
| eac66f5696 | |||
| b2c604f7b3 | |||
| 3f626b444f | |||
| c5b8931aa6 | |||
| 818d22ba61 | |||
| f9902964b0 | |||
| 27fdb1ebab | |||
| 1368ba8dc9 | |||
| 3618722574 | |||
| 24a76f53b4 | |||
| 86ce48ddc8 | |||
| cb592d687c | |||
| 2161ec98b0 | |||
| 5a6ee168c3 | |||
| 52292cab60 | |||
| 2933c879e1 | |||
| c8a19dff44 | |||
| a6768263d3 | |||
| e66306978a | |||
| 7f22809ebf | |||
| 302ebde422 | |||
| cf5624f377 | |||
| f386c9d024 | |||
| 530fcf0ea3 | |||
| 26e4091f28 | |||
| 32f86f750e | |||
| ebad631140 | |||
| b8304c03ee | |||
| 556c2d625f | |||
| aaa4469def | |||
| baa0069262 | |||
| 9ac4c7aef5 | |||
| cb2a35594f | |||
| dd501d0198 | |||
| b724d8fb32 | |||
| 7c6aee17e9 | |||
| 5e2c3a0a8b | |||
| f5121bd183 | |||
| 51b5334126 | |||
| 273c1956ab | |||
| f7c474ac2c | |||
| 4143dbd02d | |||
| 768eb3d1ed | |||
| 120bdca9eb | |||
| a5041aa34e | |||
| 59811c2841 | |||
| 38eee6135e | |||
| d3780848dc | |||
| 5719820fad | |||
| 9d15228c68 | |||
| c9c3623457 | |||
| aecc3d28bf | |||
| b51022575f | |||
| 6600e9c899 | |||
| 68aa2abbc0 | |||
| e0a483ca48 | |||
| 9b78cb3f7c | |||
| c6c90fde44 | |||
| 773500332b | |||
| 95eb00a81c | |||
| 3921b0974e | |||
| 2cd07c841f | |||
| 8f80f0e95c | |||
| 73ac2c0309 | |||
| a5ddb6c818 | |||
| 458e61e049 | |||
| 0815842640 | |||
| 53b31a5c1b | |||
| 292dd9115b | |||
| c6d0a9be00 | |||
| 14c3acc4b7 | |||
| a4098b5d25 | |||
| acdcca0b91 | |||
| 33ff82e766 | |||
| 5fd90e1c13 | |||
| a6eaec9ecb | |||
| f5553bcc06 | |||
| e0c68a8e1c | |||
| bc1b2dc5f4 | |||
| 0bb643672f | |||
| 813d60521c | |||
| 5212d17f49 | |||
| 932115585e | |||
| 948ffe4796 | |||
| 6b1dd07310 | |||
| dc2554c6d0 | |||
| 5c6514929e | |||
| 9739b3e2ef | |||
| 0b1f72f139 | |||
| 2a2e867784 | |||
| 79e0242468 | |||
| 242443d861 | |||
| 7c066b9ded | |||
| 159d605434 | |||
| 1971006a48 | |||
| 5c0c33a46b | |||
| 9bd255d9a5 | |||
| cc7f41d9ee | |||
| b4b0a37c2c | |||
| 8c841f97cc | |||
| a1ee352514 | |||
| c25b06b15f | |||
| 78bfb6a8cc | |||
| d8a8bf5f74 | |||
| b70c98ea74 | |||
| a8ad8c2a43 | |||
| 96f8cd3d60 | |||
| 91436ad247 | |||
| 678f911ff1 | |||
| afbe3ca3b9 | |||
| 32d6f2e50c | |||
| 9909f5b6be | |||
| af51465a6a | |||
| c2057656bc | |||
| 09a4e33f3f | |||
| c12f9d0272 | |||
| d2d1843e03 | |||
| a89a122b09 | |||
| e5e22f75fc | |||
| cab21e9d48 | |||
| 2e7c26fcc0 | |||
| 0f6c41679c | |||
| 777d397ae7 | |||
| 41258104f6 | |||
| 08a8e6b816 |
+81
@@ -0,0 +1,81 @@
|
||||
*.obj
|
||||
*.pdb
|
||||
*.user
|
||||
*.aps
|
||||
*.pch
|
||||
*.vspscc
|
||||
[Bb]in
|
||||
[Db]ebug*/
|
||||
obj/
|
||||
[Rr]elease*/
|
||||
_ReSharper*/
|
||||
_NCrunch_*/
|
||||
*.ncrunchsolution
|
||||
*.ncrunchsolution.user
|
||||
*.ncrunchproject
|
||||
*.crunchsolution.cache
|
||||
[Tt]est[Rr]esult*
|
||||
[Bb]uild[Ll]og.*
|
||||
*.[Pp]ublish.xml
|
||||
*.suo
|
||||
[sS]ource
|
||||
[sS]andbox
|
||||
umbraco.config
|
||||
*.vs10x
|
||||
App_Data/TEMP/*
|
||||
[Uu]mbraco/[Pp]resentation/[Uu]mbraco/[Pp]lugins/*
|
||||
[Uu]mbraco/[Pp]resentation/[Uu]ser[Cc]ontrols/*
|
||||
[Uu]mbraco/[Pp]resentation/[Ss]cripts/*
|
||||
[Uu]mbraco/[Pp]resentation/[Ff]onts/*
|
||||
[Uu]mbraco/[Pp]resentation/[Cc]ss/*
|
||||
|
||||
src/Umbraco.Web.UI/[Cc]ss/*
|
||||
src/Umbraco.Web.UI/App_Code/*
|
||||
src/Umbraco.Web.UI/App_Data/*
|
||||
src/Umbraco.Tests/App_Data/*
|
||||
src/Umbraco.Web.UI/[Mm]edia/*
|
||||
src/Umbraco.Web.UI/[Mm]aster[Pp]ages/*
|
||||
src/Umbraco.Web.UI/[Mm]acro[Ss]cripts/*
|
||||
src/Umbraco.Web.UI/[Xx]slt/*
|
||||
src/Umbraco.Web.UI/[Ii]mages/*
|
||||
src/Umbraco.Web.UI/[Ss]cripts/*
|
||||
src/Umbraco.Web.UI/Web.*.config.transformed
|
||||
|
||||
umbraco/presentation/umbraco/plugins/uComponents/uComponentsInstaller.ascx
|
||||
umbraco/presentation/packages/uComponents/MultiNodePicker/CustomTreeService.asmx
|
||||
_BuildOutput/*
|
||||
build/UmbracoCms.AllBinaries*zip
|
||||
build/UmbracoCms.WebPI*zip
|
||||
build/UmbracoCms*zip
|
||||
build/*.nupkg
|
||||
src/Umbraco.Tests/config/applications.config
|
||||
src/Umbraco.Tests/config/trees.config
|
||||
src/Umbraco.Web.UI/web.config
|
||||
*.orig
|
||||
src/Umbraco.Tests/config/404handlers.config
|
||||
src/Umbraco.Web.UI/[Vv]iews/*.cshtml
|
||||
src/Umbraco.Web.UI/[Vv]iews/*.vbhtml
|
||||
src/Umbraco.Tests/[Cc]onfig/umbracoSettings.config
|
||||
src/Umbraco.Web.UI/[Vv]iews/*
|
||||
src/packages/
|
||||
src/packages/repositories.config
|
||||
|
||||
src/Umbraco.Web.UI/[Ww]eb.config
|
||||
*.transformed
|
||||
webpihash.txt
|
||||
|
||||
node_modules
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.*
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.css
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
|
||||
src/Umbraco.Web.UI.Client/[Bb]uild/*
|
||||
src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
|
||||
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
|
||||
build/_BuildOutput/
|
||||
tools/NDepend/
|
||||
@@ -1,70 +0,0 @@
|
||||
syntax: regexp
|
||||
^src/packages/(?!repositories.config$)
|
||||
web.Template.[a-zA-Z0-9]*.Debug.config
|
||||
|
||||
syntax: glob
|
||||
*.obj
|
||||
*.pdb
|
||||
*.user
|
||||
*.aps
|
||||
*.pch
|
||||
*.vspscc
|
||||
[Bb]in
|
||||
[Db]ebug*/
|
||||
obj/
|
||||
[Rr]elease*/
|
||||
_ReSharper*/
|
||||
_NCrunch_*/
|
||||
*.ncrunchsolution
|
||||
*.ncrunchsolution.user
|
||||
*.ncrunchproject
|
||||
*.crunchsolution.cache
|
||||
[Tt]est[Rr]esult*
|
||||
[Bb]uild[Ll]og.*
|
||||
*.[Pp]ublish.xml
|
||||
*.suo
|
||||
[sS]ource
|
||||
[sS]andbox
|
||||
umbraco.config
|
||||
*.vs10x
|
||||
App_Data\TEMP\*
|
||||
umbraco\presentation\umbraco\plugins\*
|
||||
umbraco\presentation\usercontrols\*
|
||||
umbraco\presentation\scripts\*
|
||||
umbraco\presentation\fonts\*
|
||||
umbraco\presentation\css\*
|
||||
|
||||
src\Umbraco.Web.UI\[Cc]ss\*
|
||||
src\Umbraco.Web.UI\App_Code\*
|
||||
src\Umbraco.Web.UI\App_Data\*
|
||||
src\Umbraco.Tests\App_Data\*
|
||||
src\Umbraco.Web.UI\[Mm]edia\*
|
||||
src\Umbraco.Web.UI\[Mm]aster[Pp]ages\*
|
||||
src\Umbraco.Web.UI\[Mm]acro[Ss]cripts\*
|
||||
src\Umbraco.Web.UI\[Xx]slt\*
|
||||
src\Umbraco.Web.UI\[Ii]mages\*
|
||||
src\Umbraco.Web.UI\[Ss]cripts\*
|
||||
src\Umbraco.Web.UI\Web.*.config.transformed
|
||||
|
||||
umbraco\presentation\umbraco\plugins\uComponents\uComponentsInstaller.ascx
|
||||
umbraco\presentation\packages\uComponents\MultiNodePicker\CustomTreeService.asmx
|
||||
_BuildOutput/*
|
||||
*.ncrunchsolution
|
||||
build/UmbracoCms.AllBinaries*zip
|
||||
build/UmbracoCms.WebPI*zip
|
||||
build/UmbracoCms*zip
|
||||
build/*.nupkg
|
||||
src/Umbraco.Tests/config/applications.config
|
||||
src/Umbraco.Tests/config/trees.config
|
||||
src/Umbraco.Web.UI/web.config
|
||||
*.orig
|
||||
src/Umbraco.Tests/config/404handlers.config
|
||||
src/Umbraco.Web.UI/Views/*.cshtml
|
||||
src/Umbraco.Web.UI/Views/*.vbhtml
|
||||
src/Umbraco.Tests/config/umbracoSettings.config
|
||||
src/Umbraco.Web.UI/App_Plugins/*
|
||||
src/Umbraco.Web.UI/Views/*
|
||||
src/packages/
|
||||
|
||||
src\Umbraco.Web.UI\[W]eb.config
|
||||
*.transformed
|
||||
@@ -1,35 +0,0 @@
|
||||
d0aba247db91d1b70c39c6397b965ca370a67497 Sprint-Juno-A
|
||||
0b8f67be2ca8faf008151d87f232c698de69e735 Release-4.5.0
|
||||
5960c073250926d202861a09472f5f334da6e283 Sprint-Juno-B
|
||||
f15d4ff81a8368e9d42788f7e0ae726f7a70a3b1 Release-4.0.3
|
||||
283065df4d3c27245267709dd2644a479c4f62a5 Release-4.0.4.2
|
||||
ffc34b23e1a03785e4098afa4290d8c03cf10115 Release-4.5.2
|
||||
d03fcffb8834a9583a56813bb44b6abbd9f042cc Release-4.6.0
|
||||
1809f7b2593270c192cd47bdcfdb392100686f79 4.7.2
|
||||
488779dec0ceb1d2874bcef906241b919325c904 4.8.0-beta
|
||||
096f20bb0575d6199f20fcb3147b63554e765a74 Release-4.8.0
|
||||
8f8a203857886b373148af29edd57460a42940be Release-4.8.1
|
||||
de73e687ddf6086ed52b6554676c1632865d07f2 Release-4.9.0
|
||||
8d7d8609e2e4b971da99cd97f72132ce85ce3333 Release-4.9.1
|
||||
f6da531fbb4c251ff61d314e2a7effb13c71e74a Release-4.10.0
|
||||
20e4dff821d8ac2527a5353618fa1a23ea1d8b34 Release-4.11.0
|
||||
7f827760cb49d749616859f528d19dde64807947 Release-4.11.1
|
||||
7f827760cb49d749616859f528d19dde64807947 Release-4.11.1
|
||||
6eb5f2fb5a88aa29ea544499df9160a1b31b5638 Release-4.11.1
|
||||
73711b806a4044dbf0d7d7c095ddfdda23b09932 4.11.2
|
||||
73711b806a4044dbf0d7d7c095ddfdda23b09932 4.11.2
|
||||
0000000000000000000000000000000000000000 4.11.2
|
||||
73711b806a4044dbf0d7d7c095ddfdda23b09932 Release-4.11.2
|
||||
77db220b89e166b3c0736ed321ecfd6416cddbcd Release-4.11.2.1
|
||||
54cde33b809dcb3a1f7e7ae0d5375f6dd0d89c8d Release-4.11.2.2
|
||||
ff3bb24ea0c915878396a6ae27f1ff164e8ac150 Release-6.0.0-beta
|
||||
56015ac26f5ab60e3c61b1d09075297b660afa07 Release-6.0.0-RC
|
||||
1719fbd857f28b376639ac2aa0abada0ef2e7560 Release-6.0.0
|
||||
e02f5aebb87e3f07d27376647756caa9762931d8 Release-4.11.4
|
||||
14338b0ab1738fbd8987677ecdb9a73d79fc229d release-4.11.6
|
||||
ce47176bc6b9298741783e20f1fe2672c811f744 release-4.11.7
|
||||
b247b35d821144849f551e02da8ba719f91d5fb0 Release-6.0.2
|
||||
aed55cba29009ad3db48880a7cfb66407ce9805f release-6.0.3
|
||||
87cf618a39e38ec58df916d10e6a924de62ae37d release-6.1.0-beta
|
||||
0dee9964687ea51ea797984cf7cce3655d6a6558 release-6.0.4
|
||||
7670bb47a671a9ecc15118589d8048907ea76241 release-6.1.0-beta2
|
||||
@@ -0,0 +1,9 @@
|
||||
# The MIT License (MIT) #
|
||||
|
||||
Copyright (c) 2013 Umbraco
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,33 @@
|
||||
Umbraco CMS
|
||||
===========
|
||||
## Watch a five minute introduction video ##
|
||||
|
||||
[](http://umbraco.org/help-and-support/video-tutorials/getting-started/what-is-umbraco)
|
||||
|
||||
## Umbraco - the simple, flexible and friendly ASP.NET CMS ##
|
||||
|
||||
**More than 177,000 sites trust Umbraco**
|
||||
|
||||
For the first time on the Microsoft platform a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box. It's a developers dream and your users will love it too.
|
||||
|
||||
Used by more than 177,000 active websites including [http://daviscup.com](http://daviscup.com), [http://heinz.com](http://heinz.com), [http://peugeot.com](http://peugeot.com), [http://www.hersheys.com/](http://www.hersheys.com/) and **The Official ASP.NET and IIS.NET website from Microsoft** ([http://asp.net](http://asp.net) / [http://iis.net](http://iis.net)) you can be sure that the technology is proven, stable and scales.
|
||||
|
||||
To view more examples please visit [http://umbraco.com/why-umbraco/#caseStudies](http://umbraco.com/why-umbraco/#caseStudies)
|
||||
|
||||
## Downloading ##
|
||||
|
||||
The downloadable Umbraco releases live at [http://our.umbraco.org/download](http://our.umbraco.org/download).
|
||||
|
||||
## Forums ##
|
||||
|
||||
We have a forum running on [http://our.umbraco.org](http://our.umbraco.org). The discussions group on [Google Groups](https://groups.google.com/forum/#!forum/umbraco-dev) is for discussions on developing the core, and not on Umbraco-implementations or extensions in general. For those topics, please use [http://our.umbraco.org](http://our.umbraco.org).
|
||||
|
||||
## Contribute to Umbraco ##
|
||||
|
||||
If you want to contribute back to Umbraco you should check out our [guide to contributing](http://our.umbraco.org/contribute).
|
||||
|
||||
## Found a bug? ##
|
||||
|
||||
Another way you can contribute to Umbraco is by providing issue reports, for information on how to submit an issue report refer to our [online guide for reporting issues](http://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
|
||||
|
||||
To view existing issues please visit [http://issues.umbraco.org](http://issues.umbraco.org)
|
||||
+3
-1
@@ -1,10 +1,12 @@
|
||||
@ECHO OFF
|
||||
SET release=6.1.0
|
||||
SET release=6.1.3
|
||||
SET comment=
|
||||
SET version=%release%
|
||||
|
||||
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
|
||||
|
||||
ReplaceIISExpressPortNumber.exe ..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj %release%
|
||||
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment%
|
||||
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Code\dummy.txt
|
||||
|
||||
+20
-1
@@ -82,6 +82,7 @@
|
||||
<SolutionBinFolder>$(BuildFolder)bin\</SolutionBinFolder>
|
||||
<WebAppFolder>$(BuildFolder)WebApp\</WebAppFolder>
|
||||
<WebPiFolder>$(BuildFolder)WebPi\</WebPiFolder>
|
||||
<ConfigsFolder>$(BuildFolder)Configs\</ConfigsFolder>
|
||||
<SolutionBinFolderRelativeToProjects>$(BuildFolderRelativeToProjects)bin\</SolutionBinFolderRelativeToProjects>
|
||||
<SolutionBinFolderAbsolutePath>$(BuildFolderAbsolutePath)bin\</SolutionBinFolderAbsolutePath>
|
||||
<WebAppFolderRelativeToProjects>$(BuildFolderRelativeToProjects)WebApp\</WebAppFolderRelativeToProjects>
|
||||
@@ -197,7 +198,7 @@
|
||||
</Target>
|
||||
|
||||
<!-- Copy the transformed web.config file to the root -->
|
||||
<Target Name="CopyTransformedWebConfig" DependsOnTargets="CopyXmlDocumentation">
|
||||
<Target Name="CopyTransformedWebConfig" DependsOnTargets="CopyTransformedConfig">
|
||||
<ItemGroup>
|
||||
<WebConfigFile Include="..\src\Umbraco.Web.UI\web.$(BuildConfiguration).Config.transformed" />
|
||||
</ItemGroup>
|
||||
@@ -206,6 +207,24 @@
|
||||
DestinationFiles="$(WebAppFolder)Web.config"
|
||||
OverwriteReadOnlyFiles="true"
|
||||
SkipUnchangedFiles="false" />
|
||||
</Target>
|
||||
|
||||
<!-- Copy the config files and rename them to *.config.transform -->
|
||||
<Target Name="CopyTransformedConfig" DependsOnTargets="CopyXmlDocumentation">
|
||||
<ItemGroup>
|
||||
<ConfigFiles Include="$(WebAppFolder)config\*.config" />
|
||||
<WebConfigTransformFile Include="$(WebAppFolder)Web.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<Copy SourceFiles="@(ConfigFiles)"
|
||||
DestinationFiles="@(ConfigFiles->'$(ConfigsFolder)\%(RecursiveDir)%(Filename)%(Extension)')"
|
||||
OverwriteReadOnlyFiles="true"
|
||||
SkipUnchangedFiles="false" />
|
||||
|
||||
<Copy SourceFiles="@(WebConfigTransformFile)"
|
||||
DestinationFiles="$(ConfigsFolder)Web.config.transform"
|
||||
OverwriteReadOnlyFiles="true"
|
||||
SkipUnchangedFiles="false" />
|
||||
</Target>
|
||||
|
||||
<!-- Copy the xml documentation to the bin folder -->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>UmbracoCms.Core</id>
|
||||
<version>6.0.0-alpha</version>
|
||||
<version>6.1.2</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Morten Christensen</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
@@ -15,33 +15,32 @@
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[4.0.20710.0]" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="4.0.20710.0" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="4.0" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="4.0" />
|
||||
<dependency id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.0" />
|
||||
<dependency id="MiniProfiler" version="2.1.0" />
|
||||
<dependency id="HtmlAgilityPack" version="1.4.6" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1]" />
|
||||
<dependency id="SharpZipLib" version="0.86.0" />
|
||||
<dependency id="MySql.Data" version="[6.6.5]" />
|
||||
<dependency id="xmlrpcnet" version="2.5.0" />
|
||||
<dependency id="ClientDependency" version="[1.7.0,1.7.1)" />
|
||||
<dependency id="ClientDependency-Mvc" version="[1.7.0,1.7.1)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\_BuildOutput\WebApp\bin\businesslogic.dll" target="lib\businesslogic.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\businesslogic.xml" target="lib\businesslogic.xml" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\ClientDependency.Core.dll" target="lib\ClientDependency.Core.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\ClientDependency.Core.Mvc.dll" target="lib\ClientDependency.Core.Mvc.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\cms.dll" target="lib\cms.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\cms.xml" target="lib\cms.xml" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\controls.dll" target="lib\controls.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\controls.xml" target="lib\controls.xml" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\CookComputing.XmlRpcV2.dll" target="lib\CookComputing.XmlRpcV2.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Examine.dll" target="lib\Examine.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\HtmlAgilityPack.dll" target="lib\HtmlAgilityPack.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\ICSharpCode.SharpZipLib.dll" target="lib\ICSharpCode.SharpZipLib.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\interfaces.dll" target="lib\interfaces.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\interfaces.xml" target="lib\interfaces.xml" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\log4net.dll" target="lib\log4net.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Lucene.Net.dll" target="lib\Lucene.Net.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Lucene.Net.xml" target="lib\Lucene.Net.xml" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Microsoft.ApplicationBlocks.Data.dll" target="lib\Microsoft.ApplicationBlocks.Data.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Microsoft.Web.Helpers.dll" target="lib\Microsoft.Web.Helpers.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\MySql.Data.dll" target="lib\MySql.Data.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.47x.dll" target="lib\Our.Umbraco.uGoLive.47x.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.Checks.dll" target="lib\Our.Umbraco.uGoLive.Checks.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.dll" target="lib\Our.Umbraco.uGoLive.dll" />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>UmbracoCms</id>
|
||||
<version>6.0.0-alpha</version>
|
||||
<version>6.1.2</version>
|
||||
<title>Umbraco Cms</title>
|
||||
<authors>Morten Christensen</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
@@ -10,8 +10,8 @@
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Installs Umbraco Cms in your Visual Studio ASP.NET Webforms project</description>
|
||||
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET Webforms project</summary>
|
||||
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
|
||||
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
@@ -21,14 +21,14 @@
|
||||
<files>
|
||||
<file src="..\_BuildOutput\WebApp\bin\amd64\**" target="Content\bin\amd64" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\x86\**" target="Content\bin\x86" />
|
||||
<file src="..\_BuildOutput\WebApp\config\*.config" target="Content\config" />
|
||||
<file src="..\_BuildOutput\Configs\**" target="Content\config" exclude="..\_BuildOutput\Configs\Web.config.transform" />
|
||||
<file src="..\_BuildOutput\WebApp\css\**" target="Content\css" />
|
||||
<file src="..\_BuildOutput\WebApp\macroScripts\**" target="Content\macroScripts" />
|
||||
<file src="..\_BuildOutput\WebApp\masterpages\**" target="Content\masterpages" />
|
||||
<file src="..\_BuildOutput\WebApp\media\**" target="Content\media" />
|
||||
<file src="..\_BuildOutput\WebApp\scripts\**" target="Content\scripts" />
|
||||
<file src="..\_BuildOutput\WebApp\usercontrols\**" target="Content\usercontrols" />
|
||||
<file src="..\_BuildOutput\WebApp\Views\**" target="Content\Views" />
|
||||
<file src="..\_BuildOutput\WebApp\Views\**" target="Content\Views" exclude="..\_BuildOutput\WebApp\Views\Web.config" />
|
||||
<file src="..\_BuildOutput\WebApp\xslt\**" target="Content\xslt" />
|
||||
<file src="..\_BuildOutput\WebApp\default.aspx" target="Content\default.aspx" />
|
||||
<file src="..\_BuildOutput\WebApp\Web.config" target="Content\Web.config" />
|
||||
@@ -36,7 +36,7 @@
|
||||
<file src="..\_BuildOutput\WebApp\App_Code\**" target="UmbracoFiles\App_Code" />
|
||||
<file src="..\_BuildOutput\WebApp\App_Data\**" target="UmbracoFiles\App_Data" />
|
||||
<file src="..\_BuildOutput\WebApp\App_Plugins\**" target="UmbracoFiles\App_Plugins" />
|
||||
<file src="..\_BuildOutput\WebApp\config\**" target="UmbracoFiles\config" />
|
||||
<file src="..\_BuildOutput\WebApp\config\splashes\**" target="UmbracoFiles\config\splashes" />
|
||||
<file src="..\_BuildOutput\WebApp\install\**" target="UmbracoFiles\install" />
|
||||
<file src="..\_BuildOutput\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="..\_BuildOutput\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
|
||||
@@ -44,5 +44,6 @@
|
||||
<file src="..\_BuildOutput\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="tools\install.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\Readme.txt" target="tools\Readme.txt" />
|
||||
<file src="build\**" target="build" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="AddUmbracoFilesToOutput">
|
||||
<ItemGroup>
|
||||
<UmbracoFiles Include=".\umbraco\**\*;" />
|
||||
<UmbracoClientFiles Include=".\umbraco_client\**\*;" />
|
||||
<AppBrowsersFiles Include=".\App_Browsers\**\*" />
|
||||
<FilesForPackagingFromProject Include="%(UmbracoFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(UmbracoClientFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco_client\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(AppBrowsersFiles.Identity)">
|
||||
<DestinationRelativePath>App_Browsers\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="AddUmbracoFilesToOutput">
|
||||
<ItemGroup>
|
||||
<UmbracoFiles Include=".\umbraco\**\*;" />
|
||||
<UmbracoClientFiles Include=".\umbraco_client\**\*;" />
|
||||
<AppBrowsersFiles Include=".\App_Browsers\**\*" />
|
||||
<FilesForPackagingFromProject Include="%(UmbracoFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(UmbracoClientFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco_client\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(AppBrowsersFiles.Identity)">
|
||||
<DestinationRelativePath>App_Browsers\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="AddUmbracoFilesToOutput">
|
||||
<ItemGroup>
|
||||
<UmbracoFiles Include=".\umbraco\**\*;" />
|
||||
<UmbracoClientFiles Include=".\umbraco_client\**\*;" />
|
||||
<AppBrowsersFiles Include=".\App_Browsers\**\*" />
|
||||
<FilesForPackagingFromProject Include="%(UmbracoFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(UmbracoClientFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco_client\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(AppBrowsersFiles.Identity)">
|
||||
<DestinationRelativePath>App_Browsers\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,15 +1,18 @@
|
||||
A note about running Umbraco from Visual Studio.
|
||||
|
||||
When upgrading your website using nuget a backup of config files and web.config will be created and the files will
|
||||
be overwritten with those from the current release. This means that you'll have to merge the files if you made any
|
||||
changes to the previous config files.
|
||||
When upgrading your website using nuget a backup of config files and web.config will be created. Only the web.config will
|
||||
be overwritten by default to ensure that it has the necessary settings from the current release. This means that you'll
|
||||
have to merge the files if you made any changes to the previous config files.
|
||||
The config files found in the config folder will usually not be changed for patch releases, so they can usually be skipped,
|
||||
but the web.config will have to have its previous "umbracoConfigurationStatus"-appsetting and "umbracoDbDSN" connection string
|
||||
copied over (as a minimum).
|
||||
|
||||
It's not possible to create a deploy package from Visual Studio, which contains everything out of the box. This is
|
||||
due to a number of files and folders that are not added to the Visual Studio project. These folders include:
|
||||
install, umbraco and umbraco_client.
|
||||
A custom deploy script will be added in a later release.
|
||||
|
||||
Please read the release notes on Codeplex:
|
||||
http://umbraco.codeplex.com/releases
|
||||
Please read the release notes on our.umbraco.org:
|
||||
http://our.umbraco.org/contribute/releases
|
||||
|
||||
- Umbraco
|
||||
Binary file not shown.
Binary file not shown.
@@ -17,7 +17,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(PackageSources)' == '' ">
|
||||
<!-- Package sources used to restore packages. By default will used the registered sources under %APPDATA%\NuGet\NuGet.Config -->
|
||||
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
|
||||
<!-- The official NuGet package source (https://nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
|
||||
<!--
|
||||
<PackageSource Include="https://nuget.org/api/v2/" />
|
||||
<PackageSource Include="https://my-nuget-source/nuget/" />
|
||||
@@ -54,10 +55,10 @@
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
|
||||
<!-- We need to ensure packages are restored prior to assembly resolve -->
|
||||
<ResolveReferencesDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
RestorePackages;
|
||||
$(ResolveReferencesDependsOn);
|
||||
</ResolveReferencesDependsOn>
|
||||
$(BuildDependsOn);
|
||||
</BuildDependsOn>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
|
||||
@@ -75,7 +76,7 @@
|
||||
This effectively acts as a lock that makes sure that the download operation will only happen once and all
|
||||
parallel builds will have to wait for it to complete.
|
||||
-->
|
||||
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT" />
|
||||
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_DownloadNuGet">
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Umbraco.Core.Cache
|
||||
public const string UserContextCacheKey = "UmbracoUserContext";
|
||||
public const string UserContextTimeoutCacheKey = "UmbracoUserContextTimeout";
|
||||
public const string UserCacheKey = "UmbracoUser";
|
||||
public const string UserPermissionsCacheKey = "UmbracoUserPermissions";
|
||||
|
||||
public const string ContentTypeCacheKey = "UmbracoContentType";
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Umbraco.Core.Cache
|
||||
/// An abstract class for implementing a runtime cache provider
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// THIS MUST REMAIN INTERNAL UNTIL WE STREAMLINE HOW ALL CACHE IS HANDLED, WE NEED TO SUPPORT HTTP RUNTIME CACHE, IN MEMORY CACHE, ETC...
|
||||
/// THIS MUST REMAIN INTERNAL UNTIL WE STREAMLINE HOW ALL CACHE IS HANDLED, WE NEED TO SUPPORT HTTP RUNTIME CACHE, IN MEMORY CACHE, REQUEST CACHE, ETC...
|
||||
/// </remarks>
|
||||
internal abstract class RuntimeCacheProviderBase : CacheProviderBase
|
||||
{
|
||||
|
||||
@@ -1305,6 +1305,25 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default document type property used when adding new properties through the back-office
|
||||
/// </summary>
|
||||
/// <value>Configured text for the default document type property</value>
|
||||
/// <remarks>If undefined, 'Textstring' is the default</remarks>
|
||||
public static string DefaultDocumentTypeProperty
|
||||
{
|
||||
get
|
||||
{
|
||||
var defaultDocumentTypeProperty = GetKey("/settings/content/defaultDocumentTypeProperty");
|
||||
if (string.IsNullOrEmpty(defaultDocumentTypeProperty))
|
||||
{
|
||||
defaultDocumentTypeProperty = "Textstring";
|
||||
}
|
||||
|
||||
return defaultDocumentTypeProperty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configuration regarding webservices
|
||||
/// </summary>
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("6.1.0");
|
||||
private static readonly Version Version = new Version("6.1.3");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -169,6 +169,20 @@ namespace Umbraco.Core
|
||||
Initialize(providerName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures a ConnectionString for the Umbraco database that uses Microsoft SQL Server integrated security.
|
||||
/// </summary>
|
||||
/// <param name="server">Name or address of the database server</param>
|
||||
/// <param name="databaseName">Name of the database</param>
|
||||
public void ConfigureIntegratedSecurityDatabaseConnection(string server, string databaseName)
|
||||
{
|
||||
const string providerName = "System.Data.SqlClient";
|
||||
string connectionString = String.Format("Server={0};Database={1};Integrated Security=true", server, databaseName);
|
||||
|
||||
SaveConnectionString(connectionString, providerName);
|
||||
Initialize(providerName);
|
||||
}
|
||||
|
||||
internal string BuildAzureConnectionString(string server, string databaseName, string user, string password)
|
||||
{
|
||||
if (server.Contains(".") && ServerStartsWithTcp(server) == false)
|
||||
@@ -393,8 +407,8 @@ namespace Umbraco.Core
|
||||
if (supportsCaseInsensitiveQueries == false)
|
||||
{
|
||||
message = "<p> </p><p>The database you're trying to use does not support case insensitive queries. <br />We currently do not support these types of databases.</p>" +
|
||||
"<p>You can fix this by changing the following two settings in your my.ini file in your MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1\nlower_case_file_system=1</pre><br />" +
|
||||
"<p>You can fix this by changing the following setting in your my.ini file in your MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1</pre><br />" +
|
||||
"<p>Note: Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
|
||||
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
@@ -404,8 +418,8 @@ namespace Umbraco.Core
|
||||
else if (supportsCaseInsensitiveQueries == null)
|
||||
{
|
||||
message = "<p> </p><p>Warning! Could not check if your database type supports case insensitive queries. <br />We currently do not support these databases that do not support case insensitive queries.</p>" +
|
||||
"<p>You can check this by looking for the following two settings in your my.ini file in your MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1\nlower_case_file_system=1</pre><br />" +
|
||||
"<p>You can check this by looking for the following setting in your my.ini file in your MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1</pre><br />" +
|
||||
"<p>Note: Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
|
||||
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
@@ -418,8 +432,8 @@ namespace Umbraco.Core
|
||||
"<p>Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.</p>" +
|
||||
"<p>However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries</p>" +
|
||||
"<p>Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
|
||||
"<p>They can check this by looking for the following two settings in the my.ini file in their MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1\nlower_case_file_system=1</pre><br />" +
|
||||
"<p>They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1</pre><br />" +
|
||||
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static class DateTimeExtensions
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns the DateTime as an ISO formatted string that is globally expectable
|
||||
/// </summary>
|
||||
/// <param name="dt"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToIsoString(this DateTime dt)
|
||||
{
|
||||
return dt.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,8 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
if (virtualPath.StartsWith("~"))
|
||||
return virtualPath.Replace("~", SystemDirectories.Root).Replace("//", "/");
|
||||
else if (Uri.IsWellFormedUriString(virtualPath, UriKind.Absolute))
|
||||
return virtualPath;
|
||||
else
|
||||
return VirtualPathUtility.ToAbsolute(virtualPath, SystemDirectories.Root);
|
||||
}
|
||||
@@ -249,6 +251,32 @@ namespace Umbraco.Core.IO
|
||||
return _rootDir;
|
||||
}
|
||||
|
||||
internal static string GetRootDirectoryBinFolder()
|
||||
{
|
||||
string binFolder = string.Empty;
|
||||
if (string.IsNullOrEmpty(_rootDir))
|
||||
{
|
||||
binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory.FullName;
|
||||
return binFolder;
|
||||
}
|
||||
|
||||
binFolder = Path.Combine(GetRootDirectorySafe(), "bin");
|
||||
|
||||
#if DEBUG
|
||||
var debugFolder = Path.Combine(binFolder, "debug");
|
||||
if (Directory.Exists(debugFolder))
|
||||
return debugFolder;
|
||||
#endif
|
||||
var releaseFolder = Path.Combine(binFolder, "release");
|
||||
if (Directory.Exists(releaseFolder))
|
||||
return releaseFolder;
|
||||
|
||||
if (Directory.Exists(binFolder))
|
||||
return binFolder;
|
||||
|
||||
return _rootDir;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to overwrite RootDirectory, which would otherwise be resolved
|
||||
/// automatically upon application start.
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
internal class ResizedImage
|
||||
{
|
||||
public ResizedImage()
|
||||
{
|
||||
}
|
||||
|
||||
public ResizedImage(int width, int height, string fileName)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
FileName = fileName;
|
||||
}
|
||||
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
public string FileName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
public class UmbracoMediaFile
|
||||
{
|
||||
private readonly MediaFileSystem _fs;
|
||||
|
||||
#region Constructors
|
||||
|
||||
public UmbracoMediaFile()
|
||||
{
|
||||
_fs = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
|
||||
}
|
||||
|
||||
public UmbracoMediaFile(string path)
|
||||
{
|
||||
_fs = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
|
||||
|
||||
Path = path;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static Methods
|
||||
|
||||
//MB: Do we really need all these overloads? looking through the code, only one of them is actually used
|
||||
|
||||
public static UmbracoMediaFile Save(HttpPostedFile file, string path)
|
||||
{
|
||||
return Save(file.InputStream, path);
|
||||
}
|
||||
|
||||
public static UmbracoMediaFile Save(HttpPostedFileBase file, string path)
|
||||
{
|
||||
return Save(file.InputStream, path);
|
||||
}
|
||||
|
||||
public static UmbracoMediaFile Save(Stream inputStream, string path)
|
||||
{
|
||||
var fs = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
|
||||
fs.AddFile(path, inputStream);
|
||||
|
||||
return new UmbracoMediaFile(path);
|
||||
}
|
||||
|
||||
public static UmbracoMediaFile Save(byte[] file, string relativePath)
|
||||
{
|
||||
return Save(new MemoryStream(file), relativePath);
|
||||
}
|
||||
|
||||
public static UmbracoMediaFile Save(HttpPostedFile file)
|
||||
{
|
||||
var tempDir = System.IO.Path.Combine("uploads", Guid.NewGuid().ToString());
|
||||
return Save(file, tempDir);
|
||||
}
|
||||
|
||||
//filebase overload...
|
||||
public static UmbracoMediaFile Save(HttpPostedFileBase file)
|
||||
{
|
||||
var tempDir = System.IO.Path.Combine("uploads", Guid.NewGuid().ToString());
|
||||
return Save(file, tempDir);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private long? _length;
|
||||
private Size? _size;
|
||||
|
||||
/// <summary>
|
||||
/// Initialized values that don't require opening the file.
|
||||
/// </summary>
|
||||
private void Initialize()
|
||||
{
|
||||
Filename = _fs.GetFileName(Path);
|
||||
Extension = _fs.GetExtension(Path) != null
|
||||
? _fs.GetExtension(Path).Substring(1).ToLowerInvariant()
|
||||
: "";
|
||||
Url = _fs.GetUrl(Path);
|
||||
}
|
||||
|
||||
public string Filename { get; private set; }
|
||||
|
||||
public string Extension { get; private set; }
|
||||
|
||||
public string Path { get; private set; }
|
||||
|
||||
public string Url { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the length of the file in bytes
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We are lazy loading this, don't go opening the file on ctor like we were doing.
|
||||
/// </remarks>
|
||||
public long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_length == null)
|
||||
{
|
||||
_length = _fs.GetSize(Path);
|
||||
}
|
||||
return _length.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SupportsResizing
|
||||
{
|
||||
get
|
||||
{
|
||||
return ("," + UmbracoSettings.ImageFileTypes + ",").Contains(string.Format(",{0},", Extension));
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFriendlyName()
|
||||
{
|
||||
return Filename.SplitPascalCasing().ToFirstUpperInvariant();
|
||||
}
|
||||
|
||||
public Size GetDimensions()
|
||||
{
|
||||
if (_size == null)
|
||||
{
|
||||
EnsureFileSupportsResizing();
|
||||
|
||||
var fs = _fs.OpenFile(Path);
|
||||
var image = Image.FromStream(fs);
|
||||
var fileWidth = image.Width;
|
||||
var fileHeight = image.Height;
|
||||
fs.Close();
|
||||
image.Dispose();
|
||||
|
||||
_size = new Size(fileWidth, fileHeight);
|
||||
}
|
||||
return _size.Value;
|
||||
}
|
||||
|
||||
public string Resize(int width, int height)
|
||||
{
|
||||
EnsureFileSupportsResizing();
|
||||
|
||||
var fileNameThumb = DoResize(width, height, 0, string.Empty);
|
||||
|
||||
return _fs.GetUrl(fileNameThumb);
|
||||
}
|
||||
|
||||
public string Resize(int maxWidthHeight, string fileNameAddition)
|
||||
{
|
||||
EnsureFileSupportsResizing();
|
||||
|
||||
var fileNameThumb = DoResize(GetDimensions().Width, GetDimensions().Height, maxWidthHeight, fileNameAddition);
|
||||
|
||||
return _fs.GetUrl(fileNameThumb);
|
||||
}
|
||||
|
||||
private string DoResize(int width, int height, int maxWidthHeight, string fileNameAddition)
|
||||
{
|
||||
using (var fs = _fs.OpenFile(Path))
|
||||
{
|
||||
using (var image = Image.FromStream(fs))
|
||||
{
|
||||
var fileNameThumb = string.IsNullOrWhiteSpace(fileNameAddition)
|
||||
? string.Format("{0}_UMBRACOSYSTHUMBNAIL.jpg", Path.Substring(0, Path.LastIndexOf(".", StringComparison.Ordinal)))
|
||||
: string.Format("{0}_{1}.jpg", Path.Substring(0, Path.LastIndexOf(".", StringComparison.Ordinal)), fileNameAddition);
|
||||
|
||||
var thumbnail = GenerateThumbnail(image, maxWidthHeight, width, height, fileNameThumb, maxWidthHeight == 0);
|
||||
|
||||
return thumbnail.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureFileSupportsResizing()
|
||||
{
|
||||
if (SupportsResizing == false)
|
||||
throw new InvalidOperationException(string.Format("The file {0} is not an image, so can't get dimensions", Filename));
|
||||
}
|
||||
|
||||
private ResizedImage GenerateThumbnail(Image image, int maxWidthHeight, int fileWidth, int fileHeight, string thumbnailFileName, bool useFixedDimensions)
|
||||
{
|
||||
// Generate thumbnail
|
||||
float f = 1;
|
||||
if (useFixedDimensions == false)
|
||||
{
|
||||
var fx = (float)image.Size.Width / (float)maxWidthHeight;
|
||||
var fy = (float)image.Size.Height / (float)maxWidthHeight;
|
||||
|
||||
// must fit in thumbnail size
|
||||
f = Math.Max(fx, fy);
|
||||
}
|
||||
|
||||
var widthTh = (int)Math.Round((float)fileWidth / f);
|
||||
var heightTh = (int)Math.Round((float)fileHeight / f);
|
||||
|
||||
// fixes for empty width or height
|
||||
if (widthTh == 0)
|
||||
widthTh = 1;
|
||||
if (heightTh == 0)
|
||||
heightTh = 1;
|
||||
|
||||
// Create new image with best quality settings
|
||||
using (var bp = new Bitmap(widthTh, heightTh))
|
||||
{
|
||||
using (var g = Graphics.FromImage(bp))
|
||||
{
|
||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
g.CompositingQuality = CompositingQuality.HighQuality;
|
||||
|
||||
// Copy the old image to the new and resized
|
||||
var rect = new Rectangle(0, 0, widthTh, heightTh);
|
||||
g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
|
||||
|
||||
// Copy metadata
|
||||
var imageEncoders = ImageCodecInfo.GetImageEncoders();
|
||||
|
||||
var codec = Extension.ToLower() == "png" || Extension.ToLower() == "gif"
|
||||
? imageEncoders.Single(t => t.MimeType.Equals("image/png"))
|
||||
: imageEncoders.Single(t => t.MimeType.Equals("image/jpeg"));
|
||||
|
||||
// Set compresion ratio to 90%
|
||||
var ep = new EncoderParameters();
|
||||
ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
|
||||
|
||||
// Save the new image using the dimensions of the image
|
||||
var newFileName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", string.Format("{0}x{1}", widthTh, heightTh));
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
bp.Save(ms, codec, ep);
|
||||
ms.Seek(0, 0);
|
||||
|
||||
_fs.AddFile(newFileName, ms);
|
||||
}
|
||||
|
||||
return new ResizedImage(widthTh, heightTh, newFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Models
|
||||
private DateTime? _expireDate;
|
||||
private int _writer;
|
||||
private string _nodeName;//NOTE Once localization is introduced this will be the non-localized Node Name.
|
||||
|
||||
private bool _permissionsChanged;
|
||||
/// <summary>
|
||||
/// Constructor for creating a Content object
|
||||
/// </summary>
|
||||
@@ -82,6 +82,7 @@ namespace Umbraco.Core.Models
|
||||
private static readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ExpireDate);
|
||||
private static readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo<Content, int>(x => x.WriterId);
|
||||
private static readonly PropertyInfo NodeNameSelector = ExpressionHelper.GetPropertyInfo<Content, string>(x => x.NodeName);
|
||||
private static readonly PropertyInfo PermissionsChangedSelector = ExpressionHelper.GetPropertyInfo<Content, bool>(x => x.PermissionsChanged);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template used by the Content.
|
||||
@@ -243,6 +244,22 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to track if permissions have been changed during the saving process for this entity
|
||||
/// </summary>
|
||||
internal bool PermissionsChanged
|
||||
{
|
||||
get { return _permissionsChanged; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_permissionsChanged = value;
|
||||
return _permissionsChanged;
|
||||
}, _permissionsChanged, PermissionsChangedSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ContentType used by this content object
|
||||
/// </summary>
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace Umbraco.Core.Models
|
||||
private bool _trashed;
|
||||
private int _contentTypeId;
|
||||
private PropertyCollection _properties;
|
||||
private readonly List<Property> _lastInvalidProperties = new List<Property>();
|
||||
|
||||
/// <summary>
|
||||
/// Protected constructor for ContentBase (Base for Content and Media)
|
||||
@@ -421,7 +422,17 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>True if content is valid otherwise false</returns>
|
||||
public virtual bool IsValid()
|
||||
{
|
||||
return Properties.Any(property => !property.IsValid()) == false;
|
||||
_lastInvalidProperties.Clear();
|
||||
_lastInvalidProperties.AddRange(Properties.Where(property => property.IsValid() == false));
|
||||
return _lastInvalidProperties.Any() == false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a collection of the result of the last validation process, this collection contains all invalid properties.
|
||||
/// </summary>
|
||||
internal IEnumerable<Property> LastInvalidProperties
|
||||
{
|
||||
get { return _lastInvalidProperties; }
|
||||
}
|
||||
|
||||
public abstract void ChangeTrashedState(bool isTrashed, int parentId = -20);
|
||||
|
||||
@@ -16,6 +16,7 @@ using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -105,6 +106,50 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the IContentBase has children
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is a bit of a hack because we need to type check!
|
||||
/// </remarks>
|
||||
internal static bool HasChildren(IContentBase content, ServiceContext services)
|
||||
{
|
||||
if (content is IContent)
|
||||
{
|
||||
return services.ContentService.HasChildren(content.Id);
|
||||
}
|
||||
if (content is IMedia)
|
||||
{
|
||||
return services.MediaService.HasChildren(content.Id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the children for the content base item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is a bit of a hack because we need to type check!
|
||||
/// </remarks>
|
||||
internal static IEnumerable<IContentBase> Children(IContentBase content, ServiceContext services)
|
||||
{
|
||||
if (content is IContent)
|
||||
{
|
||||
return services.ContentService.GetChildren(content.Id);
|
||||
}
|
||||
if (content is IMedia)
|
||||
{
|
||||
return services.MediaService.GetChildren(content.Id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set property values by alias with an annonymous object
|
||||
/// </summary>
|
||||
@@ -467,38 +512,7 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
|
||||
internal static XElement ToDeepXml(this IContent content)
|
||||
{
|
||||
var xml = content.ToXml();
|
||||
|
||||
var descendants = content.Descendants().ToArray();
|
||||
var currentChildren = descendants.Where(x => x.ParentId == content.Id);
|
||||
AddChildXml(descendants, currentChildren, xml);
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by ToDeepXml to recursively add children
|
||||
/// </summary>
|
||||
/// <param name="originalDescendants"></param>
|
||||
/// <param name="currentChildren"></param>
|
||||
/// <param name="currentXml"></param>
|
||||
private static void AddChildXml(
|
||||
IContent[] originalDescendants,
|
||||
IEnumerable<IContent> currentChildren,
|
||||
XElement currentXml)
|
||||
{
|
||||
foreach (var child in currentChildren)
|
||||
{
|
||||
//add the child's xml
|
||||
var childXml = child.ToXml();
|
||||
currentXml.Add(childXml);
|
||||
//copy local (out of closure)
|
||||
var c = child;
|
||||
//get this item's children
|
||||
var children = originalDescendants.Where(x => x.ParentId == c.Id);
|
||||
//recurse and add it's children to the child xml element
|
||||
AddChildXml(originalDescendants, children, childXml);
|
||||
}
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(content, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -508,21 +522,7 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
|
||||
public static XElement ToXml(this IContent content)
|
||||
{
|
||||
//nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias);
|
||||
var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "node" : content.ContentType.Alias.ToSafeAliasWithForcingCheck();
|
||||
|
||||
var x = content.ToXml(nodeName);
|
||||
x.Add(new XAttribute("nodeType", content.ContentType.Id));
|
||||
x.Add(new XAttribute("creatorName", content.GetCreatorProfile().Name));
|
||||
x.Add(new XAttribute("writerName", content.GetWriterProfile().Name));
|
||||
x.Add(new XAttribute("writerID", content.WriterId));
|
||||
x.Add(new XAttribute("template", content.Template == null ? "0" : content.Template.Id.ToString()));
|
||||
if (UmbracoSettings.UseLegacyXmlSchema)
|
||||
{
|
||||
x.Add(new XAttribute("nodeTypeAlias", content.ContentType.Alias));
|
||||
}
|
||||
|
||||
return x;
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -532,52 +532,13 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
|
||||
public static XElement ToXml(this IMedia media)
|
||||
{
|
||||
//nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias);
|
||||
var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "node" : media.ContentType.Alias.ToSafeAliasWithForcingCheck();
|
||||
|
||||
var x = media.ToXml(nodeName);
|
||||
x.Add(new XAttribute("nodeType", media.ContentType.Id));
|
||||
x.Add(new XAttribute("writerName", media.GetCreatorProfile().Name));
|
||||
x.Add(new XAttribute("writerID", media.CreatorId));
|
||||
x.Add(new XAttribute("version", media.Version));
|
||||
x.Add(new XAttribute("template", 0));
|
||||
if (UmbracoSettings.UseLegacyXmlSchema)
|
||||
{
|
||||
x.Add(new XAttribute("nodeTypeAlias", media.ContentType.Alias));
|
||||
}
|
||||
|
||||
return x;
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(media);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the xml representation for the <see cref="IContentBase"/> object
|
||||
/// </summary>
|
||||
/// <param name="contentBase"><see cref="IContent"/> to generate xml for</param>
|
||||
/// <param name="nodeName"></param>
|
||||
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
|
||||
private static XElement ToXml(this IContentBase contentBase, string nodeName)
|
||||
internal static XElement ToDeepXml(this IMedia media)
|
||||
{
|
||||
// note: that one will take care of umbracoUrlName
|
||||
var url = contentBase.GetUrlSegment();
|
||||
|
||||
var xml = new XElement(nodeName,
|
||||
new XAttribute("id", contentBase.Id),
|
||||
new XAttribute("parentID", contentBase.Level > 1 ? contentBase.ParentId : -1),
|
||||
new XAttribute("level", contentBase.Level),
|
||||
new XAttribute("creatorID", contentBase.CreatorId),
|
||||
new XAttribute("sortOrder", contentBase.SortOrder),
|
||||
new XAttribute("createDate", contentBase.CreateDate.ToString("s")),
|
||||
new XAttribute("updateDate", contentBase.UpdateDate.ToString("s")),
|
||||
new XAttribute("nodeName", contentBase.Name),
|
||||
new XAttribute("urlName", url),
|
||||
new XAttribute("path", contentBase.Path),
|
||||
new XAttribute("isDoc", ""));
|
||||
|
||||
foreach (var property in contentBase.Properties.Where(p => p != null))
|
||||
xml.Add(property.ToXml());
|
||||
|
||||
return xml;
|
||||
}
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(media, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the xml representation for the <see cref="IContent"/> object
|
||||
|
||||
@@ -477,6 +477,15 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a PropertyGroup from the current ContentType
|
||||
/// </summary>
|
||||
/// <param name="propertyGroupName">Name of the <see cref="PropertyGroup"/> to remove</param>
|
||||
public void RemovePropertyGroup(string propertyGroupName)
|
||||
{
|
||||
PropertyGroups.RemoveItem(propertyGroupName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the ParentId from the lazy integer id
|
||||
/// </summary>
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Umbraco.Core.Models
|
||||
if (contentType.ContentTypeComposition.Any(x => x.CompositionAliases().Any(ContentTypeCompositionExists)))
|
||||
return false;
|
||||
|
||||
if (!ContentTypeCompositionExists(contentType.Alias))
|
||||
if (ContentTypeCompositionExists(contentType.Alias) == false)
|
||||
{
|
||||
_contentTypeComposition.Add(contentType);
|
||||
OnPropertyChanged(ContentTypeCompositionSelector);
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
/// Please note that resetting the dirty properties could potentially
|
||||
/// obstruct the saving of a new or updated entity.
|
||||
/// </remarks>
|
||||
internal void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
|
||||
internal virtual void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
|
||||
{
|
||||
if (rememberPreviouslyChangedProperties)
|
||||
{
|
||||
|
||||
@@ -64,6 +64,12 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="propertyTypeAlias">Alias of the <see cref="PropertyType"/> to remove</param>
|
||||
void RemovePropertyType(string propertyTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a PropertyGroup from the current ContentType
|
||||
/// </summary>
|
||||
/// <param name="propertyGroupName">Name of the <see cref="PropertyGroup"/> to remove</param>
|
||||
void RemovePropertyGroup(string propertyGroupName);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the ParentId from the lazy integer id
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
|
||||
@@ -7,17 +7,25 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// Defines the interface for a <see cref="User"/>
|
||||
/// </summary>
|
||||
/// <remarks>Will be left internal until a proper Membership implementation is part of the roadmap</remarks>
|
||||
internal interface IUser : IMembershipUser
|
||||
internal interface IUser : IMembershipUser, IUserProfile
|
||||
{
|
||||
string Name { get; set; }
|
||||
new object Id { get; set; }
|
||||
//string Name { get; set; }
|
||||
int SessionTimeout { get; set; }
|
||||
int StartContentId { get; set; }
|
||||
int StartMediaId { get; set; }
|
||||
string Language { get; set; }
|
||||
bool DefaultToLiveEditing { get; set; }
|
||||
IEnumerable<string> Applications { get; set; }
|
||||
|
||||
bool NoConsole { get; set; }
|
||||
IUserType UserType { get; }
|
||||
string Permissions { get; set; }
|
||||
string DefaultPermissions { get; set; }
|
||||
}
|
||||
|
||||
internal interface IUserProfile : IProfile
|
||||
{
|
||||
IEnumerable<string> AllowedSections { get; }
|
||||
void RemoveAllowedSection(string sectionAlias);
|
||||
void AddAllowedSection(string sectionAlias);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
@@ -8,7 +10,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
internal class Profile : IProfile
|
||||
internal class Profile : TracksChangesEntityBase, IProfile, IRememberBeingDirty
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Profile"/> class.
|
||||
@@ -25,11 +27,47 @@ namespace Umbraco.Core.Models.Membership
|
||||
Name = name;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public object Id { get; set; }
|
||||
private object _id;
|
||||
private string _name;
|
||||
private Type _userTypeKey;
|
||||
|
||||
private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<Profile, object>(x => x.Id);
|
||||
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<Profile, string>(x => x.Name);
|
||||
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<Profile, Type>(x => x.ProviderUserKeyType);
|
||||
|
||||
[DataMember]
|
||||
public string Name { get; set; }
|
||||
public object Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_id = value;
|
||||
return _id;
|
||||
}, _id, IdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_name = value;
|
||||
return _name;
|
||||
}, _name, NameSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public virtual object ProviderUserKey
|
||||
@@ -45,7 +83,21 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// The type of the provider user key.
|
||||
/// </value>
|
||||
[IgnoreDataMember]
|
||||
internal Type ProviderUserKeyType { get; private set; }
|
||||
internal Type ProviderUserKeyType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _userTypeKey;
|
||||
}
|
||||
private set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_userTypeKey = value;
|
||||
return _userTypeKey;
|
||||
}, _userTypeKey, UserTypeKeySelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the type of the provider user key.
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
public User(IUserType userType)
|
||||
{
|
||||
Groups = new List<object> {userType};
|
||||
Groups = new List<object> { userType };
|
||||
}
|
||||
|
||||
#region Implementation of IEntity
|
||||
@@ -91,7 +91,8 @@ namespace Umbraco.Core.Models.Membership
|
||||
[DataMember]
|
||||
public string Language { get; set; }
|
||||
[DataMember]
|
||||
public string Permissions { get; set; }
|
||||
public string DefaultPermissions { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public bool DefaultToLiveEditing { get; set; }
|
||||
[DataMember]
|
||||
@@ -100,8 +101,8 @@ namespace Umbraco.Core.Models.Membership
|
||||
[IgnoreDataMember]
|
||||
public IUserType UserType
|
||||
{
|
||||
get
|
||||
{
|
||||
get
|
||||
{
|
||||
var type = Groups.FirstOrDefault();
|
||||
return type as IUserType;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
@@ -14,14 +17,29 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
internal class UserProfile : Profile
|
||||
internal class UserProfile : Profile, IUserProfile
|
||||
{
|
||||
public UserProfile()
|
||||
{
|
||||
SessionTimeout = 60;
|
||||
Applications = Enumerable.Empty<string>();
|
||||
_sectionCollection = new ObservableCollection<string>();
|
||||
_addedSections = new List<string>();
|
||||
_removedSections = new List<string>();
|
||||
_sectionCollection.CollectionChanged += SectionCollectionChanged;
|
||||
}
|
||||
|
||||
private readonly List<string> _addedSections;
|
||||
private readonly List<string> _removedSections;
|
||||
private readonly ObservableCollection<string> _sectionCollection;
|
||||
private int _sessionTimeout;
|
||||
private int _startContentId;
|
||||
private int _startMediaId;
|
||||
|
||||
private static readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo<UserProfile, int>(x => x.SessionTimeout);
|
||||
private static readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<UserProfile, int>(x => x.StartContentId);
|
||||
private static readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<UserProfile, int>(x => x.StartMediaId);
|
||||
private static readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<UserProfile, IEnumerable<string>>(x => x.AllowedSections);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the session timeout.
|
||||
/// </summary>
|
||||
@@ -29,7 +47,21 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// The session timeout.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int SessionTimeout { get; set; }
|
||||
public int SessionTimeout
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sessionTimeout;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_sessionTimeout = value;
|
||||
return _sessionTimeout;
|
||||
}, _sessionTimeout, SessionTimeoutSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start content id.
|
||||
@@ -38,7 +70,21 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// The start content id.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int StartContentId { get; set; }
|
||||
public int StartContentId
|
||||
{
|
||||
get
|
||||
{
|
||||
return _startContentId;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_startContentId = value;
|
||||
return _startContentId;
|
||||
}, _startContentId, StartContentIdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start media id.
|
||||
@@ -47,15 +93,96 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// The start media id.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int StartMediaId { get; set; }
|
||||
public int StartMediaId
|
||||
{
|
||||
get
|
||||
{
|
||||
return _startMediaId;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_startMediaId = value;
|
||||
return _startMediaId;
|
||||
}, _startMediaId, StartMediaIdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllowedSections
|
||||
{
|
||||
get { return _sectionCollection; }
|
||||
}
|
||||
|
||||
public void RemoveAllowedSection(string sectionAlias)
|
||||
{
|
||||
_sectionCollection.Remove(sectionAlias);
|
||||
}
|
||||
|
||||
public void AddAllowedSection(string sectionAlias)
|
||||
{
|
||||
if (!_sectionCollection.Contains(sectionAlias))
|
||||
{
|
||||
_sectionCollection.Add(sectionAlias);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the applications.
|
||||
/// Whenever resetting occurs, clear the remembered add/removed collections, even if
|
||||
/// rememberPreviouslyChangedProperties is true, the AllowedSections property will still
|
||||
/// be flagged as dirty.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The applications.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public IEnumerable<string> Applications { get; set; }
|
||||
/// <param name="rememberPreviouslyChangedProperties"></param>
|
||||
internal override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
|
||||
{
|
||||
_addedSections.Clear();
|
||||
_removedSections.Clear();
|
||||
base.ResetDirtyProperties(rememberPreviouslyChangedProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to check if we need to add a section in the repository to the db
|
||||
/// </summary>
|
||||
internal IEnumerable<string> AddedSections
|
||||
{
|
||||
get { return _addedSections; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to check if we need to remove a section in the repository to the db
|
||||
/// </summary>
|
||||
internal IEnumerable<string> RemovedSections
|
||||
{
|
||||
get { return _removedSections; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the collection changed event in order for us to flag the AllowedSections property as changed
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void SectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(AllowedSectionsSelector);
|
||||
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
//remove from the removed/added sections (since people could add/remove all they want in one request)
|
||||
_removedSections.RemoveAll(s => s == e.NewItems.Cast<string>().First());
|
||||
_addedSections.RemoveAll(s => s == e.NewItems.Cast<string>().First());
|
||||
|
||||
//add to the added sections
|
||||
_addedSections.Add(e.NewItems.Cast<string>().First());
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
//remove from the removed/added sections (since people could add/remove all they want in one request)
|
||||
_removedSections.RemoveAll(s => s == e.OldItems.Cast<string>().First());
|
||||
_addedSections.RemoveAll(s => s == e.OldItems.Cast<string>().First());
|
||||
|
||||
//add to the added sections
|
||||
_removedSections.Add(e.OldItems.Cast<string>().First());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,15 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Services;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -28,8 +36,13 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
//This seems to fail during testing
|
||||
xmlNode.AppendChild(property.PropertyType.DataType(property.Id).Data.ToXMl(xd));
|
||||
|
||||
//SD: With the new null checks below, this shouldn't fail anymore.
|
||||
var dt = property.PropertyType.DataType(property.Id);
|
||||
if (dt != null && dt.Data != null)
|
||||
{
|
||||
xmlNode.AppendChild(dt.Data.ToXMl(xd));
|
||||
}
|
||||
|
||||
var element = xmlNode.GetXElement();
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -97,6 +97,14 @@ namespace Umbraco.Core.Models
|
||||
return this.Any(x => x.Name == groupName);
|
||||
}
|
||||
|
||||
public void RemoveItem(string propertyGroupName)
|
||||
{
|
||||
var key = IndexOfKey(propertyGroupName);
|
||||
//Only removes an item if the key was found
|
||||
if (key != -1)
|
||||
RemoveItem(key);
|
||||
}
|
||||
|
||||
public int IndexOfKey(string key)
|
||||
{
|
||||
for (var i = 0; i < this.Count; i++)
|
||||
|
||||
@@ -20,6 +20,10 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
Mandate.ParameterNotNull(propertyType, "propertyType");
|
||||
var dataType = ApplicationContext.Current.Services.DataTypeService.GetDataTypeById(propertyType.DataTypeId);
|
||||
if (dataType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
dataType.DataTypeDefinitionId = propertyType.DataTypeDefinitionId;
|
||||
dataType.Data.PropertyId = propertyId;
|
||||
return dataType;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Core.Persistence;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
|
||||
namespace Umbraco.Core.Models.Rdbms
|
||||
@@ -59,5 +60,8 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
[Column("defaultToLiveEditing")]
|
||||
[Constraint(Default = "0")]
|
||||
public bool DefaultToLiveEditing { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public List<User2AppDto> User2AppDtos { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ namespace Umbraco.Core.Models
|
||||
private int _level;
|
||||
private int _sortOrder;
|
||||
private int _parentId;
|
||||
private string _nodePath;
|
||||
private int _masterTemplateId;
|
||||
private string _masterTemplateAlias;
|
||||
|
||||
@@ -28,7 +27,6 @@ namespace Umbraco.Core.Models
|
||||
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<Template, int>(x => x.Level);
|
||||
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<Template, int>(x => x.SortOrder);
|
||||
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<Template, int>(x => x.ParentId);
|
||||
private static readonly PropertyInfo NodePathSelector = ExpressionHelper.GetPropertyInfo<Template, string>(x => x.NodePath);
|
||||
//private static readonly PropertyInfo MasterTemplateIdSelector = ExpressionHelper.GetPropertyInfo<Template, int>(x => x.MasterTemplateId);
|
||||
private static readonly PropertyInfo MasterTemplateAliasSelector = ExpressionHelper.GetPropertyInfo<Template, string>(x => x.MasterTemplateAlias);
|
||||
|
||||
@@ -104,21 +102,7 @@ namespace Umbraco.Core.Models
|
||||
}, _parentId, ParentIdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
internal string NodePath
|
||||
{
|
||||
get { return _nodePath; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_nodePath = value;
|
||||
return _nodePath;
|
||||
}, _nodePath, NodePathSelector);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[DataMember]
|
||||
internal Lazy<int> MasterTemplateId { get; set; }
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
@@ -21,7 +22,6 @@ namespace Umbraco.Core.Models
|
||||
private bool _isDraft;
|
||||
private bool _hasPendingChanges;
|
||||
private string _contentTypeAlias;
|
||||
private string _umbracoFile;
|
||||
private Guid _nodeObjectTypeId;
|
||||
|
||||
private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<UmbracoEntity, int>(x => x.CreatorId);
|
||||
@@ -38,7 +38,6 @@ namespace Umbraco.Core.Models
|
||||
private static readonly PropertyInfo ContentTypeAliasSelector = ExpressionHelper.GetPropertyInfo<UmbracoEntity, string>(x => x.ContentTypeAlias);
|
||||
private static readonly PropertyInfo ContentTypeIconSelector = ExpressionHelper.GetPropertyInfo<UmbracoEntity, string>(x => x.ContentTypeIcon);
|
||||
private static readonly PropertyInfo ContentTypeThumbnailSelector = ExpressionHelper.GetPropertyInfo<UmbracoEntity, string>(x => x.ContentTypeThumbnail);
|
||||
private static readonly PropertyInfo UmbracoFileSelector = ExpressionHelper.GetPropertyInfo<UmbracoEntity, string>(x => x.UmbracoFile);
|
||||
private static readonly PropertyInfo NodeObjectTypeIdSelector = ExpressionHelper.GetPropertyInfo<UmbracoEntity, Guid>(x => x.NodeObjectTypeId);
|
||||
private string _contentTypeIcon;
|
||||
private string _contentTypeThumbnail;
|
||||
@@ -234,19 +233,6 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
public string UmbracoFile
|
||||
{
|
||||
get { return _umbracoFile; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_umbracoFile = value;
|
||||
return _umbracoFile;
|
||||
}, _umbracoFile, UmbracoFileSelector);
|
||||
}
|
||||
}
|
||||
|
||||
public Guid NodeObjectTypeId
|
||||
{
|
||||
get { return _nodeObjectTypeId; }
|
||||
@@ -259,5 +245,13 @@ namespace Umbraco.Core.Models
|
||||
}, _nodeObjectTypeId, NodeObjectTypeIdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
public IList<UmbracoProperty> UmbracoProperties { get; set; }
|
||||
|
||||
internal class UmbracoProperty
|
||||
{
|
||||
public Guid DataTypeControlId { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Caching;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Caching
|
||||
@@ -11,6 +13,23 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
/// <summary>
|
||||
/// The Runtime Cache provider looks up objects in the Runtime cache for fast retrival
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// If a web session is detected then the HttpRuntime.Cache will be used for the runtime cache, otherwise a custom
|
||||
/// MemoryCache instance will be used. It is important to use the HttpRuntime.Cache when a web session is detected so
|
||||
/// that the memory management of cache in IIS can be handled appopriately.
|
||||
///
|
||||
/// When a web sessions is detected we will pre-fix all HttpRuntime.Cache entries so that when we clear it we are only
|
||||
/// clearing items that have been inserted by this provider.
|
||||
///
|
||||
/// NOTE: These changes are all temporary until we finalize the ApplicationCache implementation which will support static cache, runtime cache
|
||||
/// and request based cache which will all live in one central location so it is easily managed.
|
||||
///
|
||||
/// Also note that we don't always keep checking if HttpContext.Current == null and instead check for _memoryCache != null. This is because
|
||||
/// when there are async requests being made even in the context of a web request, the HttpContext.Current will be null but the HttpRuntime.Cache will
|
||||
/// always be available.
|
||||
///
|
||||
/// </remarks>
|
||||
internal sealed class RuntimeCacheProvider : IRepositoryCacheProvider
|
||||
{
|
||||
#region Singleton
|
||||
@@ -21,19 +40,25 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
|
||||
private RuntimeCacheProvider()
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
{
|
||||
_memoryCache = new MemoryCache("in-memory");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
//TODO Save this in cache as well, so its not limited to a single server usage
|
||||
private readonly ConcurrentHashSet<string> _keyTracker = new ConcurrentHashSet<string>();
|
||||
private ObjectCache _memoryCache = new MemoryCache("in-memory");
|
||||
private ObjectCache _memoryCache;
|
||||
private static readonly ReaderWriterLockSlim ClearLock = new ReaderWriterLockSlim();
|
||||
|
||||
public IEntity GetById(Type type, Guid id)
|
||||
{
|
||||
var key = GetCompositeId(type, id);
|
||||
var item = _memoryCache.Get(key);
|
||||
var item = _memoryCache != null
|
||||
? _memoryCache.Get(key)
|
||||
: HttpRuntime.Cache.Get(key);
|
||||
return item as IEntity;
|
||||
}
|
||||
|
||||
@@ -41,7 +66,11 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
{
|
||||
foreach (var guid in ids)
|
||||
{
|
||||
yield return _memoryCache.Get(GetCompositeId(type, guid)) as IEntity;
|
||||
var item = _memoryCache != null
|
||||
? _memoryCache.Get(GetCompositeId(type, guid))
|
||||
: HttpRuntime.Cache.Get(GetCompositeId(type, guid));
|
||||
|
||||
yield return item as IEntity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +78,13 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
{
|
||||
foreach (var key in _keyTracker)
|
||||
{
|
||||
if (key.StartsWith(type.Name))
|
||||
if (key.StartsWith(string.Format("{0}{1}-", CacheItemPrefix, type.Name)))
|
||||
{
|
||||
yield return _memoryCache.Get(key) as IEntity;
|
||||
var item = _memoryCache != null
|
||||
? _memoryCache.Get(key)
|
||||
: HttpRuntime.Cache.Get(key);
|
||||
|
||||
yield return item as IEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,21 +92,34 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
public void Save(Type type, IEntity entity)
|
||||
{
|
||||
var key = GetCompositeId(type, entity.Id);
|
||||
var exists = _memoryCache.GetCacheItem(key) != null;
|
||||
|
||||
_keyTracker.TryAdd(key);
|
||||
if (exists)
|
||||
|
||||
//NOTE: Before we were checking if it already exists but the MemoryCache.Set handles this implicitly and does
|
||||
// an add or update, same goes for HttpRuntime.Cache.Insert.
|
||||
|
||||
if (_memoryCache != null)
|
||||
{
|
||||
_memoryCache.Set(key, entity, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
|
||||
return;
|
||||
}
|
||||
|
||||
_memoryCache.Add(key, entity, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
|
||||
else
|
||||
{
|
||||
HttpRuntime.Cache.Insert(key, entity, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete(Type type, IEntity entity)
|
||||
{
|
||||
var key = GetCompositeId(type, entity.Id);
|
||||
_memoryCache.Remove(key);
|
||||
if (_memoryCache != null)
|
||||
{
|
||||
_memoryCache.Remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpRuntime.Cache.Remove(key);
|
||||
}
|
||||
|
||||
_keyTracker.Remove(key);
|
||||
}
|
||||
|
||||
@@ -88,14 +134,21 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
var keys = new string[_keyTracker.Count];
|
||||
_keyTracker.CopyTo(keys, 0);
|
||||
var keysToRemove = new List<string>();
|
||||
foreach (var key in keys.Where(x => x.StartsWith(string.Format("{0}-", type.Name))))
|
||||
foreach (var key in keys.Where(x => x.StartsWith(string.Format("{0}{1}-", CacheItemPrefix, type.Name))))
|
||||
{
|
||||
_keyTracker.Remove(key);
|
||||
keysToRemove.Add(key);
|
||||
}
|
||||
foreach (var key in keysToRemove)
|
||||
{
|
||||
_memoryCache.Remove(key);
|
||||
if (_memoryCache != null)
|
||||
{
|
||||
_memoryCache.Remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpRuntime.Cache.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,19 +158,40 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
using (new WriteLock(ClearLock))
|
||||
{
|
||||
_keyTracker.Clear();
|
||||
_memoryCache.DisposeIfDisposable();
|
||||
_memoryCache = new MemoryCache("in-memory");
|
||||
|
||||
if (_memoryCache != null)
|
||||
{
|
||||
_memoryCache.DisposeIfDisposable();
|
||||
_memoryCache = new MemoryCache("in-memory");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (DictionaryEntry c in HttpRuntime.Cache)
|
||||
{
|
||||
if (c.Key is string && ((string)c.Key).InvariantStartsWith(CacheItemPrefix))
|
||||
{
|
||||
if (HttpRuntime.Cache[(string)c.Key] == null) return;
|
||||
HttpRuntime.Cache.Remove((string)c.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We prefix all cache keys with this so that we know which ones this class has created when
|
||||
/// using the HttpRuntime cache so that when we clear it we don't clear other entries we didn't create.
|
||||
/// </summary>
|
||||
private const string CacheItemPrefix = "umbrtmche_";
|
||||
|
||||
private string GetCompositeId(Type type, Guid id)
|
||||
{
|
||||
return string.Format("{0}-{1}", type.Name, id.ToString());
|
||||
return string.Format("{0}{1}-{2}", CacheItemPrefix, type.Name, id.ToString());
|
||||
}
|
||||
|
||||
private string GetCompositeId(Type type, int id)
|
||||
{
|
||||
return string.Format("{0}-{1}", type.Name, id.ToGuid());
|
||||
return string.Format("{0}{1}-{2}", CacheItemPrefix, type.Name, id.ToGuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,17 +67,18 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
if (property.HasIdentity)
|
||||
dto.Id = property.Id;
|
||||
|
||||
if (property.DataTypeDatabaseType == DataTypeDatabaseType.Integer && property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false)
|
||||
if (property.DataTypeDatabaseType == DataTypeDatabaseType.Integer)
|
||||
{
|
||||
if (property.Value is bool)
|
||||
if (property.Value is bool || property.PropertyType.DataTypeId == new Guid("38b352c1-e9f8-4fd8-9324-9a2eab06d97a"))
|
||||
{
|
||||
int val = Convert.ToInt32(property.Value);
|
||||
dto.Integer = val;
|
||||
dto.Integer = property.Value != null && string.IsNullOrEmpty(property.Value.ToString())
|
||||
? 0
|
||||
: Convert.ToInt32(property.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
int val;
|
||||
if (int.TryParse(property.Value.ToString(), out val))
|
||||
if ((property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false) && int.TryParse(property.Value.ToString(), out val))
|
||||
{
|
||||
dto.Integer = val;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
Level = dto.NodeDto.Level,
|
||||
ParentId = dto.NodeDto.ParentId,
|
||||
SortOrder = dto.NodeDto.SortOrder,
|
||||
NodePath = dto.NodeDto.Path
|
||||
Path = dto.NodeDto.Path
|
||||
};
|
||||
|
||||
if(dto.Master.HasValue)
|
||||
@@ -83,7 +83,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
|
||||
NodeObjectType = _nodeObjectTypeId,
|
||||
ParentId = entity.ParentId,
|
||||
Path = entity.NodePath,
|
||||
Path = entity.Path,
|
||||
SortOrder = entity.SortOrder,
|
||||
Text = entity.Name,
|
||||
Trashed = false,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
@@ -25,13 +26,26 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
ContentTypeAlias = dto.Alias ?? string.Empty,
|
||||
ContentTypeIcon = dto.Icon ?? string.Empty,
|
||||
ContentTypeThumbnail = dto.Thumbnail ?? string.Empty,
|
||||
UmbracoFile = dto.UmbracoFile ?? string.Empty
|
||||
UmbracoProperties = new List<UmbracoEntity.UmbracoProperty>()
|
||||
};
|
||||
|
||||
entity.IsPublished = dto.PublishedVersion != default(Guid) || (dto.NewestVersion != default(Guid) && dto.PublishedVersion == dto.NewestVersion);
|
||||
entity.IsDraft = dto.NewestVersion != default(Guid) && (dto.PublishedVersion == default(Guid) || dto.PublishedVersion != dto.NewestVersion);
|
||||
entity.HasPendingChanges = (dto.PublishedVersion != default(Guid) && dto.NewestVersion != default(Guid)) && dto.PublishedVersion != dto.NewestVersion;
|
||||
|
||||
if (dto.UmbracoPropertyDtos != null)
|
||||
{
|
||||
foreach (var propertyDto in dto.UmbracoPropertyDtos)
|
||||
{
|
||||
entity.UmbracoProperties.Add(new UmbracoEntity.UmbracoProperty
|
||||
{
|
||||
DataTypeControlId =
|
||||
propertyDto.DataTypeControlId,
|
||||
Value = propertyDto.UmbracoFile
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
@@ -16,8 +17,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
|
||||
public IUser BuildEntity(UserDto dto)
|
||||
{
|
||||
//TODO Add list of applications for user
|
||||
return new User(_userType)
|
||||
var user = new User(_userType)
|
||||
{
|
||||
Id = dto.Id,
|
||||
ProfileId = dto.Id,
|
||||
@@ -32,8 +32,19 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
Language = dto.UserLanguage,
|
||||
DefaultToLiveEditing = dto.DefaultToLiveEditing,
|
||||
NoConsole = dto.NoConsole,
|
||||
Permissions = dto.DefaultPermissions
|
||||
DefaultPermissions = dto.DefaultPermissions
|
||||
};
|
||||
|
||||
foreach (var app in dto.User2AppDtos)
|
||||
{
|
||||
user.AddAllowedSection(app.AppAlias);
|
||||
}
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
user.ResetDirtyProperties(false);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
public UserDto BuildDto(IUser entity)
|
||||
@@ -51,9 +62,24 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
UserLanguage = entity.Language,
|
||||
UserName = entity.Name,
|
||||
Type = short.Parse(entity.UserType.Id.ToString()),
|
||||
DefaultPermissions = entity.Permissions
|
||||
DefaultPermissions = entity.DefaultPermissions,
|
||||
User2AppDtos = new List<User2AppDto>()
|
||||
};
|
||||
|
||||
foreach (var app in entity.AllowedSections)
|
||||
{
|
||||
var appDto = new User2AppDto
|
||||
{
|
||||
AppAlias = app
|
||||
};
|
||||
if (entity.Id != null)
|
||||
{
|
||||
appDto.UserId = (int) entity.Id;
|
||||
}
|
||||
|
||||
dto.User2AppDtos.Add(appDto);
|
||||
}
|
||||
|
||||
if (entity.HasIdentity)
|
||||
dto.Id = entity.Id.SafeCast<int>();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
@@ -7,11 +8,24 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
public abstract class BaseMapper
|
||||
{
|
||||
|
||||
internal abstract ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache { get; }
|
||||
|
||||
internal abstract void BuildMap();
|
||||
|
||||
internal abstract string Map(string propertyName);
|
||||
internal string Map(string propertyName)
|
||||
{
|
||||
DtoMapModel dtoTypeProperty;
|
||||
return PropertyInfoCache.TryGetValue(propertyName, out dtoTypeProperty)
|
||||
? GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo)
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
internal abstract void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember);
|
||||
internal void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
internal DtoMapModel ResolveMapping<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(IContent))]
|
||||
public sealed class ContentMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -25,6 +25,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
if(PropertyInfoCache.IsEmpty)
|
||||
@@ -52,23 +57,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
//CacheMap<Content, DocumentDto>(src => src.Template, dto => dto.TemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(IContentType))]
|
||||
public sealed class ContentTypeMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -25,6 +25,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
if (PropertyInfoCache.IsEmpty)
|
||||
@@ -48,22 +53,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
}
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(IDataTypeDefinition))]
|
||||
public sealed class DataTypeDefinitionMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -25,6 +25,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<DataTypeDefinition, NodeDto>(src => src.Id, dto => dto.NodeId);
|
||||
@@ -42,22 +47,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(IDictionaryItem))]
|
||||
public sealed class DictionaryMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -25,6 +25,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<DictionaryItem, DictionaryDto>(src => src.Id, dto => dto.PrimaryKey);
|
||||
@@ -32,23 +37,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<DictionaryItem, DictionaryDto>(src => src.ItemKey, dto => dto.Key);
|
||||
CacheMap<DictionaryItem, DictionaryDto>(src => src.ParentId, dto => dto.Parent);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(IDictionaryTranslation))]
|
||||
public class DictionaryTranslationMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -25,6 +25,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<DictionaryTranslation, LanguageTextDto>(src => src.Id, dto => dto.PrimaryKey);
|
||||
@@ -33,22 +38,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<DictionaryTranslation, LanguageTextDto>(src => src.Value, dto => dto.Value);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(Language))]
|
||||
public sealed class LanguageMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -25,6 +25,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<Language, LanguageDto>(src => src.Id, dto => dto.Id);
|
||||
@@ -32,22 +37,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<Language, LanguageDto>(src => src.CultureName, dto => dto.CultureName);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(Umbraco.Core.Models.Media))]
|
||||
public sealed class MediaMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -25,6 +25,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
if (PropertyInfoCache.IsEmpty)
|
||||
@@ -45,22 +50,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
}
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(MediaType))]
|
||||
public sealed class MediaTypeMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -25,6 +25,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
if (PropertyInfoCache.IsEmpty)
|
||||
@@ -48,22 +53,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
}
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(PropertyGroup))]
|
||||
public sealed class PropertyGroupMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -24,6 +24,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<PropertyGroup, PropertyTypeGroupDto>(src => src.Id, dto => dto.Id);
|
||||
@@ -32,22 +37,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<PropertyGroup, PropertyTypeGroupDto>(src => src.Name, dto => dto.Text);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(Property))]
|
||||
public sealed class PropertyMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -20,6 +20,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<Property, PropertyDataDto>(src => src.Id, dto => dto.Id);
|
||||
@@ -27,22 +32,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<Property, PropertyDataDto>(src => src.PropertyTypeId, dto => dto.PropertyTypeId);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(PropertyType))]
|
||||
public sealed class PropertyTypeMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -24,6 +24,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
if(PropertyInfoCache.IsEmpty)
|
||||
@@ -42,22 +47,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
}
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(Relation))]
|
||||
public sealed class RelationMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -24,6 +24,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<Relation, RelationDto>(src => src.Id, dto => dto.Id);
|
||||
@@ -33,23 +38,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<Relation, RelationDto>(src => src.ParentId, dto => dto.ParentId);
|
||||
CacheMap<Relation, RelationDto>(src => src.RelationTypeId, dto => dto.RelationType);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(RelationType))]
|
||||
public sealed class RelationTypeMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -24,6 +24,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<RelationType, RelationTypeDto>(src => src.Id, dto => dto.Id);
|
||||
@@ -33,23 +38,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<RelationType, RelationTypeDto>(src => src.Name, dto => dto.Name);
|
||||
CacheMap<RelationType, RelationTypeDto>(src => src.ParentObjectType, dto => dto.ParentObjectType);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(ServerRegistration))]
|
||||
public sealed class ServerRegistrationMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -20,6 +20,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.Id, dto => dto.Id);
|
||||
@@ -30,22 +35,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<ServerRegistration, ServerRegistrationDto>(src => src.ComputerName, dto => dto.ComputerName);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof (IUmbracoEntity))]
|
||||
public sealed class UmbracoEntityMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache =
|
||||
new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -21,6 +20,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<IUmbracoEntity, NodeDto>(src => src.Id, dto => dto.NodeId);
|
||||
@@ -34,24 +38,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<IUmbracoEntity, NodeDto>(src => src.Key, dto => dto.UniqueId);
|
||||
CacheMap<IUmbracoEntity, NodeDto>(src => src.CreatorId, dto => dto.UserId);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember,
|
||||
Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(User))]
|
||||
public sealed class UserMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -21,6 +21,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<User, UserDto>(src => src.Id, dto => dto.Id);
|
||||
@@ -28,7 +33,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<User, UserDto>(src => src.Username, dto => dto.Login);
|
||||
CacheMap<User, UserDto>(src => src.Password, dto => dto.Password);
|
||||
CacheMap<User, UserDto>(src => src.Name, dto => dto.UserName);
|
||||
CacheMap<User, UserDto>(src => src.Permissions, dto => dto.DefaultPermissions);
|
||||
CacheMap<User, UserDto>(src => src.DefaultPermissions, dto => dto.DefaultPermissions);
|
||||
CacheMap<User, UserDto>(src => src.StartMediaId, dto => dto.MediaStartId);
|
||||
CacheMap<User, UserDto>(src => src.StartContentId, dto => dto.ContentStartId);
|
||||
CacheMap<User, UserDto>(src => src.DefaultToLiveEditing, dto => dto.DefaultToLiveEditing);
|
||||
@@ -38,22 +43,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<User, UserDto>(src => src.Language, dto => dto.UserLanguage);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
[MapperFor(typeof(UserType))]
|
||||
public sealed class UserTypeMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
@@ -25,6 +25,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<UserType, UserTypeDto>(src => src.Id, dto => dto.Id);
|
||||
@@ -33,21 +38,6 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<UserType, UserTypeDto>(src => src.Permissions, dto => dto.DefaultPermissions);
|
||||
}
|
||||
|
||||
internal override string Map(string propertyName)
|
||||
{
|
||||
if (!PropertyInfoCache.ContainsKey(propertyName))
|
||||
return string.Empty;
|
||||
|
||||
var dtoTypeProperty = PropertyInfoCache[propertyName];
|
||||
|
||||
return base.GetColumnName(dtoTypeProperty.Type, dtoTypeProperty.PropertyInfo);
|
||||
}
|
||||
|
||||
internal override void CacheMap<TSource, TDestination>(Expression<Func<TSource, object>> sourceMember, Expression<Func<TDestination, object>> destinationMember)
|
||||
{
|
||||
var property = base.ResolveMapping(sourceMember, destinationMember);
|
||||
PropertyInfoCache.AddOrUpdate(property.SourcePropertyName, property, (x, y) => property);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
|
||||
// Add a parameter to a DB command
|
||||
void AddParam(IDbCommand cmd, object item, string ParameterPrefix)
|
||||
internal void AddParam(IDbCommand cmd, object item, string ParameterPrefix)
|
||||
{
|
||||
// Convert value to from poco type to db type
|
||||
if (Database.Mapper != null && item!=null)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
@@ -28,6 +30,80 @@ namespace Umbraco.Core.Persistence
|
||||
CreateTable(db, overwrite, tableType);
|
||||
}
|
||||
|
||||
public static void BulkInsertRecords<T>(this Database db, IEnumerable<T> collection)
|
||||
{
|
||||
using (var tr = db.GetTransaction())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider is SqlCeSyntaxProvider)
|
||||
{
|
||||
//SqlCe doesn't support bulk insert statements!
|
||||
|
||||
foreach (var poco in collection)
|
||||
{
|
||||
db.Insert(poco);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
string sql;
|
||||
using (var cmd = db.GenerateBulkInsertCommand(collection, db.Connection, out sql))
|
||||
{
|
||||
cmd.CommandText = sql;
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
tr.Complete();
|
||||
}
|
||||
catch
|
||||
{
|
||||
tr.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static IDbCommand GenerateBulkInsertCommand<T>(this Database db, IEnumerable<T> collection, IDbConnection connection, out string sql)
|
||||
{
|
||||
var pd = Database.PocoData.ForType(typeof(T));
|
||||
var tableName = db.EscapeTableName(pd.TableInfo.TableName);
|
||||
|
||||
//get all columns but not the primary key if it is auto-incremental
|
||||
var cols = string.Join(", ", (
|
||||
from c in pd.Columns
|
||||
where
|
||||
//don't return ResultColumns
|
||||
!c.Value.ResultColumn
|
||||
//if the table is auto-incremental, don't return the primary key
|
||||
&& (pd.TableInfo.AutoIncrement && c.Key != pd.TableInfo.PrimaryKey)
|
||||
select tableName + "." + db.EscapeSqlIdentifier(c.Key))
|
||||
.ToArray());
|
||||
|
||||
var cmd = db.CreateCommand(connection, "");
|
||||
|
||||
var pocoValues = new List<string>();
|
||||
var index = 0;
|
||||
foreach (var poco in collection)
|
||||
{
|
||||
var values = new List<string>();
|
||||
foreach (var i in pd.Columns)
|
||||
{
|
||||
if (pd.TableInfo.AutoIncrement && i.Key == pd.TableInfo.PrimaryKey)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
values.Add(string.Format("{0}{1}", "@", index++));
|
||||
db.AddParam(cmd, i.Value.GetValue(poco), "@");
|
||||
}
|
||||
pocoValues.Add("(" + string.Join(",", values.ToArray()) + ")");
|
||||
}
|
||||
sql = string.Format("INSERT INTO {0} ({1}) VALUES {2}", tableName, cols, string.Join(", ", pocoValues));
|
||||
return cmd;
|
||||
}
|
||||
|
||||
public static void CreateTable(this Database db, bool overwrite, Type modelType)
|
||||
{
|
||||
var tableDefinition = DefinitionFactory.GetTableDefinition(modelType);
|
||||
@@ -67,7 +143,7 @@ namespace Umbraco.Core.Persistence
|
||||
//Turn on identity insert if db provider is not mysql
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider.SupportsIdentityInsert() && tableDefinition.Columns.Any(x => x.IsIdentity))
|
||||
db.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName))));
|
||||
|
||||
|
||||
//Call the NewTable-event to trigger the insert of base/default data
|
||||
NewTable(tableName, db, e);
|
||||
|
||||
@@ -106,7 +182,7 @@ namespace Umbraco.Core.Persistence
|
||||
public static void DropTable<T>(this Database db)
|
||||
where T : new()
|
||||
{
|
||||
Type type = typeof (T);
|
||||
Type type = typeof(T);
|
||||
var tableNameAttribute = type.FirstAttribute<TableNameAttribute>();
|
||||
if (tableNameAttribute == null)
|
||||
throw new Exception(
|
||||
@@ -184,5 +260,5 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
}
|
||||
|
||||
internal class TableCreationEventArgs : System.ComponentModel.CancelEventArgs{}
|
||||
internal class TableCreationEventArgs : System.ComponentModel.CancelEventArgs { }
|
||||
}
|
||||
@@ -455,8 +455,11 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
if (fieldType == typeof(decimal))
|
||||
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(DateTime))
|
||||
return "'" + EscapeParam(((DateTime)value).ToString(CultureInfo.InvariantCulture)) + "'";
|
||||
if (fieldType == typeof (DateTime))
|
||||
{
|
||||
return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'";
|
||||
}
|
||||
|
||||
|
||||
if (fieldType == typeof(bool))
|
||||
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
|
||||
|
||||
@@ -465,8 +465,11 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
if (fieldType == typeof(decimal))
|
||||
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if(fieldType == typeof(DateTime))
|
||||
return "'" + EscapeParam(((DateTime)value).ToString(CultureInfo.InvariantCulture)) + "'";
|
||||
if (fieldType == typeof (DateTime))
|
||||
{
|
||||
return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'";
|
||||
}
|
||||
|
||||
|
||||
if (fieldType == typeof(bool))
|
||||
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Relators
|
||||
{
|
||||
internal class UserSectionRelator
|
||||
{
|
||||
internal UserDto Current;
|
||||
|
||||
internal UserDto Map(UserDto a, User2AppDto p)
|
||||
{
|
||||
// Terminating call. Since we can return null from this function
|
||||
// we need to be ready for PetaPoco to callback later with null
|
||||
// parameters
|
||||
if (a == null)
|
||||
return Current;
|
||||
|
||||
// Is this the same DictionaryItem as the current one we're processing
|
||||
if (Current != null && Current.Id == a.Id)
|
||||
{
|
||||
// Yes, just add this User2AppDto to the current item's collection
|
||||
Current.User2AppDtos.Add(p);
|
||||
|
||||
// Return null to indicate we're not done with this User yet
|
||||
return null;
|
||||
}
|
||||
|
||||
// This is a different User to the current one, or this is the
|
||||
// first time through and we don't have one yet
|
||||
|
||||
// Save the current User
|
||||
var prev = Current;
|
||||
|
||||
// Setup the new current User
|
||||
Current = a;
|
||||
Current.User2AppDtos = new List<User2AppDto>();
|
||||
//this can be null since we are doing a left join
|
||||
if (p.AppAlias != null)
|
||||
{
|
||||
Current.User2AppDtos.Add(p);
|
||||
}
|
||||
|
||||
// Return the now populated previous User (or null if first time through)
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_templateRepository = templateRepository;
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
|
||||
public ContentRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository)
|
||||
@@ -34,8 +36,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_templateRepository = templateRepository;
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
|
||||
public bool EnsureUniqueNaming { get; set; }
|
||||
|
||||
#region Overrides of RepositoryBase<IContent>
|
||||
|
||||
protected override IContent PerformGet(int id)
|
||||
@@ -180,6 +186,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
((Content)entity).AddingEntity();
|
||||
|
||||
//Ensure unique name on the same level
|
||||
entity.Name = EnsureUniqueNodeName(entity.ParentId, entity.Name);
|
||||
|
||||
var factory = new ContentFactory(NodeObjectTypeId, entity.Id);
|
||||
var dto = factory.BuildDto(entity);
|
||||
|
||||
@@ -197,7 +206,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture));
|
||||
nodeDto.SortOrder = sortOrder;
|
||||
var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto);
|
||||
|
||||
|
||||
//Update with new correct path
|
||||
nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId);
|
||||
Database.Update(nodeDto);
|
||||
@@ -208,6 +217,24 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
entity.SortOrder = sortOrder;
|
||||
entity.Level = level;
|
||||
|
||||
|
||||
//Assign the same permissions to it as the parent node
|
||||
// http://issues.umbraco.org/issue/U4-2161
|
||||
var parentPermissions = GetPermissionsForEntity(entity.ParentId).ToArray();
|
||||
//if there are parent permissions then assign them, otherwise leave null and permissions will become the
|
||||
// user's default permissions.
|
||||
if (parentPermissions.Any())
|
||||
{
|
||||
var userPermissions = parentPermissions.Select(
|
||||
permissionDto => new KeyValuePair<object, string>(
|
||||
permissionDto.UserId,
|
||||
permissionDto.Permission));
|
||||
AssignEntityPermissions(entity, userPermissions);
|
||||
//flag the entity's permissions changed flag so we can track those changes.
|
||||
//Currently only used for the cache refreshers to detect if we should refresh all user permissions cache.
|
||||
((Content) entity).PermissionsChanged = true;
|
||||
}
|
||||
|
||||
//Create the Content specific data - cmsContent
|
||||
var contentDto = dto.ContentVersionDto.ContentDto;
|
||||
contentDto.NodeId = nodeDto.NodeId;
|
||||
@@ -260,6 +287,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
entity.UpdateDate = DateTime.Now;
|
||||
}
|
||||
|
||||
//Ensure unique name on the same level
|
||||
entity.Name = EnsureUniqueNodeName(entity.ParentId, entity.Name, entity.Id);
|
||||
|
||||
//Look up parent to get and set the correct Path and update SortOrder if ParentId has changed
|
||||
if (((ICanBeDirty)entity).IsPropertyDirty("ParentId"))
|
||||
{
|
||||
@@ -271,6 +301,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType",
|
||||
new {ParentId = entity.ParentId, NodeObjectType = NodeObjectTypeId});
|
||||
entity.SortOrder = maxSortOrder + 1;
|
||||
|
||||
//Question: If we move a node, should we update permissions to inherit from the new parent if the parent has permissions assigned?
|
||||
// if we do that, then we'd need to propogate permissions all the way downward which might not be ideal for many people.
|
||||
// Gonna just leave it as is for now, and not re-propogate permissions.
|
||||
}
|
||||
|
||||
var factory = new ContentFactory(NodeObjectTypeId, entity.Id);
|
||||
@@ -489,5 +523,37 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
return new PropertyCollection(properties);
|
||||
}
|
||||
|
||||
private string EnsureUniqueNodeName(int parentId, string nodeName, int id = 0)
|
||||
{
|
||||
if (EnsureUniqueNaming == false)
|
||||
return nodeName;
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId && x.ParentId == parentId && x.Text.StartsWith(nodeName));
|
||||
|
||||
int uniqueNumber = 1;
|
||||
var currentName = nodeName;
|
||||
|
||||
var dtos = Database.Fetch<NodeDto>(sql);
|
||||
if (dtos.Any())
|
||||
{
|
||||
var results = dtos.OrderBy(x => x.Text, new SimilarNodeNameComparer());
|
||||
foreach (var dto in results)
|
||||
{
|
||||
if(id != 0 && id == dto.NodeId) continue;
|
||||
|
||||
if (dto.Text.ToLowerInvariant().Equals(currentName.ToLowerInvariant()))
|
||||
{
|
||||
currentName = nodeName + string.Format(" ({0})", uniqueNumber);
|
||||
uniqueNumber++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currentName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,7 +203,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.Where<NodeDto>(x => x.NodeObjectType == new Guid(Constants.ObjectTypes.Document))
|
||||
.Where<ContentDto>(x => x.ContentTypeId == entity.Id);
|
||||
|
||||
var contentDtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(sql);
|
||||
var contentDtos = Database.Fetch<ContentDto, NodeDto>(sql);
|
||||
//Loop through all tracked keys, which corresponds to the ContentTypes that has been removed from the composition
|
||||
foreach (var key in compositionBase.RemovedContentTypeKeyTracker)
|
||||
{
|
||||
@@ -321,7 +321,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
sql.Select("*")
|
||||
.From<ContentTypeAllowedContentTypeDto>()
|
||||
.LeftJoin<ContentTypeDto>()
|
||||
.On<ContentTypeAllowedContentTypeDto, ContentTypeDto>(left => left.Id, right => right.NodeId)
|
||||
.On<ContentTypeAllowedContentTypeDto, ContentTypeDto>(left => left.AllowedId, right => right.NodeId)
|
||||
.Where<ContentTypeAllowedContentTypeDto>(x => x.Id == id);
|
||||
|
||||
var allowedContentTypeDtos = Database.Fetch<ContentTypeAllowedContentTypeDto, ContentTypeDto>(sql);
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IUmbracoEntity Get(int id)
|
||||
{
|
||||
var sql = GetBaseWhere(GetBase, false, id);
|
||||
var sql = GetBaseWhere(GetBase, false, false, id);
|
||||
var nodeDto = _work.Database.FirstOrDefault<UmbracoEntityDto>(sql);
|
||||
if (nodeDto == null)
|
||||
return null;
|
||||
@@ -58,8 +58,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IUmbracoEntity Get(int id, Guid objectTypeId)
|
||||
{
|
||||
bool isContentOrMedia = objectTypeId == new Guid(Constants.ObjectTypes.Document) || objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetBaseWhere(GetBase, isContentOrMedia, objectTypeId, id).Append(GetGroupBy(isContentOrMedia));
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId, id).Append(GetGroupBy(isContent, isMedia));
|
||||
var nodeDto = _work.Database.FirstOrDefault<UmbracoEntityDto>(sql);
|
||||
if (nodeDto == null)
|
||||
return null;
|
||||
@@ -81,10 +82,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isContentOrMedia = objectTypeId == new Guid(Constants.ObjectTypes.Document) || objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetBaseWhere(GetBase, isContentOrMedia, objectTypeId).Append(GetGroupBy(isContentOrMedia));
|
||||
var dtos = _work.Database.Fetch<UmbracoEntityDto>(sql);
|
||||
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId).Append(GetGroupBy(isContent, isMedia));
|
||||
var dtos = isMedia
|
||||
? _work.Database.Fetch<UmbracoEntityDto, UmbracoPropertyDto, UmbracoEntityDto>(
|
||||
new UmbracoEntityRelator().Map, sql)
|
||||
: _work.Database.Fetch<UmbracoEntityDto>(sql);
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
foreach (var dto in dtos)
|
||||
@@ -97,9 +101,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query)
|
||||
{
|
||||
var sqlClause = GetBase(false);
|
||||
var sqlClause = GetBase(false, false);
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var sql = translator.Translate().Append(GetGroupBy(false));
|
||||
var sql = translator.Translate().Append(GetGroupBy(false, false));
|
||||
|
||||
var dtos = _work.Database.Fetch<UmbracoEntityDto>(sql);
|
||||
|
||||
@@ -111,12 +115,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query, Guid objectTypeId)
|
||||
{
|
||||
bool isContentOrMedia = objectTypeId == new Guid(Constants.ObjectTypes.Document) || objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sqlClause = GetBaseWhere(GetBase, isContentOrMedia, objectTypeId);
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId);
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var sql = translator.Translate().Append(GetGroupBy(isContentOrMedia));
|
||||
var sql = translator.Translate().Append(GetGroupBy(isContent, isMedia));
|
||||
|
||||
var dtos = _work.Database.Fetch<UmbracoEntityDto>(sql);
|
||||
var dtos = isMedia
|
||||
? _work.Database.Fetch<UmbracoEntityDto, UmbracoPropertyDto, UmbracoEntityDto>(
|
||||
new UmbracoEntityRelator().Map, sql)
|
||||
: _work.Database.Fetch<UmbracoEntityDto>(sql);
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
var list = dtos.Select(factory.BuildEntity).Cast<IUmbracoEntity>().ToList();
|
||||
@@ -128,7 +136,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
#region Sql Statements
|
||||
|
||||
protected virtual Sql GetBase(bool isContentOrMedia)
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia)
|
||||
{
|
||||
var columns = new List<object>
|
||||
{
|
||||
@@ -146,14 +154,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"COUNT(parent.parentID) as children"
|
||||
};
|
||||
|
||||
if (isContentOrMedia)
|
||||
if (isContent || isMedia)
|
||||
{
|
||||
columns.Add("published.versionId as publishedVerison");
|
||||
columns.Add("latest.versionId as newestVersion");
|
||||
columns.Add("contenttype.alias");
|
||||
columns.Add("contenttype.icon");
|
||||
columns.Add("contenttype.thumbnail");
|
||||
}
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
columns.Add("property.dataNvarchar as umbracoFile");
|
||||
columns.Add("property.controlId");
|
||||
}
|
||||
|
||||
var sql = new Sql()
|
||||
@@ -162,7 +175,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.LeftJoin("umbracoNode parent").On("parent.parentID = umbracoNode.id");
|
||||
|
||||
|
||||
if (isContentOrMedia)
|
||||
if (isContent || isMedia)
|
||||
{
|
||||
sql.InnerJoin("cmsContent content").On("content.nodeId = umbracoNode.id")
|
||||
.LeftJoin("cmsContentType contenttype").On("contenttype.nodeId = content.contentType")
|
||||
@@ -171,40 +184,51 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On("umbracoNode.id = published.nodeId")
|
||||
.LeftJoin(
|
||||
"(SELECT nodeId, versionId FROM cmsDocument WHERE newest = 1 GROUP BY nodeId, versionId) as latest")
|
||||
.On("umbracoNode.id = latest.nodeId")
|
||||
.LeftJoin(
|
||||
"(SELECT contentNodeId, dataNvarchar FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid"+
|
||||
" INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId WHERE cmsDataType.controlId = '"+ Constants.PropertyEditors.UploadField +"') as property")
|
||||
.On("umbracoNode.id = latest.nodeId");
|
||||
}
|
||||
|
||||
/*if (isContent)
|
||||
{
|
||||
sql.LeftJoin(
|
||||
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid" +
|
||||
" INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId) as property")
|
||||
.On("umbracoNode.id = property.contentNodeId AND latest.versionId = property.versionId");
|
||||
}*/
|
||||
if (isMedia)
|
||||
{
|
||||
sql.LeftJoin(
|
||||
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid" +
|
||||
" INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId) as property")
|
||||
.On("umbracoNode.id = property.contentNodeId");
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, Sql> baseQuery, bool isContentOrMedia, Guid id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, Guid id)
|
||||
{
|
||||
var sql = baseQuery(isContentOrMedia)
|
||||
var sql = baseQuery(isContent, isMedia)
|
||||
.Where("umbracoNode.nodeObjectType = @NodeObjectType", new { NodeObjectType = id });
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, Sql> baseQuery, bool isContentOrMedia, int id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, int id)
|
||||
{
|
||||
var sql = baseQuery(isContentOrMedia)
|
||||
var sql = baseQuery(isContent, isMedia)
|
||||
.Where("umbracoNode.id = @Id", new { Id = id })
|
||||
.Append(GetGroupBy(isContentOrMedia));
|
||||
.Append(GetGroupBy(isContent, isMedia));
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, Sql> baseQuery, bool isContentOrMedia, Guid objectId, int id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, Guid objectId, int id)
|
||||
{
|
||||
var sql = baseQuery(isContentOrMedia)
|
||||
var sql = baseQuery(isContent, isMedia)
|
||||
.Where("umbracoNode.id = @Id AND umbracoNode.nodeObjectType = @NodeObjectType",
|
||||
new {Id = id, NodeObjectType = objectId});
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetGroupBy(bool isContentOrMedia)
|
||||
protected virtual Sql GetGroupBy(bool isContent, bool isMedia)
|
||||
{
|
||||
var columns = new List<object>
|
||||
{
|
||||
@@ -221,14 +245,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"umbracoNode.createDate"
|
||||
};
|
||||
|
||||
if (isContentOrMedia)
|
||||
if (isContent || isMedia)
|
||||
{
|
||||
columns.Add("published.versionId");
|
||||
columns.Add("latest.versionId");
|
||||
columns.Add("contenttype.alias");
|
||||
columns.Add("contenttype.icon");
|
||||
columns.Add("contenttype.thumbnail");
|
||||
}
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
columns.Add("property.dataNvarchar");
|
||||
columns.Add("property.controlId");
|
||||
}
|
||||
|
||||
var sql = new Sql()
|
||||
@@ -274,9 +303,57 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
[Column("thumbnail")]
|
||||
public string Thumbnail { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public List<UmbracoPropertyDto> UmbracoPropertyDtos { get; set; }
|
||||
}
|
||||
|
||||
[ExplicitColumns]
|
||||
internal class UmbracoPropertyDto
|
||||
{
|
||||
[Column("controlId")]
|
||||
public Guid DataTypeControlId { get; set; }
|
||||
|
||||
[Column("umbracoFile")]
|
||||
public string UmbracoFile { get; set; }
|
||||
}
|
||||
|
||||
internal class UmbracoEntityRelator
|
||||
{
|
||||
internal UmbracoEntityDto Current;
|
||||
|
||||
internal UmbracoEntityDto Map(UmbracoEntityDto a, UmbracoPropertyDto p)
|
||||
{
|
||||
// Terminating call. Since we can return null from this function
|
||||
// we need to be ready for PetaPoco to callback later with null
|
||||
// parameters
|
||||
if (a == null)
|
||||
return Current;
|
||||
|
||||
// Is this the same UmbracoEntityDto as the current one we're processing
|
||||
if (Current != null && Current.UniqueId == a.UniqueId)
|
||||
{
|
||||
// Yes, just add this UmbracoPropertyDto to the current UmbracoEntityDto's collection
|
||||
Current.UmbracoPropertyDtos.Add(p);
|
||||
|
||||
// Return null to indicate we're not done with this UmbracoEntityDto yet
|
||||
return null;
|
||||
}
|
||||
|
||||
// This is a different UmbracoEntityDto to the current one, or this is the
|
||||
// first time through and we don't have a Tab yet
|
||||
|
||||
// Save the current UmbracoEntityDto
|
||||
var prev = Current;
|
||||
|
||||
// Setup the new current UmbracoEntityDto
|
||||
Current = a;
|
||||
Current.UmbracoPropertyDtos = new List<UmbracoPropertyDto>();
|
||||
Current.UmbracoPropertyDtos.Add(p);
|
||||
|
||||
// Return the now populated previous UmbracoEntityDto (or null if first time through)
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">Type of <see cref="IAggregateRoot"/> entity for which the repository is used</typeparam>
|
||||
/// <typeparam name="TId">Type of the Id used for this entity</typeparam>
|
||||
public interface IRepositoryQueryable<TId, TEntity> : IRepository<TId, TEntity>
|
||||
where TEntity : IAggregateRoot
|
||||
public interface IRepositoryQueryable<in TId, TEntity> : IRepository<TId, TEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all entities of the specified type and query
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
internal interface IUserRepository : IRepositoryQueryable<int, IUser>
|
||||
{
|
||||
IProfile GetProfileById(int id);
|
||||
//IProfile GetProfileById(int id);
|
||||
//IProfile GetProfileByUserName(string username);
|
||||
//IUser GetUserByUserName(string username);
|
||||
|
||||
/// <summary>
|
||||
/// This is useful when an entire section is removed from config
|
||||
/// </summary>
|
||||
/// <param name="sectionAlias"></param>
|
||||
IEnumerable<IUser> GetUsersAssignedToSection(string sectionAlias);
|
||||
}
|
||||
}
|
||||
@@ -25,14 +25,20 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
: base(work)
|
||||
{
|
||||
_mediaTypeRepository = mediaTypeRepository;
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
|
||||
public MediaRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMediaTypeRepository mediaTypeRepository)
|
||||
: base(work, cache)
|
||||
{
|
||||
_mediaTypeRepository = mediaTypeRepository;
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
|
||||
public bool EnsureUniqueNaming { get; set; }
|
||||
|
||||
#region Overrides of RepositoryBase<int,IMedia>
|
||||
|
||||
protected override IMedia PerformGet(int id)
|
||||
@@ -182,6 +188,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
((Models.Media)entity).AddingEntity();
|
||||
|
||||
//Ensure unique name on the same level
|
||||
entity.Name = EnsureUniqueNodeName(entity.ParentId, entity.Name);
|
||||
|
||||
var factory = new MediaFactory(NodeObjectTypeId, entity.Id);
|
||||
var dto = factory.BuildDto(entity);
|
||||
|
||||
@@ -246,6 +255,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//Updates Modified date
|
||||
((Models.Media)entity).UpdatingEntity();
|
||||
|
||||
//Ensure unique name on the same level
|
||||
entity.Name = EnsureUniqueNodeName(entity.ParentId, entity.Name, entity.Id);
|
||||
|
||||
//Look up parent to get and set the correct Path and update SortOrder if ParentId has changed
|
||||
if (((ICanBeDirty)entity).IsPropertyDirty("ParentId"))
|
||||
{
|
||||
@@ -370,5 +382,37 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
return new PropertyCollection(properties);
|
||||
}
|
||||
|
||||
private string EnsureUniqueNodeName(int parentId, string nodeName, int id = 0)
|
||||
{
|
||||
if (EnsureUniqueNaming == false)
|
||||
return nodeName;
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId && x.ParentId == parentId && x.Text.StartsWith(nodeName));
|
||||
|
||||
int uniqueNumber = 1;
|
||||
var currentName = nodeName;
|
||||
|
||||
var dtos = Database.Fetch<NodeDto>(sql);
|
||||
if (dtos.Any())
|
||||
{
|
||||
var results = dtos.OrderBy(x => x.Text, new SimilarNodeNameComparer());
|
||||
foreach (var dto in results)
|
||||
{
|
||||
if (id != 0 && id == dto.NodeId) continue;
|
||||
|
||||
if (dto.Text.ToLowerInvariant().Equals(currentName.ToLowerInvariant()))
|
||||
{
|
||||
currentName = nodeName + string.Format(" ({0})", uniqueNumber);
|
||||
uniqueNumber++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currentName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// A repository that exposes functionality to modify assigned permissions to a node
|
||||
/// </summary>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
internal abstract class PermissionRepository<TId, TEntity> : PetaPocoRepositoryBase<TId, TEntity>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
protected PermissionRepository(IDatabaseUnitOfWork work)
|
||||
: base(work)
|
||||
{
|
||||
}
|
||||
|
||||
protected PermissionRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache)
|
||||
: base(work, cache)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal IEnumerable<User2NodePermissionDto> GetPermissionsForEntity(int entityId)
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
.From<User2NodePermissionDto>()
|
||||
.Where<User2NodePermissionDto>(dto => dto.NodeId == entityId);
|
||||
return Database.Fetch<User2NodePermissionDto>(sql);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns permissions to an entity for multiple users
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="permissions"></param>
|
||||
/// <param name="userIds"></param>
|
||||
protected internal void AssignEntityPermissions(TEntity entity, string permissions, IEnumerable<object> userIds)
|
||||
{
|
||||
var actions = userIds.Select(id => new User2NodePermissionDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
Permission = permissions,
|
||||
UserId = (int)id
|
||||
});
|
||||
|
||||
Database.BulkInsertRecords(actions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns permissions to an entity for multiple users/permission entries
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="userPermissions">
|
||||
/// A key/value pair list containing a userId and a permission to assign
|
||||
/// </param>
|
||||
protected internal void AssignEntityPermissions(TEntity entity, IEnumerable<KeyValuePair<object, string>> userPermissions)
|
||||
{
|
||||
var actions = userPermissions.Select(p => new User2NodePermissionDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
Permission = p.Value,
|
||||
UserId = (int)p.Key
|
||||
});
|
||||
|
||||
Database.BulkInsertRecords(actions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace permissions for an entity for multiple users
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="permissions"></param>
|
||||
/// <param name="userIds"></param>
|
||||
protected internal void ReplaceEntityPermissions(TEntity entity, string permissions, IEnumerable<object> userIds)
|
||||
{
|
||||
Database.Update<User2NodePermissionDto>(
|
||||
GenerateReplaceEntityPermissionsSql(entity.Id, permissions, userIds.ToArray()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An overload to replace entity permissions and all replace all descendant permissions
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="permissions"></param>
|
||||
/// <param name="getDescendantIds">
|
||||
/// A callback to get the descendant Ids of the current entity
|
||||
/// </param>
|
||||
/// <param name="userIds"></param>
|
||||
protected internal void ReplaceEntityPermissions(TEntity entity, string permissions, Func<IEntity, IEnumerable<int>> getDescendantIds, IEnumerable<object> userIds)
|
||||
{
|
||||
Database.Update<User2NodePermissionDto>(
|
||||
GenerateReplaceEntityPermissionsSql(
|
||||
new[] {entity.Id}.Concat(getDescendantIds(entity)).ToArray(),
|
||||
permissions,
|
||||
userIds.ToArray()));
|
||||
}
|
||||
|
||||
internal static string GenerateReplaceEntityPermissionsSql(int entityId, string permissions, object[] userIds)
|
||||
{
|
||||
return GenerateReplaceEntityPermissionsSql(new[] {entityId}, permissions, userIds);
|
||||
}
|
||||
|
||||
internal static string GenerateReplaceEntityPermissionsSql(int[] entityIds, string permissions, object[] userIds)
|
||||
{
|
||||
//create the "SET" clause of the update statement
|
||||
var sqlSet = string.Format("SET {0}={1}",
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("permission"),
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(permissions));
|
||||
|
||||
//build the nodeIds part of the where clause
|
||||
var sqlNodeWhere = BuildOrClause(entityIds, "nodeId");
|
||||
|
||||
//build up the userIds part of the where clause
|
||||
var userWhereBuilder = BuildOrClause(userIds, "userId");
|
||||
|
||||
var sqlWhere = new Sql();
|
||||
sqlWhere.Where(string.Format("{0} AND {1}", sqlNodeWhere, userWhereBuilder));
|
||||
|
||||
return string.Format("{0} {1}", sqlSet, sqlWhere.SQL);
|
||||
}
|
||||
|
||||
private static string BuildOrClause<T>(IEnumerable<T> ids, string colName)
|
||||
{
|
||||
var asArray = ids.ToArray();
|
||||
var userWhereBuilder = new StringBuilder();
|
||||
userWhereBuilder.Append("(");
|
||||
for (var index = 0; index < asArray.Length; index++)
|
||||
{
|
||||
var userId = asArray[index];
|
||||
userWhereBuilder.Append(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(colName));
|
||||
userWhereBuilder.Append("=");
|
||||
userWhereBuilder.Append(userId);
|
||||
if (index < asArray.Length - 1)
|
||||
{
|
||||
userWhereBuilder.Append(" OR ");
|
||||
}
|
||||
}
|
||||
userWhereBuilder.Append(")");
|
||||
return userWhereBuilder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
Entity asEntity = entity as Entity;
|
||||
TracksChangesEntityBase asEntity = entity as TracksChangesEntityBase;
|
||||
if (asEntity != null)
|
||||
{
|
||||
asEntity.ResetDirtyProperties(false);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Comparer that takes into account the duplicate index of a node name
|
||||
/// This is needed as a normal alphabetic sort would go Page (1), Page (10), Page (2) etc.
|
||||
/// </summary>
|
||||
internal class SimilarNodeNameComparer : IComparer<string>
|
||||
{
|
||||
public int Compare(string x, string y)
|
||||
{
|
||||
if (x.LastIndexOf(')') == x.Length - 1 && y.LastIndexOf(')') == y.Length - 1)
|
||||
{
|
||||
if (x.ToLower().Substring(0, x.LastIndexOf('(')) == y.ToLower().Substring(0, y.LastIndexOf('(')))
|
||||
{
|
||||
int xDuplicateIndex = ExtractDuplicateIndex(x);
|
||||
int yDuplicateIndex = ExtractDuplicateIndex(y);
|
||||
|
||||
if (xDuplicateIndex != 0 && yDuplicateIndex != 0)
|
||||
{
|
||||
return xDuplicateIndex.CompareTo(yDuplicateIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return String.Compare(x.ToLower(), y.ToLower(), StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private int ExtractDuplicateIndex(string text)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (text.LastIndexOf('(') != -1 && text.LastIndexOf('(') < text.Length - 2)
|
||||
{
|
||||
int startPos = text.LastIndexOf('(') + 1;
|
||||
int length = text.Length - 1 - startPos;
|
||||
|
||||
int.TryParse(text.Substring(startPos, length), out index);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Relators;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
@@ -13,17 +17,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <summary>
|
||||
/// Represents the UserRepository for doing CRUD operations for <see cref="IUser"/>
|
||||
/// </summary>
|
||||
internal class UserRepository : PetaPocoRepositoryBase<int, IUser>, IUserRepository
|
||||
internal class UserRepository : PermissionRepository<int, IUser>, IUserRepository
|
||||
{
|
||||
private readonly IUserTypeRepository _userTypeRepository;
|
||||
|
||||
public UserRepository(IDatabaseUnitOfWork work, IUserTypeRepository userTypeRepository)
|
||||
public UserRepository(IDatabaseUnitOfWork work, IUserTypeRepository userTypeRepository)
|
||||
: base(work)
|
||||
{
|
||||
_userTypeRepository = userTypeRepository;
|
||||
}
|
||||
|
||||
public UserRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IUserTypeRepository userTypeRepository)
|
||||
public UserRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IUserTypeRepository userTypeRepository)
|
||||
: base(work, cache)
|
||||
{
|
||||
_userTypeRepository = userTypeRepository;
|
||||
@@ -36,7 +40,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = GetBaseQuery(false);
|
||||
sql.Where(GetBaseWhereClause(), new { Id = id });
|
||||
|
||||
var dto = Database.FirstOrDefault<UserDto>(sql);
|
||||
var dto = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql).FirstOrDefault();
|
||||
|
||||
if (dto == null)
|
||||
return null;
|
||||
@@ -52,18 +56,20 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
if (ids.Any())
|
||||
{
|
||||
foreach (var id in ids)
|
||||
{
|
||||
yield return Get(id);
|
||||
}
|
||||
return PerformGetAllOnIds(ids);
|
||||
}
|
||||
else
|
||||
|
||||
var sql = GetBaseQuery(false);
|
||||
|
||||
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql));
|
||||
}
|
||||
|
||||
private IEnumerable<IUser> PerformGetAllOnIds(params int[] ids)
|
||||
{
|
||||
if (ids.Any() == false) yield break;
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var userDtos = Database.Fetch<UserDto>("WHERE id >= 0");
|
||||
foreach (var userDto in userDtos)
|
||||
{
|
||||
yield return Get(userDto.Id);
|
||||
}
|
||||
yield return Get(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +79,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var translator = new SqlTranslator<IUser>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
var dtos = Database.Fetch<UserDto>(sql);
|
||||
var dtos = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql);
|
||||
|
||||
foreach (var dto in dtos.DistinctBy(x => x.Id))
|
||||
{
|
||||
@@ -88,20 +94,41 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
protected override Sql GetBaseQuery(bool isCount)
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select(isCount ? "COUNT(*)" : "*")
|
||||
.From<UserDto>();
|
||||
if (isCount)
|
||||
{
|
||||
sql.Select("COUNT(*)").From<UserDto>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetBaseQuery("*");
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
private static Sql GetBaseQuery(string columns)
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select(columns)
|
||||
.From<UserDto>()
|
||||
.LeftJoin<User2AppDto>()
|
||||
.On<UserDto, User2AppDto>(left => left.Id, right => right.UserId);
|
||||
return sql;
|
||||
}
|
||||
|
||||
|
||||
protected override string GetBaseWhereClause()
|
||||
{
|
||||
return "umbracoUser.id = @Id";
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
{
|
||||
var list = new List<string>
|
||||
{
|
||||
"DELETE FROM umbracoUser2NodePermission WHERE userId = @Id",
|
||||
"DELETE FROM umbracoUser2NodeNotify WHERE userId = @Id",
|
||||
"DELETE FROM umbracoUserLogins WHERE userId = @Id",
|
||||
"DELETE FROM umbracoUser2app WHERE " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("user") + "=@Id",
|
||||
"DELETE FROM umbracoUser WHERE id = @Id"
|
||||
};
|
||||
return list;
|
||||
@@ -120,6 +147,14 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var id = Convert.ToInt32(Database.Insert(userDto));
|
||||
entity.Id = id;
|
||||
|
||||
foreach (var sectionDto in userDto.User2AppDtos)
|
||||
{
|
||||
//need to set the id explicitly here
|
||||
sectionDto.UserId = id;
|
||||
Database.Insert(sectionDto);
|
||||
}
|
||||
|
||||
((ICanBeDirty)entity).ResetDirtyProperties();
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(IUser entity)
|
||||
@@ -128,25 +163,89 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var userDto = userFactory.BuildDto(entity);
|
||||
|
||||
Database.Update(userDto);
|
||||
|
||||
//update the sections if they've changed
|
||||
var user = (User)entity;
|
||||
if (user.IsPropertyDirty("AllowedSections"))
|
||||
{
|
||||
//for any that exist on the object, we need to determine if we need to update or insert
|
||||
foreach (var sectionDto in userDto.User2AppDtos)
|
||||
{
|
||||
if (user.AddedSections.Contains(sectionDto.AppAlias))
|
||||
{
|
||||
//we need to insert since this was added
|
||||
Database.Insert(sectionDto);
|
||||
}
|
||||
else
|
||||
{
|
||||
//we need to manually update this record because it has a composite key
|
||||
Database.Update<User2AppDto>("SET app=@Section WHERE app=@Section AND " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("user") + "=@UserId",
|
||||
new { Section = sectionDto.AppAlias, UserId = sectionDto.UserId });
|
||||
}
|
||||
}
|
||||
|
||||
//now we need to delete any applications that have been removed
|
||||
foreach (var section in user.RemovedSections)
|
||||
{
|
||||
//we need to manually delete thsi record because it has a composite key
|
||||
Database.Delete<User2AppDto>("WHERE app=@Section AND " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("user") + "=@UserId",
|
||||
new { Section = section, UserId = (int)user.Id });
|
||||
}
|
||||
}
|
||||
|
||||
((ICanBeDirty)entity).ResetDirtyProperties();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IUserRepository
|
||||
|
||||
public IProfile GetProfileById(int id)
|
||||
|
||||
public IEnumerable<IUser> GetUsersAssignedToSection(string sectionAlias)
|
||||
{
|
||||
//Here we're building up a query that looks like this, a sub query is required because the resulting structure
|
||||
// needs to still contain all of the section rows per user.
|
||||
|
||||
//SELECT *
|
||||
//FROM [umbracoUser]
|
||||
//LEFT JOIN [umbracoUser2app]
|
||||
//ON [umbracoUser].[id] = [umbracoUser2app].[user]
|
||||
//WHERE umbracoUser.id IN (SELECT umbracoUser.id
|
||||
// FROM [umbracoUser]
|
||||
// LEFT JOIN [umbracoUser2app]
|
||||
// ON [umbracoUser].[id] = [umbracoUser2app].[user]
|
||||
// WHERE umbracoUser2app.app = 'content')
|
||||
|
||||
var sql = GetBaseQuery(false);
|
||||
sql.Where(GetBaseWhereClause(), new { Id = id });
|
||||
var innerSql = GetBaseQuery("umbracoUser.id");
|
||||
innerSql.Where("umbracoUser2app.app = " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(sectionAlias));
|
||||
sql.Where(string.Format("umbracoUser.id IN ({0})", innerSql.SQL));
|
||||
|
||||
var dto = Database.FirstOrDefault<UserDto>(sql);
|
||||
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
return new Profile(dto.Id, dto.UserName);
|
||||
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private IEnumerable<IUser> ConvertFromDtos(IEnumerable<UserDto> dtos)
|
||||
{
|
||||
var foundUserTypes = new Dictionary<short, IUserType>();
|
||||
return dtos.Select(dto =>
|
||||
{
|
||||
//first we need to get the user type
|
||||
IUserType userType;
|
||||
if (foundUserTypes.ContainsKey(dto.Type))
|
||||
{
|
||||
userType = foundUserTypes[dto.Type];
|
||||
}
|
||||
else
|
||||
{
|
||||
userType = _userTypeRepository.Get(dto.Type);
|
||||
//put it in the local cache
|
||||
foundUserTypes.Add(dto.Type, userType);
|
||||
}
|
||||
|
||||
var userFactory = new UserFactory(userType);
|
||||
return userFactory.BuildEntity(dto);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = GetBaseQuery(false);
|
||||
sql.Where(GetBaseWhereClause(), new { Id = id });
|
||||
|
||||
var dto = Database.Query<UserTypeDto>(sql).FirstOrDefault();
|
||||
var dto = Database.FirstOrDefault<UserTypeDto>(sql);
|
||||
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
@@ -8,7 +8,7 @@ using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
internal abstract class VersionableRepositoryBase<TId, TEntity> : PetaPocoRepositoryBase<TId, TEntity>
|
||||
internal abstract class VersionableRepositoryBase<TId, TEntity> : PermissionRepository<TId, TEntity>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
protected VersionableRepositoryBase(IDatabaseUnitOfWork work) : base(work)
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Umbraco.Core.Persistence
|
||||
uow,
|
||||
RuntimeCacheProvider.Current,
|
||||
CreateContentTypeRepository(uow),
|
||||
CreateTemplateRepository(uow));
|
||||
CreateTemplateRepository(uow)) { EnsureUniqueNaming = Umbraco.Core.Configuration.UmbracoSettings.EnsureUniqueNaming };
|
||||
}
|
||||
|
||||
public virtual IContentTypeRepository CreateContentTypeRepository(IDatabaseUnitOfWork uow)
|
||||
@@ -81,7 +81,7 @@ namespace Umbraco.Core.Persistence
|
||||
return new MediaRepository(
|
||||
uow,
|
||||
RuntimeCacheProvider.Current,
|
||||
CreateMediaTypeRepository(uow));
|
||||
CreateMediaTypeRepository(uow)) { EnsureUniqueNaming = Umbraco.Core.Configuration.UmbracoSettings.EnsureUniqueNaming };
|
||||
}
|
||||
|
||||
public virtual IMediaTypeRepository CreateMediaTypeRepository(IDatabaseUnitOfWork uow)
|
||||
@@ -118,7 +118,7 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
public virtual ITemplateRepository CreateTemplateRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new TemplateRepository(uow, NullCacheProvider.Current);
|
||||
return new TemplateRepository(uow, RuntimeCacheProvider.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -317,11 +317,10 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
{
|
||||
db.OpenSharedConnection();
|
||||
// Need 4 @ signs as it is regarded as a parameter, @@ escapes it once, @@@@ escapes it twice
|
||||
var lowerCaseFileSystem = db.Fetch<int>("SELECT @@@@Global.lower_case_file_system");
|
||||
var lowerCaseTableNames = db.Fetch<int>("SELECT @@@@Global.lower_case_table_names");
|
||||
|
||||
if(lowerCaseFileSystem.Any() && lowerCaseTableNames.Any())
|
||||
supportsCaseInsensitiveQueries = lowerCaseFileSystem.First() == 1 && lowerCaseTableNames.First() == 1;
|
||||
if(lowerCaseTableNames.Any())
|
||||
supportsCaseInsensitiveQueries = lowerCaseTableNames.First() == 1;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using StackExchange.Profiling;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -46,8 +48,7 @@ namespace Umbraco.Core.Persistence
|
||||
// wrap the connection with a profiling connection that tracks timings
|
||||
return new StackExchange.Profiling.Data.ProfiledDbConnection(connection as DbConnection, MiniProfiler.Current);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void OnException(Exception x)
|
||||
{
|
||||
LogHelper.Info<UmbracoDatabase>(x.StackTrace);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using StackExchange.Profiling;
|
||||
using StackExchange.Profiling.SqlFormatters;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -52,13 +53,8 @@ namespace Umbraco.Core.Profiling
|
||||
/// <param name="e"></param>
|
||||
void UmbracoApplicationEndRequest(object sender, EventArgs e)
|
||||
{
|
||||
if (GlobalSettings.DebugMode == false) return;
|
||||
var request = TryGetRequest(sender);
|
||||
if (request.Success == false) return;
|
||||
if (request.Result.Url.IsClientSideRequest()) return;
|
||||
if (string.IsNullOrEmpty(request.Result["umbDebug"]) == false)
|
||||
if (CanPerformProfilingAction(sender))
|
||||
{
|
||||
//stop the profiler
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
@@ -70,17 +66,28 @@ namespace Umbraco.Core.Profiling
|
||||
/// <param name="e"></param>
|
||||
void UmbracoApplicationBeginRequest(object sender, EventArgs e)
|
||||
{
|
||||
if (GlobalSettings.DebugMode == false) return;
|
||||
var request = TryGetRequest(sender);
|
||||
if (request.Success == false) return;
|
||||
if (request.Result.Url.IsClientSideRequest()) return;
|
||||
if (string.IsNullOrEmpty(request.Result["umbDebug"]) == false)
|
||||
if (CanPerformProfilingAction(sender))
|
||||
{
|
||||
//start the profiler
|
||||
Start();
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanPerformProfilingAction(object sender)
|
||||
{
|
||||
if (GlobalSettings.DebugMode == false)
|
||||
return false;
|
||||
|
||||
//will not run in medium trust
|
||||
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
|
||||
return false;
|
||||
|
||||
var request = TryGetRequest(sender);
|
||||
if (request.Success == false || request.Result.Url.IsClientSideRequest() || string.IsNullOrEmpty(request.Result["umbDebug"]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Render the UI to display the profiler
|
||||
/// </summary>
|
||||
@@ -103,9 +110,7 @@ namespace Umbraco.Core.Profiling
|
||||
/// </remarks>
|
||||
public IDisposable Step(string name)
|
||||
{
|
||||
if (GlobalSettings.DebugMode == false) return null;
|
||||
|
||||
return MiniProfiler.Current.Step(name);
|
||||
return GlobalSettings.DebugMode == false ? null : MiniProfiler.Current.Step(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -113,10 +118,8 @@ namespace Umbraco.Core.Profiling
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
if (GlobalSettings.DebugMode == false) return;
|
||||
//will not run in medium trust
|
||||
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High) return;
|
||||
|
||||
MiniProfiler.Settings.SqlFormatter = new SqlServerFormatter();
|
||||
MiniProfiler.Settings.StackMaxLength = 5000;
|
||||
MiniProfiler.Start();
|
||||
}
|
||||
|
||||
@@ -129,10 +132,6 @@ namespace Umbraco.Core.Profiling
|
||||
/// </remarks>
|
||||
public void Stop(bool discardResults = false)
|
||||
{
|
||||
if (GlobalSettings.DebugMode == false) return;
|
||||
//will not run in medium trust
|
||||
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High) return;
|
||||
|
||||
MiniProfiler.Stop(discardResults);
|
||||
}
|
||||
|
||||
@@ -156,6 +155,5 @@ namespace Umbraco.Core.Profiling
|
||||
return new Attempt<HttpRequestBase>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Publishing
|
||||
@@ -10,6 +11,11 @@ namespace Umbraco.Core.Publishing
|
||||
public IContent ContentItem { get; private set; }
|
||||
public PublishStatusType StatusType { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets sets the invalid properties if the status failed due to validation.
|
||||
/// </summary>
|
||||
public IEnumerable<Property> InvalidProperties { get; set; }
|
||||
|
||||
public PublishStatus(IContent content, PublishStatusType statusType)
|
||||
{
|
||||
ContentItem = content;
|
||||
@@ -24,6 +30,5 @@ namespace Umbraco.Core.Publishing
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,12 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Auditing;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
@@ -88,7 +86,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parentId), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", content.CreatorId, content.Id);
|
||||
Audit.Add(AuditTypes.New, string.Format("Content '{0}' was created", name), content.CreatorId, content.Id);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -123,7 +121,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parent), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", content.CreatorId, content.Id);
|
||||
Audit.Add(AuditTypes.New, string.Format("Content '{0}' was created", name), content.CreatorId, content.Id);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -163,7 +161,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parentId), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", content.CreatorId, content.Id);
|
||||
Audit.Add(AuditTypes.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -203,7 +201,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parent), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", content.CreatorId, content.Id);
|
||||
Audit.Add(AuditTypes.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -333,7 +331,7 @@ namespace Umbraco.Core.Services
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var query = Query<IContent>.Builder.Where(x => x.ParentId == id);
|
||||
var contents = repository.GetByQuery(query);
|
||||
var contents = repository.GetByQuery(query).OrderBy(x => x.SortOrder);
|
||||
|
||||
return contents;
|
||||
}
|
||||
@@ -1036,7 +1034,10 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
content.WriterId = userId;
|
||||
// Update the create author and last edit author
|
||||
copy.CreatorId = userId;
|
||||
copy.WriterId = userId;
|
||||
|
||||
repository.AddOrUpdate(copy);
|
||||
uow.Commit();
|
||||
|
||||
@@ -1111,7 +1112,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
//Look for children and copy those as well
|
||||
var children = GetChildren(content.Id).OrderBy(x => x.SortOrder);
|
||||
var children = GetChildren(content.Id);
|
||||
foreach (var child in children)
|
||||
{
|
||||
Copy(child, copy.Id, relateToOriginal, userId);
|
||||
@@ -1121,6 +1122,9 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit.Add(AuditTypes.Copy, "Copy Content performed by user", content.WriterId, content.Id);
|
||||
|
||||
|
||||
//TODO: Don't think we need this here because cache should be cleared by the event listeners
|
||||
// and the correct ICacheRefreshers!?
|
||||
RuntimeCacheProvider.Current.Clear();
|
||||
|
||||
return copy;
|
||||
@@ -1172,6 +1176,7 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
content.WriterId = userId;
|
||||
content.CreatorId = userId;
|
||||
content.ChangePublishedState(PublishedState.Unpublished);
|
||||
|
||||
repository.AddOrUpdate(content);
|
||||
uow.Commit();
|
||||
@@ -1451,11 +1456,10 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
//Only loop through content that was successfully published, was not already published and where the Published property has been updated
|
||||
//NOTE The Publish with subpages-dialog was used more as a republish-type-thing, so we'll have to include PublishStatusType.SuccessAlreadyPublished
|
||||
//in the updated-list, so the Published event is triggered with the expected set of pages and the xml is updated.
|
||||
foreach (var item in publishedOutcome.Where(
|
||||
x => x.Success
|
||||
&& x.Result.StatusType != PublishStatusType.SuccessAlreadyPublished
|
||||
&& ((ICanBeDirty)x.Result.ContentItem).IsPropertyDirty("Published")))
|
||||
x => x.Success || x.Result.StatusType == PublishStatusType.SuccessAlreadyPublished))
|
||||
{
|
||||
item.Result.ContentItem.WriterId = userId;
|
||||
repository.AddOrUpdate(item.Result.ContentItem);
|
||||
@@ -1548,6 +1552,8 @@ namespace Umbraco.Core.Services
|
||||
publishStatus.StatusType = CheckAndLogIsPublishable(content);
|
||||
//Content contains invalid property values and can therefore not be published - fire event?
|
||||
publishStatus.StatusType = CheckAndLogIsValid(content);
|
||||
//set the invalid properties (if there are any)
|
||||
publishStatus.InvalidProperties = ((ContentBase) content).LastInvalidProperties;
|
||||
|
||||
//if we're still successful, then publish using the strategy
|
||||
if (publishStatus.StatusType == PublishStatusType.Success)
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all values for an <see cref="IDataTypeDefinition"/>
|
||||
/// Gets all prevalues for an <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="IDataTypeDefinition"/> to retrieve prevalues from</param>
|
||||
/// <returns>An enumerable list of string values</returns>
|
||||
@@ -115,6 +115,24 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all prevalues for an <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method should be kept internal until a proper PreValue object model is introduced.
|
||||
/// </remarks>
|
||||
/// <param name="id">Id of the <see cref="IDataTypeDefinition"/> to retrieve prevalues from</param>
|
||||
/// <returns>An enumerable list of Tuples containing Id, Alias, SortOrder, Value</returns>
|
||||
internal IEnumerable<Tuple<int, string, int, string>> GetDetailedPreValuesByDataTypeId(int id)
|
||||
{
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
var dtos = uow.Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = id });
|
||||
var list = dtos.Select(x => new Tuple<int, string, int, string>(x.Id, x.Alias, x.SortOrder, x.Value)).ToList();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific PreValue by its Id
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using Umbraco.Core.Models.Membership;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines part of the UserService, which is specific to methods used by the membership provider.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Idea is to have this is an isolated interface so that it can be easily 'replaced' in the membership provider impl.
|
||||
/// </remarks>
|
||||
internal interface IMembershipUserService : IService
|
||||
{
|
||||
IMembershipUser CreateMembershipUser(string name, string login, string password, IUserType userType, string email = "");
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,10 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IProfile"/></returns>
|
||||
IProfile GetProfileById(int id);
|
||||
|
||||
IProfile GetProfileByUserName(string username);
|
||||
IUser GetUserByUserName(string username);
|
||||
IUser GetUserById(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IUserType by its Alias
|
||||
/// </summary>
|
||||
@@ -28,16 +32,17 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="name">Name of the UserType to retrieve</param>
|
||||
/// <returns><see cref="IUserType"/></returns>
|
||||
IUserType GetUserTypeByName(string name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines part of the UserService, which is specific to methods used by the membership provider.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Idea is to have this is an isolated interface so that it can be easily 'replaced' in the membership provider impl.
|
||||
/// </remarks>
|
||||
internal interface IMembershipUserService : IService
|
||||
{
|
||||
IMembershipUser CreateUser(string name, string login, string password, IUserType userType, string email = "");
|
||||
/// <summary>
|
||||
/// Saves changes to the user object
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
void SaveUser(IUser user);
|
||||
|
||||
/// <summary>
|
||||
/// This is useful when an entire section is removed from config
|
||||
/// </summary>
|
||||
/// <param name="sectionAlias"></param>
|
||||
void DeleteSectionFromAllUsers(string sectionAlias);
|
||||
}
|
||||
}
|
||||
@@ -63,9 +63,9 @@ namespace Umbraco.Core.Services
|
||||
|
||||
media.CreatorId = userId;
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId), this);
|
||||
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", media.CreatorId, media.Id);
|
||||
Audit.Add(AuditTypes.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
|
||||
|
||||
return media;
|
||||
}
|
||||
@@ -98,7 +98,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parent), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", media.CreatorId, media.Id);
|
||||
Audit.Add(AuditTypes.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
|
||||
|
||||
return media;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", media.CreatorId, media.Id);
|
||||
Audit.Add(AuditTypes.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
|
||||
|
||||
return media;
|
||||
}
|
||||
@@ -186,7 +186,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parent), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", media.CreatorId, media.Id);
|
||||
Audit.Add(AuditTypes.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
|
||||
|
||||
return media;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
@@ -45,8 +49,131 @@ namespace Umbraco.Core.Services
|
||||
_importedContentTypes = new Dictionary<string, IContentType>();
|
||||
}
|
||||
|
||||
#region Generic export methods
|
||||
|
||||
internal void ExportToFile(string absoluteFilePath, string nodeType, int id)
|
||||
{
|
||||
XElement xml = null;
|
||||
|
||||
if (nodeType.Equals("content", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var content = _contentService.GetById(id);
|
||||
xml = Export(content);
|
||||
}
|
||||
|
||||
if (nodeType.Equals("media", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var media = _mediaService.GetById(id);
|
||||
xml = Export(media);
|
||||
}
|
||||
|
||||
if (nodeType.Equals("contenttype", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var contentType = _contentTypeService.GetContentType(id);
|
||||
xml = Export(contentType);
|
||||
}
|
||||
|
||||
if (nodeType.Equals("mediatype", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var mediaType = _contentTypeService.GetMediaType(id);
|
||||
xml = Export(mediaType);
|
||||
}
|
||||
|
||||
if (nodeType.Equals("datatype", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var dataType = _dataTypeService.GetDataTypeDefinitionById(id);
|
||||
xml = Export(dataType);
|
||||
}
|
||||
|
||||
if(xml != null)
|
||||
xml.Save(absoluteFilePath);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Content
|
||||
|
||||
/// <summary>
|
||||
/// Exports an <see cref="IContent"/> item to xml as an <see cref="XElement"/>
|
||||
/// </summary>
|
||||
/// <param name="content">Content to export</param>
|
||||
/// <param name="deep">Optional parameter indicating whether to include descendents</param>
|
||||
/// <returns><see cref="XElement"/> containing the xml representation of the Content object</returns>
|
||||
internal XElement Export(IContent content, bool deep = false)
|
||||
{
|
||||
//nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias);
|
||||
var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "node" : content.ContentType.Alias.ToSafeAliasWithForcingCheck();
|
||||
|
||||
var xml = Export(content, nodeName);
|
||||
xml.Add(new XAttribute("nodeType", content.ContentType.Id));
|
||||
xml.Add(new XAttribute("creatorName", content.GetCreatorProfile().Name));
|
||||
xml.Add(new XAttribute("writerName", content.GetWriterProfile().Name));
|
||||
xml.Add(new XAttribute("writerID", content.WriterId));
|
||||
xml.Add(new XAttribute("template", content.Template == null ? "0" : content.Template.Id.ToString(CultureInfo.InvariantCulture)));
|
||||
xml.Add(new XAttribute("nodeTypeAlias", content.ContentType.Alias));
|
||||
|
||||
if (deep)
|
||||
{
|
||||
var descendants = content.Descendants().ToArray();
|
||||
var currentChildren = descendants.Where(x => x.ParentId == content.Id);
|
||||
AddChildXml(descendants, currentChildren, xml);
|
||||
}
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Part of the export of IContent and IMedia which is shared
|
||||
/// </summary>
|
||||
/// <param name="contentBase">Base Content or Media to export</param>
|
||||
/// <param name="nodeName">Name of the node</param>
|
||||
/// <returns><see cref="XElement"/></returns>
|
||||
private XElement Export(IContentBase contentBase, string nodeName)
|
||||
{
|
||||
//NOTE: that one will take care of umbracoUrlName
|
||||
var url = contentBase.GetUrlSegment();
|
||||
|
||||
var xml = new XElement(nodeName,
|
||||
new XAttribute("id", contentBase.Id),
|
||||
new XAttribute("parentID", contentBase.Level > 1 ? contentBase.ParentId : -1),
|
||||
new XAttribute("level", contentBase.Level),
|
||||
new XAttribute("creatorID", contentBase.CreatorId),
|
||||
new XAttribute("sortOrder", contentBase.SortOrder),
|
||||
new XAttribute("createDate", contentBase.CreateDate.ToString("s")),
|
||||
new XAttribute("updateDate", contentBase.UpdateDate.ToString("s")),
|
||||
new XAttribute("nodeName", contentBase.Name),
|
||||
new XAttribute("urlName", url),
|
||||
new XAttribute("path", contentBase.Path),
|
||||
new XAttribute("isDoc", ""));
|
||||
|
||||
foreach (var property in contentBase.Properties.Where(p => p != null))
|
||||
xml.Add(property.ToXml());
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by Content Export to recursively add children
|
||||
/// </summary>
|
||||
/// <param name="originalDescendants"></param>
|
||||
/// <param name="currentChildren"></param>
|
||||
/// <param name="currentXml"></param>
|
||||
private void AddChildXml(IContent[] originalDescendants, IEnumerable<IContent> currentChildren, XElement currentXml)
|
||||
{
|
||||
foreach (var child in currentChildren)
|
||||
{
|
||||
//add the child's xml
|
||||
var childXml = Export(child);
|
||||
currentXml.Add(childXml);
|
||||
//copy local (out of closure)
|
||||
var c = child;
|
||||
//get this item's children
|
||||
var children = originalDescendants.Where(x => x.ParentId == c.Id);
|
||||
//recurse and add it's children to the child xml element
|
||||
AddChildXml(originalDescendants, children, childXml);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports and saves package xml as <see cref="IContent"/>
|
||||
/// </summary>
|
||||
@@ -160,7 +287,7 @@ namespace Umbraco.Core.Services
|
||||
var properties = from property in element.Elements()
|
||||
where property.Attribute("isDoc") == null
|
||||
select property;
|
||||
|
||||
|
||||
IContent content = parent == null
|
||||
? new Content(nodeName, parentId, contentType)
|
||||
{
|
||||
@@ -177,21 +304,42 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
string propertyTypeAlias = isLegacySchema ? property.Attribute("alias").Value : property.Name.LocalName;
|
||||
if (content.HasProperty(propertyTypeAlias))
|
||||
content.SetValue(propertyTypeAlias, property.Value);
|
||||
{
|
||||
var propertyValue = property.Value;
|
||||
|
||||
var propertyType = contentType.PropertyTypes.FirstOrDefault(pt => pt.Alias == propertyTypeAlias);
|
||||
if (propertyType != null && propertyType.DataTypeId == new Guid(Constants.PropertyEditors.CheckBoxList))
|
||||
{
|
||||
var database = ApplicationContext.Current.DatabaseContext.Database;
|
||||
var dtos = database.Fetch<DataTypePreValueDto>("WHERE datatypeNo" + "deId = @Id", new { Id = propertyType.DataTypeDefinitionId });
|
||||
|
||||
var propertyValueList = new List<string>();
|
||||
foreach (var preValue in propertyValue.Split(','))
|
||||
{
|
||||
propertyValueList.Add(dtos.Single(x => x.Value == preValue).Id.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
propertyValue = string.Join(",", propertyValueList.ToArray());
|
||||
}
|
||||
|
||||
content.SetValue(propertyTypeAlias, propertyValue);
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
internal XElement Export(IContent content, bool deep = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region ContentTypes
|
||||
|
||||
/// <summary>
|
||||
/// Exports an <see cref="IContentType"/> to xml as an <see cref="XElement"/>
|
||||
/// </summary>
|
||||
/// <param name="contentType">ContentType to export</param>
|
||||
/// <returns><see cref="XElement"/> containing the xml representation of the ContentType item.</returns>
|
||||
public XElement Export(IContentType contentType)
|
||||
{
|
||||
var info = new XElement("Info",
|
||||
@@ -244,7 +392,7 @@ namespace Umbraco.Core.Services
|
||||
foreach (var propertyGroup in contentType.PropertyGroups)
|
||||
{
|
||||
var tab = new XElement("Tab",
|
||||
new XElement("Id", propertyGroup.Id.ToString()),
|
||||
new XElement("Id", propertyGroup.Id.ToString(CultureInfo.InvariantCulture)),
|
||||
new XElement("Caption", propertyGroup.Name));
|
||||
tabs.Add(tab);
|
||||
}
|
||||
@@ -386,7 +534,7 @@ namespace Umbraco.Core.Services
|
||||
foreach (var templateElement in allowedTemplatesElement.Elements("Template"))
|
||||
{
|
||||
var alias = templateElement.Value;
|
||||
var template = _fileService.GetTemplate(alias);
|
||||
var template = _fileService.GetTemplate(alias.ToSafeAlias());
|
||||
if (template != null)
|
||||
{
|
||||
if(allowedTemplates.Any(x => x.Id == template.Id)) continue;
|
||||
@@ -406,7 +554,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
if (string.IsNullOrEmpty(defaultTemplateElement.Value) == false)
|
||||
{
|
||||
var defaultTemplate = _fileService.GetTemplate(defaultTemplateElement.Value);
|
||||
var defaultTemplate = _fileService.GetTemplate(defaultTemplateElement.Value.ToSafeAlias());
|
||||
if (defaultTemplate != null)
|
||||
{
|
||||
contentType.SetDefaultTemplate(defaultTemplate);
|
||||
@@ -548,6 +696,30 @@ namespace Umbraco.Core.Services
|
||||
|
||||
#region DataTypes
|
||||
|
||||
internal XElement Export(IDataTypeDefinition dataTypeDefinition)
|
||||
{
|
||||
var prevalues = new XElement("PreValues");
|
||||
|
||||
var prevalueList = ((DataTypeService)_dataTypeService).GetDetailedPreValuesByDataTypeId(dataTypeDefinition.Id);
|
||||
foreach (var tuple in prevalueList)
|
||||
{
|
||||
var prevalue = new XElement("PreValue");
|
||||
prevalue.Add(new XAttribute("Id", tuple.Item1));
|
||||
prevalue.Add(new XAttribute("Value", tuple.Item4));
|
||||
prevalue.Add(new XAttribute("Alias", tuple.Item2));
|
||||
prevalue.Add(new XAttribute("SortOrder", tuple.Item3));
|
||||
prevalues.Add(prevalue);
|
||||
}
|
||||
|
||||
var xml = new XElement("DataType", prevalues);
|
||||
xml.Add(new XAttribute("Name", dataTypeDefinition.Name));
|
||||
xml.Add(new XAttribute("Id", dataTypeDefinition.Id));
|
||||
xml.Add(new XAttribute("Definition", dataTypeDefinition.Key));
|
||||
xml.Add(new XAttribute("DatabaseType", dataTypeDefinition.DatabaseType.ToString()));
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports and saves package xml as <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
@@ -615,6 +787,7 @@ namespace Umbraco.Core.Services
|
||||
_dataTypeService.SavePreValues(dataTypeDefinition.Id, values);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dictionary Items
|
||||
@@ -630,9 +803,121 @@ namespace Umbraco.Core.Services
|
||||
#endregion
|
||||
|
||||
#region Media
|
||||
|
||||
/// <summary>
|
||||
/// Exports an <see cref="IMedia"/> item to xml as an <see cref="XElement"/>
|
||||
/// </summary>
|
||||
/// <param name="media">Media to export</param>
|
||||
/// <param name="deep">Optional parameter indicating whether to include descendents</param>
|
||||
/// <returns><see cref="XElement"/> containing the xml representation of the Media object</returns>
|
||||
internal XElement Export(IMedia media, bool deep = false)
|
||||
{
|
||||
//nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias);
|
||||
var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "node" : media.ContentType.Alias.ToSafeAliasWithForcingCheck();
|
||||
|
||||
var xml = Export(media, nodeName);
|
||||
xml.Add(new XAttribute("nodeType", media.ContentType.Id));
|
||||
xml.Add(new XAttribute("writerName", media.GetCreatorProfile().Name));
|
||||
xml.Add(new XAttribute("writerID", media.CreatorId));
|
||||
xml.Add(new XAttribute("version", media.Version));
|
||||
xml.Add(new XAttribute("template", 0));
|
||||
xml.Add(new XAttribute("nodeTypeAlias", media.ContentType.Alias));
|
||||
|
||||
if (deep)
|
||||
{
|
||||
var descendants = media.Descendants().ToArray();
|
||||
var currentChildren = descendants.Where(x => x.ParentId == media.Id);
|
||||
AddChildXml(descendants, currentChildren, xml);
|
||||
}
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by Media Export to recursively add children
|
||||
/// </summary>
|
||||
/// <param name="originalDescendants"></param>
|
||||
/// <param name="currentChildren"></param>
|
||||
/// <param name="currentXml"></param>
|
||||
private void AddChildXml(IMedia[] originalDescendants, IEnumerable<IMedia> currentChildren, XElement currentXml)
|
||||
{
|
||||
foreach (var child in currentChildren)
|
||||
{
|
||||
//add the child's xml
|
||||
var childXml = Export(child);
|
||||
currentXml.Add(childXml);
|
||||
//copy local (out of closure)
|
||||
var c = child;
|
||||
//get this item's children
|
||||
var children = originalDescendants.Where(x => x.ParentId == c.Id);
|
||||
//recurse and add it's children to the child xml element
|
||||
AddChildXml(originalDescendants, children, childXml);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MediaTypes
|
||||
|
||||
/// <summary>
|
||||
/// Exports an <see cref="IMediaType"/> to xml as an <see cref="XElement"/>
|
||||
/// </summary>
|
||||
/// <param name="mediaType">MediaType to export</param>
|
||||
/// <returns><see cref="XElement"/> containing the xml representation of the MediaType item.</returns>
|
||||
internal XElement Export(IMediaType mediaType)
|
||||
{
|
||||
var info = new XElement("Info",
|
||||
new XElement("Name", mediaType.Name),
|
||||
new XElement("Alias", mediaType.Alias),
|
||||
new XElement("Icon", mediaType.Icon),
|
||||
new XElement("Thumbnail", mediaType.Thumbnail),
|
||||
new XElement("Description", mediaType.Description),
|
||||
new XElement("AllowAtRoot", mediaType.AllowedAsRoot.ToString()));
|
||||
|
||||
var masterContentType = mediaType.CompositionAliases().FirstOrDefault();
|
||||
if (masterContentType != null)
|
||||
info.Add(new XElement("Master", masterContentType));
|
||||
|
||||
var structure = new XElement("Structure");
|
||||
foreach (var allowedType in mediaType.AllowedContentTypes)
|
||||
{
|
||||
structure.Add(new XElement("MediaType", allowedType.Alias));
|
||||
}
|
||||
|
||||
var genericProperties = new XElement("GenericProperties");
|
||||
foreach (var propertyType in mediaType.PropertyTypes)
|
||||
{
|
||||
var definition = _dataTypeService.GetDataTypeDefinitionById(propertyType.DataTypeDefinitionId);
|
||||
var propertyGroup = mediaType.PropertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyGroupId.Value);
|
||||
var genericProperty = new XElement("GenericProperty",
|
||||
new XElement("Name", propertyType.Name),
|
||||
new XElement("Alias", propertyType.Alias),
|
||||
new XElement("Type", propertyType.DataTypeId.ToString()),
|
||||
new XElement("Definition", definition.Key),
|
||||
new XElement("Tab", propertyGroup == null ? "" : propertyGroup.Name),
|
||||
new XElement("Mandatory", propertyType.Mandatory.ToString()),
|
||||
new XElement("Validation", propertyType.ValidationRegExp),
|
||||
new XElement("Description", new XCData(propertyType.Description)));
|
||||
genericProperties.Add(genericProperty);
|
||||
}
|
||||
|
||||
var tabs = new XElement("Tabs");
|
||||
foreach (var propertyGroup in mediaType.PropertyGroups)
|
||||
{
|
||||
var tab = new XElement("Tab",
|
||||
new XElement("Id", propertyGroup.Id.ToString(CultureInfo.InvariantCulture)),
|
||||
new XElement("Caption", propertyGroup.Name));
|
||||
tabs.Add(tab);
|
||||
}
|
||||
|
||||
var xml = new XElement("MediaType",
|
||||
info,
|
||||
structure,
|
||||
genericProperties,
|
||||
tabs);
|
||||
return xml;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Package Manifest
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -14,19 +16,21 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
internal class UserService : IUserService
|
||||
{
|
||||
private readonly RepositoryFactory _repositoryFactory;
|
||||
private readonly RepositoryFactory _repositoryFactory;
|
||||
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
|
||||
|
||||
public UserService(RepositoryFactory repositoryFactory) : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
|
||||
{}
|
||||
public UserService(RepositoryFactory repositoryFactory)
|
||||
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
|
||||
{ }
|
||||
|
||||
public UserService(IDatabaseUnitOfWorkProvider provider) : this(provider, new RepositoryFactory())
|
||||
{}
|
||||
public UserService(IDatabaseUnitOfWorkProvider provider)
|
||||
: this(provider, new RepositoryFactory())
|
||||
{ }
|
||||
|
||||
public UserService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory)
|
||||
{
|
||||
_repositoryFactory = repositoryFactory;
|
||||
_uowProvider = provider;
|
||||
_repositoryFactory = repositoryFactory;
|
||||
_uowProvider = provider;
|
||||
}
|
||||
|
||||
#region Implementation of IUserService
|
||||
@@ -37,13 +41,35 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="id">Id of the User to retrieve</param>
|
||||
/// <returns><see cref="IProfile"/></returns>
|
||||
public IProfile GetProfileById(int id)
|
||||
{
|
||||
var user = GetUserById(id);
|
||||
return new Profile(user.Id, user.Username);
|
||||
}
|
||||
|
||||
public IProfile GetProfileByUserName(string username)
|
||||
{
|
||||
var user = GetUserByUserName(username);
|
||||
return new Profile(user.Id, user.Username);
|
||||
}
|
||||
|
||||
public IUser GetUserByUserName(string username)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateUserRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
return repository.GetProfileById(id);
|
||||
var query = Query<IUser>.Builder.Where(x => x.Username == username);
|
||||
return repository.GetByQuery(query).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public IUser GetUserById(int id)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateUserRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
return repository.Get(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IUserType by its Alias
|
||||
/// </summary>
|
||||
@@ -74,6 +100,45 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Savers changes to a user to the database
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
public void SaveUser(IUser user)
|
||||
{
|
||||
if (UserSaving.IsRaisedEventCancelled(new SaveEventArgs<IUser>(user), this))
|
||||
return;
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateUserRepository(uow))
|
||||
{
|
||||
repository.AddOrUpdate(user);
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
UserSaved.RaiseEvent(new SaveEventArgs<IUser>(user, false), this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is useful for when a section is removed from config
|
||||
/// </summary>
|
||||
/// <param name="sectionAlias"></param>
|
||||
public void DeleteSectionFromAllUsers(string sectionAlias)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateUserRepository(uow))
|
||||
{
|
||||
var assignedUsers = repository.GetUsersAssignedToSection(sectionAlias);
|
||||
foreach (var user in assignedUsers)
|
||||
{
|
||||
//now remove the section for each user and commit
|
||||
user.RemoveAllowedSection(sectionAlias);
|
||||
repository.AddOrUpdate(user);
|
||||
}
|
||||
uow.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new user for logging into the umbraco backoffice
|
||||
/// </summary>
|
||||
@@ -83,7 +148,7 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="userType"></param>
|
||||
/// <param name="email"></param>
|
||||
/// <returns></returns>
|
||||
public IMembershipUser CreateUser(string name, string login, string password, IUserType userType, string email = "")
|
||||
public IMembershipUser CreateMembershipUser(string name, string login, string password, IUserType userType, string email = "")
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateUserRepository(uow))
|
||||
@@ -93,19 +158,19 @@ namespace Umbraco.Core.Services
|
||||
throw new ArgumentException("Login already exists");
|
||||
|
||||
var user = new User(userType)
|
||||
{
|
||||
DefaultToLiveEditing = false,
|
||||
Email = email,
|
||||
Language = Umbraco.Core.Configuration.GlobalSettings.DefaultUILanguage,
|
||||
Name = name,
|
||||
Password = password,
|
||||
Permissions = userType.Permissions,
|
||||
Username = login,
|
||||
StartContentId = -1,
|
||||
StartMediaId = -1,
|
||||
NoConsole = false,
|
||||
IsApproved = true
|
||||
};
|
||||
{
|
||||
DefaultToLiveEditing = false,
|
||||
Email = email,
|
||||
Language = Umbraco.Core.Configuration.GlobalSettings.DefaultUILanguage,
|
||||
Name = name,
|
||||
Password = password,
|
||||
DefaultPermissions = userType.Permissions,
|
||||
Username = login,
|
||||
StartContentId = -1,
|
||||
StartMediaId = -1,
|
||||
NoConsole = false,
|
||||
IsApproved = true
|
||||
};
|
||||
|
||||
repository.AddOrUpdate(user);
|
||||
uow.Commit();
|
||||
@@ -115,5 +180,15 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IUserService, SaveEventArgs<IUser>> UserSaving;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IUserService, SaveEventArgs<IUser>> UserSaved;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
@@ -14,12 +15,27 @@ namespace Umbraco.Core.Standalone
|
||||
private ServiceContext _serviceContext;
|
||||
private readonly StandaloneCoreApplication _application;
|
||||
|
||||
public ServiceContextManager(string connectionString, string providerName)
|
||||
public ServiceContextManager(string connectionString, string providerName, string baseDirectory)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
_providerName = providerName;
|
||||
|
||||
_application = StandaloneCoreApplication.GetApplication();
|
||||
Trace.WriteLine("ServiceContextManager-Current AppDomain: " + AppDomain.CurrentDomain.FriendlyName);
|
||||
Trace.WriteLine("ServiceContextManager-Current AppDomain: " + AppDomain.CurrentDomain.BaseDirectory);
|
||||
|
||||
//var webAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.FullName.StartsWith("umbraco"));
|
||||
//if (webAssembly != null && examineEventHandlerToRemove == null)
|
||||
//{
|
||||
// var examineEventType = webAssembly.GetType("Umbraco.Web.Search.ExamineEvents");
|
||||
// examineEventHandlerToRemove = examineEventType;
|
||||
//}
|
||||
|
||||
_application = StandaloneCoreApplication.GetApplication(baseDirectory);
|
||||
|
||||
var examineEventHandlerToRemove = Type.GetType("Umbraco.Web.Search.ExamineEvents, umbraco");
|
||||
if (examineEventHandlerToRemove != null)
|
||||
_application.WithoutApplicationEventHandler(examineEventHandlerToRemove);
|
||||
|
||||
_application.Start();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ namespace Umbraco.Core.Standalone
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StandaloneCoreApplication"/> class.
|
||||
/// </summary>
|
||||
protected StandaloneCoreApplication() { }
|
||||
protected StandaloneCoreApplication(string baseDirectory)
|
||||
{
|
||||
_baseDirectory = baseDirectory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides the application boot manager.
|
||||
@@ -16,11 +19,12 @@ namespace Umbraco.Core.Standalone
|
||||
/// <returns>An application boot manager.</returns>
|
||||
protected override IBootManager GetBootManager()
|
||||
{
|
||||
return new StandaloneCoreBootManager(this, _handlersToAdd, _handlersToRemove);
|
||||
return new StandaloneCoreBootManager(this, _handlersToAdd, _handlersToRemove, _baseDirectory);
|
||||
}
|
||||
|
||||
#region Application
|
||||
|
||||
private readonly string _baseDirectory;
|
||||
private static StandaloneCoreApplication _application;
|
||||
private static bool _started;
|
||||
private static readonly object AppLock = new object();
|
||||
@@ -28,11 +32,11 @@ namespace Umbraco.Core.Standalone
|
||||
/// <summary>
|
||||
/// Gets the instance of the standalone Umbraco application.
|
||||
/// </summary>
|
||||
public static StandaloneCoreApplication GetApplication()
|
||||
public static StandaloneCoreApplication GetApplication(string baseDirectory)
|
||||
{
|
||||
lock (AppLock)
|
||||
{
|
||||
return _application ?? (_application = new StandaloneCoreApplication());
|
||||
return _application ?? (_application = new StandaloneCoreApplication(baseDirectory));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user