Compare commits
281 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e553f2c671 | |||
| 42c6533e16 | |||
| b0f4cb7d02 | |||
| f809dec874 | |||
| 2477500045 | |||
| d89539a437 | |||
| 4368f15097 | |||
| b90150279b | |||
| ca1b05e30d | |||
| 5c09ba9a2d | |||
| cfa3e3aff1 | |||
| 59ff4a0484 | |||
| b1db99f639 | |||
| ccbb838cef | |||
| 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 | |||
| ddbe15de08 | |||
| 5c5d63ce9a | |||
| d3916a1d85 | |||
| db7cb2dcb4 | |||
| 6281268954 | |||
| cd606a7e9e | |||
| ae9d77a765 | |||
| f6e44b4e7c | |||
| 8e1c45e981 | |||
| 955282f260 | |||
| 4a7ee52d63 | |||
| b4d88b0361 | |||
| b41cf37dd5 | |||
| e6fcdc8dc6 | |||
| 547a137b9a | |||
| 5041e6fcc4 | |||
| db0d139a39 | |||
| fc32100142 | |||
| 7ecbc3b391 | |||
| c3c44df52e | |||
| 13a86624ff | |||
| 2f61bc27c8 | |||
| f484dbf0fc | |||
| 6d0ededd9f | |||
| e7d157a209 | |||
| d3ed90c23e | |||
| f6155d8e49 | |||
| c1cd609325 | |||
| b916360771 | |||
| db4b93dbc3 | |||
| fa8934f89a | |||
| c6940096d3 | |||
| 40868ac361 | |||
| f399a9f52b | |||
| 562851b93e | |||
| 634e4a6949 | |||
| e61b567ee1 | |||
| 7ccae64dd1 | |||
| aef44065c5 | |||
| 4ce22b836e | |||
| 2b8544b4c7 | |||
| 6afa6a277f | |||
| f5bf05a6f5 | |||
| 469db82f1d | |||
| e50569597b | |||
| 071f3dcc01 | |||
| e0bc99af9c | |||
| 232581664b | |||
| b15e147d6b | |||
| c7a4c782e3 | |||
| 780908e24f | |||
| 3ac7e237c4 | |||
| 6943a454f3 | |||
| e870db3c29 | |||
| 41b17160f7 | |||
| b19621c07b | |||
| 0ff979e814 | |||
| f26e39f5ce | |||
| 9a6030a3eb | |||
| 84ef216d57 | |||
| ecfe51134d | |||
| c8414116ad | |||
| 532f407260 | |||
| 834d04f8ed | |||
| 2aa902beaf | |||
| 2f16e6662d | |||
| 0c4897d7c1 | |||
| 43dc14fa93 | |||
| e209aa3c2a | |||
| 5890fe1849 | |||
| b6f52bf782 | |||
| 922ebe5411 | |||
| f36ab37f6a | |||
| aeff33d0a6 | |||
| 645637d550 | |||
| 5cfe9e57ce | |||
| 4863e657df | |||
| 2486e75210 | |||
| c0e1be4df9 | |||
| a93e562f14 | |||
| 2201c644f7 | |||
| 822cac5d87 | |||
| d58487fafc | |||
| ea9653fa83 | |||
| b38397868e | |||
| 7d1a18638b | |||
| 748e88c3e8 | |||
| cb8d080f1d | |||
| 3fd3bf0fda | |||
| 09a6cdc8b6 | |||
| b2fe35695f | |||
| 67b57dea50 | |||
| 3d6172738f | |||
| d94772892d | |||
| 50c12a5c35 | |||
| b42fb1c5c1 | |||
| 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,34 +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
|
||||
@@ -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 your ASP.NET 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/contribute/releases](http://our.umbraco.org/contribute/releases).
|
||||
|
||||
## 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)
|
||||
+4
-2
@@ -1,10 +1,12 @@
|
||||
@ECHO OFF
|
||||
SET release=6.1.0
|
||||
SET comment=beta-2
|
||||
SET release=6.1.2
|
||||
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,10 +15,14 @@
|
||||
<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.5" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1]" />
|
||||
<dependency id="SharpZipLib" version="0.86.0" />
|
||||
<dependency id="MySql.Data" version="[6.6,6.7)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
@@ -32,16 +36,11 @@
|
||||
<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>
|
||||
@@ -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" />
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// An abstract class for implementing a cache helper
|
||||
/// An abstract class for implementing a basic cache provider
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// THIS MUST REMAIN INTERNAL UNTIL WE STREAMLINE HOW ALL CACHE IS HANDLED, WE NEED TO SUPPORT HTTP RUNTIME CACHE, IN MEMORY CACHE, ETC...
|
||||
@@ -22,13 +20,5 @@ namespace Umbraco.Core.Cache
|
||||
public abstract IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith);
|
||||
public abstract T GetCacheItem<T>(string cacheKey);
|
||||
public abstract T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem);
|
||||
public abstract T GetCacheItem<T>(string cacheKey, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract T GetCacheItem<T>(string cacheKey, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, Func<T> getCacheItem);
|
||||
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Cache
|
||||
/// <summary>
|
||||
/// A CacheProvider that wraps the logic of the HttpRuntime.Cache
|
||||
/// </summary>
|
||||
internal class HttpRuntimeCacheProvider : CacheProviderBase
|
||||
internal class HttpRuntimeCacheProvider : RuntimeCacheProviderBase
|
||||
{
|
||||
private readonly System.Web.Caching.Cache _cache;
|
||||
private static readonly object Locker = new object();
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
internal class NullCacheProvider : CacheProviderBase
|
||||
internal class NullCacheProvider : RuntimeCacheProviderBase
|
||||
{
|
||||
public override void ClearAllCache()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// An abstract class for implementing a runtime cache provider
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// THIS MUST REMAIN INTERNAL UNTIL WE STREAMLINE HOW ALL CACHE IS HANDLED, WE NEED TO SUPPORT HTTP RUNTIME CACHE, IN MEMORY CACHE, ETC...
|
||||
/// </remarks>
|
||||
internal abstract class RuntimeCacheProviderBase : CacheProviderBase
|
||||
{
|
||||
public abstract T GetCacheItem<T>(string cacheKey, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract T GetCacheItem<T>(string cacheKey, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract T GetCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, Func<T> getCacheItem);
|
||||
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
public abstract void InsertCacheItem<T>(string cacheKey, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan? timeout, Func<T> getCacheItem);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A cache provider that statically caches everything in an in memory dictionary
|
||||
/// </summary>
|
||||
internal class StaticCacheProvider : CacheProviderBase
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, object> _staticCache = new ConcurrentDictionary<string, object>();
|
||||
|
||||
public override void ClearAllCache()
|
||||
{
|
||||
_staticCache.Clear();
|
||||
}
|
||||
|
||||
public override void ClearCacheItem(string key)
|
||||
{
|
||||
object val;
|
||||
_staticCache.TryRemove(key, out val);
|
||||
}
|
||||
|
||||
public override void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
foreach (var key in _staticCache.Keys)
|
||||
{
|
||||
if (_staticCache[key] != null
|
||||
&& _staticCache[key].GetType().ToString().InvariantEquals(typeName))
|
||||
{
|
||||
object val;
|
||||
_staticCache.TryRemove(key, out val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
foreach (var key in _staticCache.Keys)
|
||||
{
|
||||
if (_staticCache[key] != null
|
||||
&& _staticCache[key].GetType() == typeof(T))
|
||||
{
|
||||
object val;
|
||||
_staticCache.TryRemove(key, out val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
foreach (var key in _staticCache.Keys)
|
||||
{
|
||||
if (key.InvariantStartsWith(keyStartsWith))
|
||||
{
|
||||
ClearCacheItem(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
foreach (var key in _staticCache.Keys)
|
||||
{
|
||||
if (Regex.IsMatch(key, regexString))
|
||||
{
|
||||
ClearCacheItem(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
|
||||
{
|
||||
return (from KeyValuePair<string, object> c in _staticCache
|
||||
where c.Key.InvariantStartsWith(keyStartsWith)
|
||||
select c.Value.TryConvertTo<T>()
|
||||
into attempt
|
||||
where attempt.Success
|
||||
select attempt.Result).ToList();
|
||||
}
|
||||
|
||||
public override T GetCacheItem<T>(string cacheKey)
|
||||
{
|
||||
var result = _staticCache[cacheKey];
|
||||
if (result == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
return result.TryConvertTo<T>().Result;
|
||||
}
|
||||
|
||||
public override T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem)
|
||||
{
|
||||
return (T)_staticCache.GetOrAdd(cacheKey, getCacheItem);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+240
-76
@@ -15,14 +15,13 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Class that is exposed by the ApplicationContext for application wide caching purposes
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class may be opened publicly at some point but needs a review of what is absoletely necessary.
|
||||
/// </remarks>
|
||||
public class CacheHelper //: CacheProviderBase
|
||||
public class CacheHelper
|
||||
{
|
||||
private readonly bool _enableCache;
|
||||
private readonly HttpRuntimeCacheProvider _httpCache;
|
||||
private readonly NullCacheProvider _nullCache = new NullCacheProvider();
|
||||
private readonly CacheProviderBase _staticCache;
|
||||
private readonly CacheProviderBase _nullStaticCache = new NullCacheProvider();
|
||||
private readonly RuntimeCacheProviderBase _httpCache;
|
||||
private readonly RuntimeCacheProviderBase _nullHttpCache = new NullCacheProvider();
|
||||
|
||||
public CacheHelper(System.Web.Caching.Cache cache)
|
||||
: this(cache, true)
|
||||
@@ -30,21 +29,185 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
internal CacheHelper(System.Web.Caching.Cache cache, bool enableCache)
|
||||
{
|
||||
_httpCache = new HttpRuntimeCacheProvider(cache);
|
||||
_enableCache = enableCache;
|
||||
: this(new HttpRuntimeCacheProvider(cache), enableCache)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
internal CacheHelper(RuntimeCacheProviderBase httpCacheProvider, bool enableCache)
|
||||
: this(httpCacheProvider, new StaticCacheProvider(), enableCache)
|
||||
{
|
||||
}
|
||||
|
||||
internal CacheHelper(RuntimeCacheProviderBase httpCacheProvider, CacheProviderBase staticCacheProvider, bool enableCache)
|
||||
{
|
||||
_httpCache = httpCacheProvider;
|
||||
_staticCache = staticCacheProvider;
|
||||
_enableCache = enableCache;
|
||||
}
|
||||
|
||||
#region Static cache
|
||||
|
||||
/// <summary>
|
||||
/// Clears the item in umbraco's static cache
|
||||
/// </summary>
|
||||
internal void ClearAllStaticCache()
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullStaticCache.ClearAllCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
_staticCache.ClearAllCache();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the item in umbraco's static cache with the given key
|
||||
/// </summary>
|
||||
/// <param name="key">Key</param>
|
||||
internal void ClearStaticCacheItem(string key)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullStaticCache.ClearCacheItem(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
_staticCache.ClearCacheItem(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all objects in the static cache with the System.Type name as the
|
||||
/// input parameter. (using [object].GetType())
|
||||
/// </summary>
|
||||
/// <param name="typeName">The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument"</param>
|
||||
internal void ClearStaticCacheObjectTypes(string typeName)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullStaticCache.ClearCacheObjectTypes(typeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
_staticCache.ClearCacheObjectTypes(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all objects in the static cache with the System.Type specified
|
||||
/// </summary>
|
||||
internal void ClearStaticCacheObjectTypes<T>()
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullStaticCache.ClearCacheObjectTypes<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
_staticCache.ClearCacheObjectTypes<T>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all static cache items that starts with the key passed.
|
||||
/// </summary>
|
||||
/// <param name="keyStartsWith">The start of the key</param>
|
||||
internal void ClearStaticCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullStaticCache.ClearCacheByKeySearch(keyStartsWith);
|
||||
}
|
||||
else
|
||||
{
|
||||
_staticCache.ClearCacheByKeySearch(keyStartsWith);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all cache items that have a key that matches the regular expression
|
||||
/// </summary>
|
||||
/// <param name="regexString"></param>
|
||||
internal void ClearStaticCacheByKeyExpression(string regexString)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullStaticCache.ClearCacheByKeyExpression(regexString);
|
||||
}
|
||||
else
|
||||
{
|
||||
_staticCache.ClearCacheByKeyExpression(regexString);
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<T> GetStaticCacheItemsByKeySearch<T>(string keyStartsWith)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullStaticCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _staticCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a static cache item by key, does not update the cache if it isn't there.
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <returns></returns>
|
||||
internal TT GetStaticCacheItem<TT>(string cacheKey)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullStaticCache.GetCacheItem<TT>(cacheKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _staticCache.GetCacheItem<TT>(cacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and adds if necessary) an item from the static cache with all of the default parameters
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
internal TT GetStaticCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullStaticCache.GetCacheItem<TT>(cacheKey, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _staticCache.GetCacheItem<TT>(cacheKey, getCacheItem);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Runtime/Http Cache
|
||||
/// <summary>
|
||||
/// Clears the item in umbraco's runtime cache
|
||||
/// </summary>
|
||||
public void ClearAllCache()
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.ClearAllCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpCache.ClearAllCache();
|
||||
}
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullHttpCache.ClearAllCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpCache.ClearAllCache();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -55,7 +218,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.ClearCacheItem(key);
|
||||
_nullHttpCache.ClearCacheItem(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -73,7 +236,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.ClearCacheObjectTypes(typeName);
|
||||
_nullHttpCache.ClearCacheObjectTypes(typeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -84,55 +247,55 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Clears all objects in the System.Web.Cache with the System.Type specified
|
||||
/// </summary>
|
||||
public void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
public void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.ClearCacheObjectTypes<T>();
|
||||
_nullHttpCache.ClearCacheObjectTypes<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpCache.ClearCacheObjectTypes<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Clears all cache items that starts with the key passed.
|
||||
/// </summary>
|
||||
/// <param name="keyStartsWith">The start of the key</param>
|
||||
public void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.ClearCacheByKeySearch(keyStartsWith);
|
||||
_nullHttpCache.ClearCacheByKeySearch(keyStartsWith);
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpCache.ClearCacheByKeySearch(keyStartsWith);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all cache items that have a key that matches the regular expression
|
||||
/// </summary>
|
||||
/// <param name="regexString"></param>
|
||||
public void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
public void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.ClearCacheByKeyExpression(regexString);
|
||||
_nullHttpCache.ClearCacheByKeyExpression(regexString);
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpCache.ClearCacheByKeyExpression(regexString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
|
||||
return _nullHttpCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -140,7 +303,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Returns a cache item by key, does not update the cache if it isn't there.
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
@@ -150,7 +313,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullCache.GetCacheItem<TT>(cacheKey);
|
||||
return _nullHttpCache.GetCacheItem<TT>(cacheKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -169,7 +332,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullCache.GetCacheItem<TT>(cacheKey, getCacheItem);
|
||||
return _nullHttpCache.GetCacheItem<TT>(cacheKey, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -190,7 +353,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullCache.GetCacheItem<TT>(cacheKey, timeout, getCacheItem);
|
||||
return _nullHttpCache.GetCacheItem<TT>(cacheKey, timeout, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -213,7 +376,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullCache.GetCacheItem<TT>(cacheKey, refreshAction, timeout, getCacheItem);
|
||||
return _nullHttpCache.GetCacheItem<TT>(cacheKey, refreshAction, timeout, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -237,7 +400,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, timeout, getCacheItem);
|
||||
return _nullHttpCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, timeout, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -257,15 +420,15 @@ namespace Umbraco.Core
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
public TT GetCacheItem<TT>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
CacheItemRemovedCallback refreshAction,
|
||||
CacheDependency cacheDependency,
|
||||
TimeSpan timeout,
|
||||
Func<TT> getCacheItem)
|
||||
CacheItemPriority priority,
|
||||
CacheItemRemovedCallback refreshAction,
|
||||
CacheDependency cacheDependency,
|
||||
TimeSpan timeout,
|
||||
Func<TT> getCacheItem)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
|
||||
return _nullHttpCache.GetCacheItem<TT>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -289,7 +452,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
return _nullCache.GetCacheItem<TT>(cacheKey, priority, null, cacheDependency, null, getCacheItem);
|
||||
return _nullHttpCache.GetCacheItem<TT>(cacheKey, priority, null, cacheDependency, null, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -310,14 +473,14 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.InsertCacheItem<T>(cacheKey, priority, getCacheItem);
|
||||
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpCache.InsertCacheItem<T>(cacheKey, priority, getCacheItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
|
||||
/// </summary>
|
||||
@@ -333,7 +496,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.InsertCacheItem<T>(cacheKey, priority, timeout, getCacheItem);
|
||||
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, timeout, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -341,30 +504,30 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="cacheDependency"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
public void InsertCacheItem<T>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
CacheDependency cacheDependency,
|
||||
TimeSpan timeout,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
/// <summary>
|
||||
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="cacheDependency"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
public void InsertCacheItem<T>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
CacheDependency cacheDependency,
|
||||
TimeSpan timeout,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.InsertCacheItem<T>(cacheKey, priority, cacheDependency, timeout, getCacheItem);
|
||||
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, cacheDependency, timeout, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpCache.InsertCacheItem<T>(cacheKey, priority, cacheDependency, timeout, getCacheItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
|
||||
@@ -376,22 +539,23 @@ namespace Umbraco.Core
|
||||
/// <param name="cacheDependency"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
public void InsertCacheItem<T>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
CacheItemRemovedCallback refreshAction,
|
||||
CacheDependency cacheDependency,
|
||||
TimeSpan? timeout,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
public void InsertCacheItem<T>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
CacheItemRemovedCallback refreshAction,
|
||||
CacheDependency cacheDependency,
|
||||
TimeSpan? timeout,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
if (!_enableCache)
|
||||
{
|
||||
_nullCache.InsertCacheItem<T>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
|
||||
_nullHttpCache.InsertCacheItem<T>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpCache.InsertCacheItem<T>(cacheKey, priority, refreshAction, cacheDependency, timeout, getCacheItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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.2");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets the version comment (like beta or RC).
|
||||
/// </summary>
|
||||
/// <value>The version comment.</value>
|
||||
public static string CurrentComment { get { return "beta-2"; } }
|
||||
public static string CurrentComment { get { return ""; } }
|
||||
|
||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||
|
||||
@@ -10,6 +10,7 @@ using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix;
|
||||
using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Publishing;
|
||||
using Umbraco.Core.Macros;
|
||||
@@ -52,8 +53,9 @@ namespace Umbraco.Core
|
||||
if (_isInitialized)
|
||||
throw new InvalidOperationException("The boot manager has already been initialized");
|
||||
|
||||
LogHelper.Info<CoreBootManager>("Umbraco application starting");
|
||||
_timer = DisposableTimer.Start(x => LogHelper.Info<CoreBootManager>("Umbraco application startup complete" + " (took " + x + "ms)"));
|
||||
InitializeProfilerResolver();
|
||||
|
||||
_timer = DisposableTimer.DebugDuration<CoreBootManager>("Umbraco application starting", "Umbraco application startup complete");
|
||||
|
||||
//create database and service contexts for the app context
|
||||
var dbFactory = new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName);
|
||||
@@ -93,6 +95,20 @@ namespace Umbraco.Core
|
||||
ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Special method to initialize the ProfilerResolver
|
||||
/// </summary>
|
||||
protected virtual void InitializeProfilerResolver()
|
||||
{
|
||||
//By default we'll initialize the Log profiler (in the web project, we'll override with the web profiler)
|
||||
ProfilerResolver.Current = new ProfilerResolver(new LogProfiler())
|
||||
{
|
||||
//This is another special resolver that needs to be resolvable before resolution is frozen
|
||||
//since it is used for profiling the application startup
|
||||
CanResolveBeforeFrozen = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Special method to initialize the ApplicationEventsResolver and any modifications required for it such
|
||||
/// as adding custom types to the resolver.
|
||||
@@ -113,6 +129,17 @@ namespace Umbraco.Core
|
||||
ApplicationEventsResolver.Current.AddType<PublishedContentHelper>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Special method to extend the use of Umbraco by enabling the consumer to overwrite
|
||||
/// the absolute path to the root of an Umbraco site/solution, which is used for stuff
|
||||
/// like Umbraco.Core.IO.IOHelper.MapPath etc.
|
||||
/// </summary>
|
||||
/// <param name="rootPath">Absolute</param>
|
||||
protected virtual void InitializeApplicationRootPath(string rootPath)
|
||||
{
|
||||
Umbraco.Core.IO.IOHelper.SetRootDirectory(rootPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires after initialization and calls the callback to allow for customizations to occur &
|
||||
/// Ensure that the OnApplicationStarting methods of the IApplicationEvents are called
|
||||
@@ -185,7 +212,8 @@ namespace Umbraco.Core
|
||||
/// Create the resolvers
|
||||
/// </summary>
|
||||
protected virtual void InitializeResolvers()
|
||||
{
|
||||
{
|
||||
|
||||
//by default we'll use the standard configuration based sync
|
||||
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
|
||||
new ConfigServerRegistrar());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
@@ -10,10 +11,60 @@ using System.Web;
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
///<summary>
|
||||
/// Extension methods for dictionary
|
||||
/// Extension methods for dictionary & concurrentdictionary
|
||||
///</summary>
|
||||
internal static class DictionaryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Updates an item with the specified key with the specified value
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dict"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="updateFactory"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Taken from: http://stackoverflow.com/questions/12240219/is-there-a-way-to-use-concurrentdictionary-tryupdate-with-a-lambda-expression
|
||||
///
|
||||
/// If there is an item in the dictionary with the key, it will keep trying to update it until it can
|
||||
/// </remarks>
|
||||
public static bool TryUpdate<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict, TKey key, Func<TValue, TValue> updateFactory)
|
||||
{
|
||||
TValue curValue;
|
||||
while (dict.TryGetValue(key, out curValue))
|
||||
{
|
||||
if (dict.TryUpdate(key, updateFactory(curValue), curValue))
|
||||
return true;
|
||||
//if we're looping either the key was removed by another thread, or another thread
|
||||
//changed the value, so we start again.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an item with the specified key with the specified value
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dict"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="updateFactory"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Taken from: http://stackoverflow.com/questions/12240219/is-there-a-way-to-use-concurrentdictionary-tryupdate-with-a-lambda-expression
|
||||
///
|
||||
/// WARNING: If the value changes after we've retreived it, then the item will not be updated
|
||||
/// </remarks>
|
||||
public static bool TryUpdateOptimisitic<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict, TKey key, Func<TValue, TValue> updateFactory)
|
||||
{
|
||||
TValue curValue;
|
||||
if (!dict.TryGetValue(key, out curValue))
|
||||
return false;
|
||||
dict.TryUpdate(key, updateFactory(curValue), curValue);
|
||||
return true;//note we return true whether we succeed or not, see explanation below.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a dictionary to another type by only using direct casting
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Profiling;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -9,11 +11,17 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
///
|
||||
/// using (DisposableTimer.TraceDuration{MyType}("starting", "finished"))
|
||||
/// {
|
||||
/// Thread.Sleep(567);
|
||||
/// }
|
||||
///
|
||||
/// Console.WriteLine("Testing Stopwatchdisposable, should be 567:");
|
||||
// using (var timer = new DisposableTimer(result => Console.WriteLine("Took {0}ms", result)))
|
||||
// {
|
||||
// Thread.Sleep(567);
|
||||
// }
|
||||
/// using (var timer = new DisposableTimer(result => Console.WriteLine("Took {0}ms", result)))
|
||||
/// {
|
||||
/// Thread.Sleep(567);
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class DisposableTimer : DisposableObject
|
||||
@@ -24,7 +32,7 @@ namespace Umbraco.Core
|
||||
protected DisposableTimer(Action<long> callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
}
|
||||
|
||||
public Stopwatch Stopwatch
|
||||
{
|
||||
@@ -36,96 +44,149 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
/// <param name="callback">The callback.</param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use either TraceDuration or DebugDuration instead of using Start")]
|
||||
public static DisposableTimer Start(Action<long> callback)
|
||||
{
|
||||
return new DisposableTimer(callback);
|
||||
}
|
||||
|
||||
public static DisposableTimer TraceDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
#region TraceDuration
|
||||
public static DisposableTimer TraceDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
public static DisposableTimer TraceDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
LogHelper.Debug(loggerType, startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage() + " (took " + x + "ms)"));
|
||||
}
|
||||
public static DisposableTimer TraceDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
var startMsg = startMessage();
|
||||
LogHelper.Info(loggerType, startMsg);
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("Start: " + startMsg);
|
||||
var profiler = ActivateProfiler(loggerType, startMsg);
|
||||
return new DisposableTimer(x =>
|
||||
{
|
||||
profiler.DisposeIfDisposable();
|
||||
LogHelper.Info(loggerType, () => completeMessage() + " (took " + x + "ms)");
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("End: " + startMsg);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer TraceDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer TraceDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Info(loggerType, () => startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage + " (took " + x + "ms)"));
|
||||
}
|
||||
public static DisposableTimer TraceDuration<T>(string startMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, "Complete");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Info(loggerType, startMessage);
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("Start: " + startMessage);
|
||||
var profiler = ActivateProfiler(loggerType, startMessage);
|
||||
return new DisposableTimer(x =>
|
||||
{
|
||||
profiler.DisposeIfDisposable();
|
||||
LogHelper.Info(loggerType, () => completeMessage + " (took " + x + "ms)");
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("End: " + startMessage);
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
#region DebugDuration
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Debug(loggerType, () => startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Debug(loggerType, () => completeMessage + " (took " + x + "ms)"));
|
||||
}
|
||||
public static DisposableTimer DebugDuration<T>(string startMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, "Complete");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
LogHelper.Debug(loggerType, startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Debug(loggerType, () => completeMessage() + " (took " + x + "ms)"));
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Debug(loggerType, startMessage);
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("Start: " + startMessage);
|
||||
var profiler = ActivateProfiler(loggerType, startMessage);
|
||||
return new DisposableTimer(x =>
|
||||
{
|
||||
profiler.DisposeIfDisposable();
|
||||
LogHelper.Debug(loggerType, () => completeMessage + " (took " + x + "ms)");
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("End: " + startMessage);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
var msg = startMessage();
|
||||
LogHelper.Debug(loggerType, msg);
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("Start: " + startMessage);
|
||||
var profiler = ActivateProfiler(loggerType, msg);
|
||||
return new DisposableTimer(x =>
|
||||
{
|
||||
profiler.DisposeIfDisposable();
|
||||
LogHelper.Debug(loggerType, () => completeMessage() + " (took " + x + "ms)");
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("End: " + startMessage);
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
|
||||
@@ -134,5 +195,19 @@ namespace Umbraco.Core
|
||||
{
|
||||
_callback.Invoke(Stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
private static IDisposable ActivateProfiler(Type loggerType, string profileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ProfilerResolver.Current.Profiler.Step(loggerType, profileName);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
//swallow this exception, it will occur if the ProfilerResolver is not initialized... generally only in
|
||||
// unit tests.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,11 @@ using System.Text;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
internal class FileSystemProviderAttribute : Attribute
|
||||
public class FileSystemProviderAttribute : Attribute
|
||||
{
|
||||
public string Alias { get; set; }
|
||||
public string Alias { get; private set; }
|
||||
|
||||
public FileSystemProviderAttribute(string alias)
|
||||
{
|
||||
|
||||
+1
-2
@@ -6,8 +6,7 @@ using Umbraco.Core.CodeAnnotations;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
|
||||
internal class FileSystemProvider
|
||||
internal class FileSystemProviderConstants
|
||||
{
|
||||
public const string Media = "media";
|
||||
}
|
||||
@@ -9,9 +9,8 @@ using Umbraco.Core.CodeAnnotations;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
|
||||
internal class FileSystemProviderManager
|
||||
{
|
||||
public class FileSystemProviderManager
|
||||
{
|
||||
private readonly FileSystemProvidersSection _config;
|
||||
|
||||
@@ -28,7 +27,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
#region Constructors
|
||||
|
||||
public FileSystemProviderManager()
|
||||
internal FileSystemProviderManager()
|
||||
{
|
||||
_config = (FileSystemProvidersSection)ConfigurationManager.GetSection("FileSystemProviders");
|
||||
}
|
||||
@@ -48,7 +47,15 @@ namespace Umbraco.Core.IO
|
||||
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
|
||||
private readonly ConcurrentDictionary<Type, string> _wrappedProviderLookup = new ConcurrentDictionary<Type, string>();
|
||||
|
||||
public IFileSystem GetFileSystemProvider(string alias)
|
||||
/// <summary>
|
||||
/// Returns the underlying (non-typed) file system provider for the alias specified
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// It is recommended to use the typed GetFileSystemProvider method instead to get a strongly typed provider instance.
|
||||
/// </remarks>
|
||||
public IFileSystem GetUnderlyingFileSystemProvider(string alias)
|
||||
{
|
||||
//either get the constructor info from cache or create it and add to cache
|
||||
var ctorInfo = _providerLookup.GetOrAdd(alias, s =>
|
||||
@@ -88,6 +95,11 @@ namespace Umbraco.Core.IO
|
||||
return fs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the strongly typed file system provider
|
||||
/// </summary>
|
||||
/// <typeparam name="TProviderTypeFilter"></typeparam>
|
||||
/// <returns></returns>
|
||||
public TProviderTypeFilter GetFileSystemProvider<TProviderTypeFilter>()
|
||||
where TProviderTypeFilter : FileSystemWrapper
|
||||
{
|
||||
@@ -111,7 +123,7 @@ namespace Umbraco.Core.IO
|
||||
return attr.Alias;
|
||||
});
|
||||
|
||||
var innerFs = GetFileSystemProvider(alias);
|
||||
var innerFs = GetUnderlyingFileSystemProvider(alias);
|
||||
var outputFs = Activator.CreateInstance(typeof (TProviderTypeFilter), innerFs);
|
||||
return (TProviderTypeFilter)outputFs;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Configuration;
|
||||
using System.Web;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -37,7 +34,7 @@ namespace Umbraco.Core.IO
|
||||
if (virtualPath.StartsWith("~"))
|
||||
retval = virtualPath.Replace("~", SystemDirectories.Root);
|
||||
|
||||
if (virtualPath.StartsWith("/") && !virtualPath.StartsWith(SystemDirectories.Root))
|
||||
if (virtualPath.StartsWith("/") && virtualPath.StartsWith(SystemDirectories.Root) == false)
|
||||
retval = SystemDirectories.Root + "/" + virtualPath.TrimStart('/');
|
||||
|
||||
return retval;
|
||||
@@ -68,11 +65,7 @@ namespace Umbraco.Core.IO
|
||||
if (tag.Groups[1].Success)
|
||||
url = tag.Groups[1].Value;
|
||||
|
||||
// The richtext editor inserts a slash in front of the url. That's why we need this little fix
|
||||
// if (url.StartsWith("/"))
|
||||
// text = text.Replace(url, ResolveUrl(url.Substring(1)));
|
||||
// else
|
||||
if (!String.IsNullOrEmpty(url))
|
||||
if (string.IsNullOrEmpty(url) == false)
|
||||
{
|
||||
string resolvedUrl = (url.Substring(0, 1) == "/") ? ResolveUrl(url.Substring(1)) : ResolveUrl(url);
|
||||
text = text.Replace(url, resolvedUrl);
|
||||
@@ -97,19 +90,15 @@ namespace Umbraco.Core.IO
|
||||
if (useHttpContext && HttpContext.Current != null)
|
||||
{
|
||||
//string retval;
|
||||
if (!string.IsNullOrEmpty(path) && (path.StartsWith("~") || path.StartsWith(SystemDirectories.Root)))
|
||||
if (string.IsNullOrEmpty(path) == false && (path.StartsWith("~") || path.StartsWith(SystemDirectories.Root)))
|
||||
return System.Web.Hosting.HostingEnvironment.MapPath(path);
|
||||
else
|
||||
return System.Web.Hosting.HostingEnvironment.MapPath("~/" + path.TrimStart('/'));
|
||||
}
|
||||
|
||||
//var root = (!string.IsNullOrEmpty(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath))
|
||||
// ? System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath.TrimEnd(IOHelper.DirSepChar)
|
||||
// : getRootDirectorySafe();
|
||||
|
||||
var root = GetRootDirectorySafe();
|
||||
var newPath = path.TrimStart('~', '/').Replace('/', IOHelper.DirSepChar);
|
||||
var retval = root + IOHelper.DirSepChar.ToString() + newPath;
|
||||
var retval = root + IOHelper.DirSepChar.ToString(CultureInfo.InvariantCulture) + newPath;
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -144,9 +133,9 @@ namespace Umbraco.Core.IO
|
||||
/// <returns>A value indicating whether the filepath is valid.</returns>
|
||||
internal static bool VerifyEditPath(string filePath, string validDir)
|
||||
{
|
||||
if (!filePath.StartsWith(MapPath(SystemDirectories.Root)))
|
||||
if (filePath.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
filePath = MapPath(filePath);
|
||||
if (!validDir.StartsWith(MapPath(SystemDirectories.Root)))
|
||||
if (validDir.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
validDir = MapPath(validDir);
|
||||
|
||||
return filePath.StartsWith(validDir);
|
||||
@@ -161,7 +150,7 @@ namespace Umbraco.Core.IO
|
||||
/// <exception cref="FileSecurityException">The filepath is invalid.</exception>
|
||||
internal static bool ValidateEditPath(string filePath, string validDir)
|
||||
{
|
||||
if (!VerifyEditPath(filePath, validDir))
|
||||
if (VerifyEditPath(filePath, validDir) == false)
|
||||
throw new FileSecurityException(String.Format("The filepath '{0}' is not within an allowed directory for this type of files", filePath.Replace(MapPath(SystemDirectories.Root), "")));
|
||||
return true;
|
||||
}
|
||||
@@ -177,9 +166,9 @@ namespace Umbraco.Core.IO
|
||||
foreach (var dir in validDirs)
|
||||
{
|
||||
var validDir = dir;
|
||||
if (!filePath.StartsWith(MapPath(SystemDirectories.Root)))
|
||||
if (filePath.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
filePath = MapPath(filePath);
|
||||
if (!validDir.StartsWith(MapPath(SystemDirectories.Root)))
|
||||
if (validDir.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
validDir = MapPath(validDir);
|
||||
|
||||
if (filePath.StartsWith(validDir))
|
||||
@@ -198,7 +187,7 @@ namespace Umbraco.Core.IO
|
||||
/// <exception cref="FileSecurityException">The filepath is invalid.</exception>
|
||||
internal static bool ValidateEditPath(string filePath, IEnumerable<string> validDirs)
|
||||
{
|
||||
if (!VerifyEditPath(filePath, validDirs))
|
||||
if (VerifyEditPath(filePath, validDirs) == false)
|
||||
throw new FileSecurityException(String.Format("The filepath '{0}' is not within an allowed directory for this type of files", filePath.Replace(MapPath(SystemDirectories.Root), "")));
|
||||
return true;
|
||||
}
|
||||
@@ -211,7 +200,7 @@ namespace Umbraco.Core.IO
|
||||
/// <returns>A value indicating whether the filepath is valid.</returns>
|
||||
internal static bool VerifyFileExtension(string filePath, List<string> validFileExtensions)
|
||||
{
|
||||
if (!filePath.StartsWith(MapPath(SystemDirectories.Root)))
|
||||
if (filePath.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
filePath = MapPath(filePath);
|
||||
var f = new FileInfo(filePath);
|
||||
|
||||
@@ -227,7 +216,7 @@ namespace Umbraco.Core.IO
|
||||
/// <exception cref="FileSecurityException">The filepath is invalid.</exception>
|
||||
internal static bool ValidateFileExtension(string filePath, List<string> validFileExtensions)
|
||||
{
|
||||
if (!VerifyFileExtension(filePath, validFileExtensions))
|
||||
if (VerifyFileExtension(filePath, validFileExtensions) == false)
|
||||
throw new FileSecurityException(String.Format("The extension for the current file '{0}' is not of an allowed type for this editor. This is typically controlled from either the installed MacroEngines or based on configuration in /config/umbracoSettings.config", filePath.Replace(MapPath(SystemDirectories.Root), "")));
|
||||
return true;
|
||||
}
|
||||
@@ -241,7 +230,7 @@ namespace Umbraco.Core.IO
|
||||
/// <returns></returns>
|
||||
internal static string GetRootDirectorySafe()
|
||||
{
|
||||
if (!String.IsNullOrEmpty(_rootDir))
|
||||
if (string.IsNullOrEmpty(_rootDir) == false)
|
||||
{
|
||||
return _rootDir;
|
||||
}
|
||||
@@ -250,12 +239,53 @@ namespace Umbraco.Core.IO
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
var baseDirectory = Path.GetDirectoryName(path);
|
||||
_rootDir = baseDirectory.Substring(0, baseDirectory.LastIndexOf("bin") - 1);
|
||||
if (string.IsNullOrEmpty(baseDirectory))
|
||||
throw new Exception("No root directory could be resolved. Please ensure that your Umbraco solution is correctly configured.");
|
||||
|
||||
_rootDir = baseDirectory.Contains("bin")
|
||||
? baseDirectory.Substring(0, baseDirectory.LastIndexOf("bin", StringComparison.OrdinalIgnoreCase) - 1)
|
||||
: baseDirectory;
|
||||
|
||||
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.
|
||||
/// </summary>
|
||||
/// <remarks>The supplied path should be the absolute path to the root of the umbraco site.</remarks>
|
||||
/// <param name="rootPath"></param>
|
||||
internal static void SetRootDirectory(string rootPath)
|
||||
{
|
||||
_rootDir = rootPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check to see if filename passed has any special chars in it and strips them to create a safe filename. Used to overcome an issue when Umbraco is used in IE in an intranet environment.
|
||||
/// </summary>
|
||||
|
||||
@@ -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,53 +532,9 @@ 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)
|
||||
{
|
||||
// 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>
|
||||
/// Creates the xml representation for the <see cref="IContent"/> object
|
||||
/// </summary>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Web.Security;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
internal class UmbracoMembershipUser<T> : MembershipUser where T : IMembershipUser
|
||||
{
|
||||
private T _user;
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoMembershipUser{T}"/> class.
|
||||
/// </summary>
|
||||
public UmbracoMembershipUser(T user)
|
||||
{
|
||||
_user = user;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoMembershipUser{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="providerName">Name of the provider.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="providerUserKey">The provider user key.</param>
|
||||
/// <param name="email">The email.</param>
|
||||
/// <param name="passwordQuestion">The password question.</param>
|
||||
/// <param name="comment">The comment.</param>
|
||||
/// <param name="isApproved">if set to <c>true</c> [is approved].</param>
|
||||
/// <param name="isLockedOut">if set to <c>true</c> [is locked out].</param>
|
||||
/// <param name="creationDate">The creation date.</param>
|
||||
/// <param name="lastLoginDate">The last login date.</param>
|
||||
/// <param name="lastActivityDate">The last activity date.</param>
|
||||
/// <param name="lastPasswordChangedDate">The last password changed date.</param>
|
||||
/// <param name="lastLockoutDate">The last lockout date.</param>
|
||||
/// <param name="fullName">The full name.</param>
|
||||
/// <param name="language">The language.</param>
|
||||
/// <param name="userType">Type of the user.</param>
|
||||
/// <param name="user"></param>
|
||||
public UmbracoMembershipUser(string providerName, string name, object providerUserKey, string email,
|
||||
string passwordQuestion, string comment, bool isApproved, bool isLockedOut,
|
||||
DateTime creationDate, DateTime lastLoginDate, DateTime lastActivityDate, DateTime lastPasswordChangedDate,
|
||||
DateTime lastLockoutDate, string fullName, string language, IUserType userType, T user)
|
||||
: base( providerName, name, providerUserKey, email, passwordQuestion, comment, isApproved, isLockedOut,
|
||||
creationDate, lastLoginDate, lastActivityDate, lastPasswordChangedDate, lastLockoutDate)
|
||||
{
|
||||
_user = user;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -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,5 +20,8 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
[Column("SortOrder")]
|
||||
[Constraint(Name = "df_cmsContentTypeAllowedContentType_sortOrder", Default = "0")]
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public ContentTypeDto ContentTypeDto { 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;
|
||||
@@ -171,7 +170,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
public bool IsDraft
|
||||
{
|
||||
get { return _isPublished; }
|
||||
get { return _isDraft; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
get
|
||||
{
|
||||
// ensure we can
|
||||
if (!CanResolveBeforeFrozen)
|
||||
if (CanResolveBeforeFrozen == false)
|
||||
Resolution.EnsureIsFrozen();
|
||||
|
||||
// note: we apply .ToArray() to the output of CreateInstance() because that is an IEnumerable that
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
//add itself to the internal collection
|
||||
ResolverCollection.Add(this, resetAction);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -69,6 +69,12 @@ namespace Umbraco.Core.ObjectResolution
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the resolver can resolve objects before resolution is frozen.
|
||||
/// </summary>
|
||||
/// <remarks>This is false by default and is used for some special internal resolvers.</remarks>
|
||||
internal bool CanResolveBeforeFrozen { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the resolved object instance can be null.
|
||||
/// </summary>
|
||||
@@ -96,7 +102,10 @@ namespace Umbraco.Core.ObjectResolution
|
||||
{
|
||||
get
|
||||
{
|
||||
Resolution.EnsureIsFrozen();
|
||||
// ensure we can
|
||||
if (CanResolveBeforeFrozen == false)
|
||||
Resolution.EnsureIsFrozen();
|
||||
|
||||
using (new ReadLock(_lock))
|
||||
{
|
||||
if (!_canBeNull && _value == null)
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using NuGet;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Packaging
|
||||
{
|
||||
internal class DefaultPackageContext : IPackageContext
|
||||
{
|
||||
public DefaultPackageContext(Func<string, string> mapPath)
|
||||
{}
|
||||
|
||||
private readonly string _localPackageRepoFolderPath;
|
||||
private readonly string _pluginInstallFolderPath;
|
||||
private readonly Lazy<IPackageManager> _localPackageManager;
|
||||
private readonly Lazy<IPackageRepository> _localPackageRepository;
|
||||
private readonly Lazy<IPackageManager> _publicPackageManager;
|
||||
private readonly Lazy<IPackageManager> _privatePackageManager;
|
||||
private readonly Lazy<IPackageRepository> _publicPackageRepository;
|
||||
private readonly Lazy<IPackageRepository> _sprivatePackageRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local path resolver.
|
||||
/// </summary>
|
||||
public IPackagePathResolver LocalPathResolver
|
||||
{
|
||||
get { return ((PackageManager)LocalPackageManager).PathResolver; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local package manager.
|
||||
/// </summary>
|
||||
public IPackageManager LocalPackageManager
|
||||
{
|
||||
get { return _localPackageManager.Value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the public package manager.
|
||||
/// </summary>
|
||||
public IPackageManager PublicPackageManager
|
||||
{
|
||||
get { return _publicPackageManager.Value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using NuGet;
|
||||
|
||||
namespace Umbraco.Core.Packaging
|
||||
{
|
||||
internal interface IPackageContext
|
||||
{
|
||||
IPackageManager LocalPackageManager { get; }
|
||||
IPackageManager PublicPackageManager { get; }
|
||||
IPackagePathResolver LocalPathResolver { get; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
@@ -25,15 +26,25 @@ 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;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -455,9 +455,12 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
if (fieldType == typeof(decimal))
|
||||
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if(fieldType == typeof(DateTime))
|
||||
if (fieldType == typeof(DateTime))
|
||||
return "'" + EscapeParam(((DateTime)value).ToString(CultureInfo.InvariantCulture)) + "'";
|
||||
|
||||
|
||||
if (fieldType == typeof(bool))
|
||||
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
|
||||
|
||||
return ShouldQuoteValue(fieldType)
|
||||
? "'" + EscapeParam(value) + "'"
|
||||
: value.ToString();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -260,6 +269,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"))
|
||||
{
|
||||
@@ -489,5 +501,77 @@ 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.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;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
private 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
@@ -320,10 +320,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
.From<ContentTypeAllowedContentTypeDto>()
|
||||
.LeftJoin<ContentTypeDto>()
|
||||
.On<ContentTypeAllowedContentTypeDto, ContentTypeDto>(left => left.AllowedId, right => right.NodeId)
|
||||
.Where<ContentTypeAllowedContentTypeDto>(x => x.Id == id);
|
||||
|
||||
var allowedContentTypeDtos = Database.Fetch<ContentTypeAllowedContentTypeDto>(sql);
|
||||
return allowedContentTypeDtos.Select(x => new ContentTypeSort { Id = new Lazy<int>(() => x.AllowedId), SortOrder = x.SortOrder }).ToList();
|
||||
var allowedContentTypeDtos = Database.Fetch<ContentTypeAllowedContentTypeDto, ContentTypeDto>(sql);
|
||||
return allowedContentTypeDtos.Select(x => new ContentTypeSort { Id = new Lazy<int>(() => x.AllowedId), Alias = x.ContentTypeDto.Alias, SortOrder = x.SortOrder }).ToList();
|
||||
}
|
||||
|
||||
protected PropertyGroupCollection GetPropertyGroupCollection(int id, DateTime createDate, DateTime updateDate)
|
||||
|
||||
@@ -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()
|
||||
@@ -262,7 +291,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
[Column("publishedVerison")]
|
||||
public Guid PublishedVersion { get; set; }
|
||||
|
||||
[Column("newestVerison")]
|
||||
[Column("newestVersion")]
|
||||
public Guid NewestVersion { get; set; }
|
||||
|
||||
[Column("alias")]
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Profiling
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines an object for use in the application to profile operations
|
||||
/// </summary>
|
||||
internal interface IProfiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Render the UI to display the profiler
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Generally used for HTML displays
|
||||
/// </remarks>
|
||||
string Render();
|
||||
|
||||
/// <summary>
|
||||
/// Profile an operation
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Use the 'using(' syntax
|
||||
/// </remarks>
|
||||
IDisposable Step(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Start the profiler
|
||||
/// </summary>
|
||||
void Start();
|
||||
|
||||
/// <summary>
|
||||
/// Start the profiler
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// set discardResults to false when you want to abandon all profiling, this is useful for
|
||||
/// when someone is not authenticated or you want to clear the results based on some other mechanism.
|
||||
/// </remarks>
|
||||
void Stop(bool discardResults = false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Profiling
|
||||
{
|
||||
/// <summary>
|
||||
/// A profiler that outputs its results to the LogHelper
|
||||
/// </summary>
|
||||
internal class LogProfiler : IProfiler
|
||||
{
|
||||
public string Render()
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public IDisposable Step(string name)
|
||||
{
|
||||
LogHelper.Debug(typeof(LogProfiler), "Starting - " + name);
|
||||
return DisposableTimer.Start(l => LogHelper.Info(typeof(LogProfiler), () => name + " (took " + l + "ms)"));
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
//the log will alwasy be started
|
||||
}
|
||||
|
||||
public void Stop(bool discardResults = false)
|
||||
{
|
||||
//we don't need to do anything here
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using StackExchange.Profiling;
|
||||
|
||||
namespace Umbraco.Core.Profiling
|
||||
{
|
||||
public class Profiler
|
||||
{
|
||||
private static Profiler _instance;
|
||||
|
||||
private Profiler()
|
||||
{
|
||||
}
|
||||
|
||||
public string Render()
|
||||
{
|
||||
return MiniProfiler.RenderIncludes().ToString();
|
||||
}
|
||||
|
||||
public IDisposable Step(string name)
|
||||
{
|
||||
return MiniProfiler.Current.Step(name);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
MiniProfiler.Start();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
MiniProfiler.Stop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Profiler Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new Profiler();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Profiling
|
||||
{
|
||||
internal static class ProfilerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes out a step prefixed with the type
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="profiler"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
internal static IDisposable Step<T>(this IProfiler profiler, string name)
|
||||
{
|
||||
if (profiler == null) throw new ArgumentNullException("profiler");
|
||||
return profiler.Step(typeof (T), name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes out a step prefixed with the type
|
||||
/// </summary>
|
||||
/// <param name="profiler"></param>
|
||||
/// <param name="objectType"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
internal static IDisposable Step(this IProfiler profiler, Type objectType, string name)
|
||||
{
|
||||
if (profiler == null) throw new ArgumentNullException("profiler");
|
||||
if (objectType == null) throw new ArgumentNullException("objectType");
|
||||
if (name == null) throw new ArgumentNullException("name");
|
||||
return profiler.Step(string.Format("[{0}] {1}", objectType.Name, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
|
||||
namespace Umbraco.Core.Profiling
|
||||
{
|
||||
/// <summary>
|
||||
/// A resolver exposing the current profiler
|
||||
/// </summary>
|
||||
internal class ProfilerResolver : SingleObjectResolverBase<ProfilerResolver, IProfiler>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="profiler"></param>
|
||||
public ProfilerResolver(IProfiler profiler)
|
||||
: base(profiler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method allowing to change the profiler during startup
|
||||
/// </summary>
|
||||
/// <param name="profiler"></param>
|
||||
internal void SetProfiler(IProfiler profiler)
|
||||
{
|
||||
Value = profiler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current profiler
|
||||
/// </summary>
|
||||
public IProfiler Profiler
|
||||
{
|
||||
get { return Value; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using StackExchange.Profiling;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Profiling
|
||||
{
|
||||
/// <summary>
|
||||
/// A profiler used for web based activity based on the MiniProfiler framework
|
||||
/// </summary>
|
||||
internal class WebProfiler : IProfiler
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Binds to application events to enable the MiniProfiler
|
||||
/// </remarks>
|
||||
internal WebProfiler()
|
||||
{
|
||||
UmbracoApplicationBase.ApplicationInit += UmbracoApplicationApplicationInit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the Init event o fthe UmbracoApplication which allows us to subscribe to the HttpApplication events
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void UmbracoApplicationApplicationInit(object sender, EventArgs e)
|
||||
{
|
||||
var app = sender as HttpApplication;
|
||||
if (app == null) return;
|
||||
|
||||
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High)
|
||||
{
|
||||
//If we don't have a high enough trust level we cannot bind to the events
|
||||
LogHelper.Info<WebProfiler>("Cannot start the WebProfiler since the application is running in Medium trust");
|
||||
}
|
||||
else
|
||||
{
|
||||
app.BeginRequest += UmbracoApplicationBeginRequest;
|
||||
app.EndRequest += UmbracoApplicationEndRequest;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the begin request event
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <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)
|
||||
{
|
||||
//stop the profiler
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the end request event
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <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)
|
||||
{
|
||||
//start the profiler
|
||||
Start();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Render the UI to display the profiler
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Generally used for HTML displays
|
||||
/// </remarks>
|
||||
public string Render()
|
||||
{
|
||||
return MiniProfiler.RenderIncludes().ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Profile a step
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Use the 'using(' syntax
|
||||
/// </remarks>
|
||||
public IDisposable Step(string name)
|
||||
{
|
||||
if (GlobalSettings.DebugMode == false) return null;
|
||||
|
||||
return MiniProfiler.Current.Step(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the profiler
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
if (GlobalSettings.DebugMode == false) return;
|
||||
//will not run in medium trust
|
||||
if (SystemUtilities.GetCurrentTrustLevel() < AspNetHostingPermissionLevel.High) return;
|
||||
|
||||
MiniProfiler.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the profiler
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// set discardResults to false when you want to abandon all profiling, this is useful for
|
||||
/// when someone is not authenticated or you want to clear the results based on some other mechanism.
|
||||
/// </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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the request object from the app instance if it is available
|
||||
/// </summary>
|
||||
/// <param name="sender">The application object</param>
|
||||
/// <returns></returns>
|
||||
private Attempt<HttpRequestBase> TryGetRequest(object sender)
|
||||
{
|
||||
var app = sender as HttpApplication;
|
||||
if (app == null) return Attempt<HttpRequestBase>.False;
|
||||
|
||||
try
|
||||
{
|
||||
var req = app.Request;
|
||||
return new Attempt<HttpRequestBase>(true, new HttpRequestWrapper(req));
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
return new Attempt<HttpRequestBase>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -42,4 +42,5 @@ using System.Security.Permissions;
|
||||
[assembly: InternalsVisibleTo("Umbraco.Courier.Persistence")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Concorde.Sync")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Belle")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Belle")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")]
|
||||
@@ -1,48 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a PropertyEditor
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
internal sealed class PropertyEditorAttribute : Attribute
|
||||
{
|
||||
public PropertyEditorAttribute(string id, string alias, string name)
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(id, "id");
|
||||
Mandate.ParameterNotNullOrEmpty(alias, "alias");
|
||||
Mandate.ParameterNotNullOrEmpty(name, "name");
|
||||
|
||||
Id = Guid.Parse(id);
|
||||
Alias = alias;
|
||||
Name = name;
|
||||
|
||||
IsContentPropertyEditor = true;
|
||||
}
|
||||
|
||||
public Guid Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the alias.
|
||||
/// </summary>
|
||||
/// <value>The alias.</value>
|
||||
public string Alias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flag determining if this property editor is used to edit content
|
||||
/// </summary>
|
||||
public bool IsContentPropertyEditor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flag determining if this property editor is used to edit parameters
|
||||
/// </summary>
|
||||
public bool IsParameterEditor { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute determining whether or not to hide/show the label of a property
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This directly affects the meta data property: HideSurroundingHtml
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
|
||||
internal class ShowLabelAttribute : Attribute
|
||||
{
|
||||
public ShowLabelAttribute(bool show)
|
||||
{
|
||||
ShowLabel = show;
|
||||
}
|
||||
|
||||
public bool ShowLabel { get; private set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// A class representing a blank, null or empty pre-value editor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class can be used for Property Editors who do not define a Pre value editor
|
||||
/// </remarks>
|
||||
internal class BlankPreValueModel : PreValueModel
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
internal abstract class EditorModel<TValueModel> where TValueModel : IValueModel, new()
|
||||
{
|
||||
protected EditorModel()
|
||||
{
|
||||
// Set the UI Elements collection to an empty list
|
||||
//UIElements = new List<UIElement>();
|
||||
}
|
||||
|
||||
[ReadOnly(true)]
|
||||
public virtual bool ShowUmbracoLabel
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of UI Elements for the property editor.
|
||||
/// </summary>
|
||||
//[ScaffoldColumn(false)]
|
||||
//public virtual IList<UIElement> UIElements { get; protected internal set; }
|
||||
|
||||
private ModelMetadata _modelMetadata;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the meta data for the current editor model
|
||||
/// </summary>
|
||||
protected internal ModelMetadata MetaData
|
||||
{
|
||||
get
|
||||
{
|
||||
return _modelMetadata ?? (_modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => this, GetType()));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the serialized value for the PropertyEditor
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual IDictionary<string, object> GetSerializedValue()
|
||||
{
|
||||
var editableProps = MetaData.Properties.Where(x => x.ShowForEdit && !x.IsReadOnly);
|
||||
var d = new Dictionary<string, object>();
|
||||
foreach (var p in editableProps)
|
||||
{
|
||||
//by default, we will not support complex modelled properties, developers will need to override
|
||||
//the GetSerializedValue method if they need support for this.
|
||||
if (p.IsComplexType)
|
||||
{
|
||||
//TODO: We should magically support this
|
||||
throw new NotSupportedException("The default serialization implementation of EditorModel does not support properties that are complex models");
|
||||
}
|
||||
|
||||
d.Add(p.PropertyName, p.Model);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
public virtual void SetModelValues(IDictionary<string, object> serializedVal)
|
||||
{
|
||||
if (serializedVal == null || serializedVal.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var modelProperties = GetType().GetProperties();
|
||||
|
||||
var editableProps = MetaData.Properties.Where(x => x.ShowForEdit && !x.IsReadOnly);
|
||||
|
||||
foreach (var i in serializedVal)
|
||||
{
|
||||
if (i.Value == null)
|
||||
continue;
|
||||
|
||||
//get the property with the name
|
||||
var prop = editableProps.Where(x => x.PropertyName == i.Key).SingleOrDefault();
|
||||
if (prop != null)
|
||||
{
|
||||
//set the property value
|
||||
var toConverter = TypeDescriptor.GetConverter(prop.ModelType);
|
||||
if (toConverter != null)
|
||||
{
|
||||
//get the model property for this property meta data to set its value
|
||||
var propInfo = modelProperties.Where(x => x.Name == prop.PropertyName).Single();
|
||||
object convertedVal;
|
||||
|
||||
//if value is already of the same type, just use the current value, otherwise try and convert it
|
||||
if (i.Value.GetType() == propInfo.PropertyType)
|
||||
{
|
||||
convertedVal = i.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
convertedVal = toConverter.ConvertFrom(i.Value);
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
//this occurs when the converter doesn't know how, so we can try the opposite way as a last ditch effort
|
||||
var fromConverter = TypeDescriptor.GetConverter(i.Value.GetType());
|
||||
if (fromConverter == null)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
convertedVal = fromConverter.ConvertTo(i.Value, prop.ModelType);
|
||||
|
||||
}
|
||||
}
|
||||
propInfo.SetValue(this, convertedVal, null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public virtual TValueModel GetValueModel()
|
||||
{
|
||||
var editableProps = MetaData.Properties.Where(x => x.ShowForEdit && !x.IsReadOnly);
|
||||
var d = new TValueModel();
|
||||
foreach (var p in editableProps)
|
||||
{
|
||||
//by default, we will not support complex modelled properties, developers will need to override
|
||||
//the GetSerializedValue method if they need support for this.
|
||||
//TODO Test if this exception is still valid
|
||||
if (p.IsComplexType)
|
||||
{
|
||||
throw new NotSupportedException("The default serialization implementation of EditorModel does not support properties that are complex models");
|
||||
}
|
||||
|
||||
var property = d.GetType().GetProperty(p.PropertyName);
|
||||
if(property != null)
|
||||
{
|
||||
property.SetValue(d, p.Model, null);
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// An abstract class representing the model to render a Property Editor's content editor with PreValues
|
||||
/// </summary>
|
||||
/// <typeparam name="TPreValueModel">The type of the PreValue model.</typeparam>
|
||||
/// <typeparam name="TValueModel"> </typeparam>
|
||||
internal abstract class EditorModel<TValueModel, TPreValueModel> : EditorModel<TValueModel>
|
||||
where TValueModel : IValueModel, new()
|
||||
where TPreValueModel : PreValueModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="preValues">The pre value options used to construct the editor</param>
|
||||
protected EditorModel(TPreValueModel preValues)
|
||||
{
|
||||
PreValueModel = preValues;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The pre value options used to configure the editor
|
||||
/// </summary>
|
||||
/// <value>The pre value model.</value>
|
||||
public TPreValueModel PreValueModel { get; protected internal set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
internal interface IValueModel
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// A class representing a single value of a Pre-Value editor to be saved
|
||||
/// </summary>
|
||||
internal class PreValueDefinition
|
||||
{
|
||||
public PreValueDefinition(string propertyName, Type modeType, object modelValue)
|
||||
{
|
||||
ModelType = modeType;
|
||||
PropertyName = propertyName;
|
||||
ModelValue = modelValue;
|
||||
}
|
||||
|
||||
public Type ModelType { get; private set; }
|
||||
public string PropertyName { get; private set; }
|
||||
public object ModelValue { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract class representing a Property Editor's model to render it's Pre value editor
|
||||
/// </summary>
|
||||
internal abstract class PreValueModel
|
||||
{
|
||||
protected virtual IEnumerable<PreValueDefinition> GetValueDefinitions()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public virtual string GetSerializedValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected virtual void SetModelPropertyValue(PreValueDefinition def, Action<object> setProperty)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public virtual void SetModelValues(string serializedVal)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.PropertyEditors.Attributes;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
internal abstract class PropertyEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor for a PropertyEditor
|
||||
/// </summary>
|
||||
protected PropertyEditor()
|
||||
{
|
||||
//Locate the metadata attribute
|
||||
var docTypeAttributes = GetType()
|
||||
.GetCustomAttributes(typeof(PropertyEditorAttribute), true)
|
||||
.OfType<PropertyEditorAttribute>();
|
||||
|
||||
if (!docTypeAttributes.Any())
|
||||
throw new InvalidOperationException(
|
||||
string.Format("The PropertyEditor of type {0} is missing the {1} attribute", GetType().FullName,
|
||||
typeof(PropertyEditorAttribute).FullName));
|
||||
|
||||
//assign the properties of this object to those of the metadata attribute
|
||||
var attr = docTypeAttributes.First();
|
||||
Id = attr.Id;
|
||||
Name = attr.Name;
|
||||
Alias = attr.Alias;
|
||||
}
|
||||
|
||||
public virtual Guid Id { get; protected set; }
|
||||
|
||||
public virtual string Name { get; protected set; }
|
||||
|
||||
public virtual string Alias { get; protected set; }
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract class that all Property editors should inherit from
|
||||
/// </summary>
|
||||
/// <typeparam name="TEditorModel"></typeparam>
|
||||
/// <typeparam name="TPreValueModel"></typeparam>
|
||||
/// <typeparam name="TValueModel"> </typeparam>
|
||||
internal abstract class PropertyEditor<TValueModel, TEditorModel, TPreValueModel> : PropertyEditor
|
||||
where TValueModel : IValueModel, new()
|
||||
where TEditorModel : EditorModel<TValueModel>
|
||||
where TPreValueModel : PreValueModel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns the editor model to be used for the property editor
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract TEditorModel CreateEditorModel(TPreValueModel preValues);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the editor model to be used for the prevalue editor
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract TPreValueModel CreatePreValueEditorModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract class that Property editors should inherit from that don't require a pre-value editor
|
||||
/// </summary>
|
||||
/// <typeparam name="TEditorModel"></typeparam>
|
||||
/// <typeparam name="TValueModel"> </typeparam>
|
||||
internal abstract class PropertyEditor<TValueModel, TEditorModel> : PropertyEditor<TValueModel, TEditorModel, BlankPreValueModel>
|
||||
where TValueModel : IValueModel, new()
|
||||
where TEditorModel : EditorModel<TValueModel>
|
||||
{
|
||||
public override BlankPreValueModel CreatePreValueEditorModel()
|
||||
{
|
||||
return new BlankPreValueModel();
|
||||
}
|
||||
|
||||
public sealed override TEditorModel CreateEditorModel(BlankPreValueModel preValues)
|
||||
{
|
||||
return CreateEditorModel();
|
||||
}
|
||||
|
||||
public abstract TEditorModel CreateEditorModel();
|
||||
}
|
||||
}
|
||||
@@ -60,8 +60,13 @@ namespace Umbraco.Core.Services
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
|
||||
/// that this Content is based on.
|
||||
/// that this Content should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that using this method will simply return a new IContent without any identity
|
||||
/// as it has not yet been persisted. It is intended as a shortcut to creating new content objects
|
||||
/// that does not invoke a save operation against the database.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Content object</param>
|
||||
/// <param name="parentId">Id of Parent for the new Content</param>
|
||||
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
|
||||
@@ -70,7 +75,7 @@ namespace Umbraco.Core.Services
|
||||
public IContent CreateContent(string name, int parentId, string contentTypeAlias, int userId = 0)
|
||||
{
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parentId, contentType); ;
|
||||
var content = new Content(name, parentId, contentType);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parentId), this))
|
||||
{
|
||||
@@ -90,8 +95,13 @@ namespace Umbraco.Core.Services
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
|
||||
/// that this Content is based on.
|
||||
/// that this Content should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that using this method will simply return a new IContent without any identity
|
||||
/// as it has not yet been persisted. It is intended as a shortcut to creating new content objects
|
||||
/// that does not invoke a save operation against the database.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Content object</param>
|
||||
/// <param name="parent">Parent <see cref="IContent"/> object for the new Content</param>
|
||||
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
|
||||
@@ -118,6 +128,86 @@ namespace Umbraco.Core.Services
|
||||
return content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and saves an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
|
||||
/// that this Content should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns an <see cref="IContent"/> object that has been persisted to the database
|
||||
/// and therefor has an identity.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Content object</param>
|
||||
/// <param name="parentId">Id of Parent for the new Content</param>
|
||||
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
|
||||
/// <param name="userId">Optional id of the user creating the content</param>
|
||||
/// <returns><see cref="IContent"/></returns>
|
||||
public IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0)
|
||||
{
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parentId, contentType);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parentId), this))
|
||||
{
|
||||
content.WasCancelled = true;
|
||||
return content;
|
||||
}
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
content.CreatorId = userId;
|
||||
content.WriterId = userId;
|
||||
repository.AddOrUpdate(content);
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parentId), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", content.CreatorId, content.Id);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and saves an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
|
||||
/// that this Content should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns an <see cref="IContent"/> object that has been persisted to the database
|
||||
/// and therefor has an identity.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Content object</param>
|
||||
/// <param name="parent">Parent <see cref="IContent"/> object for the new Content</param>
|
||||
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
|
||||
/// <param name="userId">Optional id of the user creating the content</param>
|
||||
/// <returns><see cref="IContent"/></returns>
|
||||
public IContent CreateContentWithIdentity(string name, IContent parent, string contentTypeAlias, int userId = 0)
|
||||
{
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parent, contentType);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parent), this))
|
||||
{
|
||||
content.WasCancelled = true;
|
||||
return content;
|
||||
}
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
content.CreatorId = userId;
|
||||
content.WriterId = userId;
|
||||
repository.AddOrUpdate(content);
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parent), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", content.CreatorId, content.Id);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an <see cref="IContent"/> object by Id
|
||||
/// </summary>
|
||||
@@ -243,7 +333,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;
|
||||
}
|
||||
@@ -946,7 +1036,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();
|
||||
|
||||
@@ -1021,7 +1114,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);
|
||||
@@ -1082,6 +1175,7 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
content.WriterId = userId;
|
||||
content.CreatorId = userId;
|
||||
content.ChangePublishedState(PublishedState.Unpublished);
|
||||
|
||||
repository.AddOrUpdate(content);
|
||||
uow.Commit();
|
||||
@@ -1094,6 +1188,92 @@ namespace Umbraco.Core.Services
|
||||
return content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts a collection of <see cref="IContent"/> objects by updating the SortOrder according
|
||||
/// to the ordering of items in the passed in <see cref="IEnumerable{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Using this method will ensure that the Published-state is maintained upon sorting
|
||||
/// so the cache is updated accordingly - as needed.
|
||||
/// </remarks>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="raiseEvents"></param>
|
||||
/// <returns>True if sorting succeeded, otherwise False</returns>
|
||||
public bool Sort(IEnumerable<IContent> items, int userId = 0, bool raiseEvents = true)
|
||||
{
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IContent>(items), this))
|
||||
return false;
|
||||
}
|
||||
|
||||
var shouldBePublished = new List<IContent>();
|
||||
var shouldBeSaved = new List<IContent>();
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var content in items)
|
||||
{
|
||||
//If the current sort order equals that of the content
|
||||
//we don't need to update it, so just increment the sort order
|
||||
//and continue.
|
||||
if (content.SortOrder == i)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
content.SortOrder = i;
|
||||
content.WriterId = userId;
|
||||
i++;
|
||||
|
||||
if (content.Published)
|
||||
{
|
||||
var published = _publishingStrategy.Publish(content, userId);
|
||||
shouldBePublished.Add(content);
|
||||
}
|
||||
else
|
||||
shouldBeSaved.Add(content);
|
||||
|
||||
repository.AddOrUpdate(content);
|
||||
}
|
||||
|
||||
uow.Commit();
|
||||
|
||||
foreach (var content in shouldBeSaved)
|
||||
{
|
||||
//Create and Save PreviewXml DTO
|
||||
var xml = content.ToXml();
|
||||
CreateAndSavePreviewXml(xml, content.Id, content.Version, uow.Database);
|
||||
}
|
||||
|
||||
foreach (var content in shouldBePublished)
|
||||
{
|
||||
//Create and Save PreviewXml DTO
|
||||
var xml = content.ToXml();
|
||||
CreateAndSavePreviewXml(xml, content.Id, content.Version, uow.Database);
|
||||
//Create and Save ContentXml DTO
|
||||
CreateAndSaveContentXml(xml, content.Id, uow.Database);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(new SaveEventArgs<IContent>(items, false), this);
|
||||
|
||||
if(shouldBePublished.Any())
|
||||
_publishingStrategy.PublishingFinalized(shouldBePublished, false);
|
||||
|
||||
Audit.Add(AuditTypes.Sort, "Sorting content performed by user", userId, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
/// <summary>
|
||||
@@ -1275,11 +1455,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);
|
||||
@@ -1369,24 +1548,9 @@ namespace Umbraco.Core.Services
|
||||
var publishStatus = new PublishStatus(content, PublishStatusType.Success); //initially set to success
|
||||
|
||||
//Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published
|
||||
if (content.ParentId != -1 && content.ParentId != -20 && IsPublishable(content) == false)
|
||||
{
|
||||
LogHelper.Info<ContentService>(
|
||||
string.Format(
|
||||
"Content '{0}' with Id '{1}' could not be published because its parent is not published.",
|
||||
content.Name, content.Id));
|
||||
publishStatus.StatusType = PublishStatusType.FailedPathNotPublished;
|
||||
}
|
||||
|
||||
publishStatus.StatusType = CheckAndLogIsPublishable(content);
|
||||
//Content contains invalid property values and can therefore not be published - fire event?
|
||||
if (content.IsValid() == false)
|
||||
{
|
||||
LogHelper.Info<ContentService>(
|
||||
string.Format(
|
||||
"Content '{0}' with Id '{1}' could not be published because of invalid properties.",
|
||||
content.Name, content.Id));
|
||||
publishStatus.StatusType = PublishStatusType.FailedContentInvalid;
|
||||
}
|
||||
publishStatus.StatusType = CheckAndLogIsValid(content);
|
||||
|
||||
//if we're still successful, then publish using the strategy
|
||||
if (publishStatus.StatusType == PublishStatusType.Success)
|
||||
@@ -1413,37 +1577,12 @@ namespace Umbraco.Core.Services
|
||||
|
||||
var xml = content.ToXml();
|
||||
//Preview Xml
|
||||
var previewPoco = new PreviewXmlDto
|
||||
{
|
||||
NodeId = content.Id,
|
||||
Timestamp = DateTime.Now,
|
||||
VersionId = content.Version,
|
||||
Xml = xml.ToString(SaveOptions.None)
|
||||
};
|
||||
var previewExists =
|
||||
uow.Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version",
|
||||
new { Id = content.Id, Version = content.Version }) != 0;
|
||||
int previewResult = previewExists
|
||||
? uow.Database.Update<PreviewXmlDto>(
|
||||
"SET xml = @Xml, timestamp = @Timestamp WHERE nodeId = @Id AND versionId = @Version",
|
||||
new
|
||||
{
|
||||
Xml = previewPoco.Xml,
|
||||
Timestamp = previewPoco.Timestamp,
|
||||
Id = previewPoco.NodeId,
|
||||
Version = previewPoco.VersionId
|
||||
})
|
||||
: Convert.ToInt32(uow.Database.Insert(previewPoco));
|
||||
CreateAndSavePreviewXml(xml, content.Id, content.Version, uow.Database);
|
||||
|
||||
if (published)
|
||||
{
|
||||
//Content Xml
|
||||
var contentPoco = new ContentXmlDto { NodeId = content.Id, Xml = xml.ToString(SaveOptions.None) };
|
||||
var contentExists = uow.Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = content.Id }) != 0;
|
||||
int contentResult = contentExists
|
||||
? uow.Database.Update(contentPoco)
|
||||
: Convert.ToInt32(uow.Database.Insert(contentPoco));
|
||||
|
||||
CreateAndSaveContentXml(xml, content.Id, uow.Database);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1501,27 +1640,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
//Preview Xml
|
||||
var xml = content.ToXml();
|
||||
var previewPoco = new PreviewXmlDto
|
||||
{
|
||||
NodeId = content.Id,
|
||||
Timestamp = DateTime.Now,
|
||||
VersionId = content.Version,
|
||||
Xml = xml.ToString(SaveOptions.None)
|
||||
};
|
||||
var previewExists =
|
||||
uow.Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version",
|
||||
new { Id = content.Id, Version = content.Version }) != 0;
|
||||
int previewResult = previewExists
|
||||
? uow.Database.Update<PreviewXmlDto>(
|
||||
"SET xml = @Xml, timestamp = @Timestamp WHERE nodeId = @Id AND versionId = @Version",
|
||||
new
|
||||
{
|
||||
Xml = previewPoco.Xml,
|
||||
Timestamp = previewPoco.Timestamp,
|
||||
Id = previewPoco.NodeId,
|
||||
Version = previewPoco.VersionId
|
||||
})
|
||||
: Convert.ToInt32(uow.Database.Insert(previewPoco));
|
||||
CreateAndSavePreviewXml(xml, content.Id, content.Version, uow.Database);
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
@@ -1565,6 +1684,68 @@ namespace Umbraco.Core.Services
|
||||
return true;
|
||||
}
|
||||
|
||||
private PublishStatusType CheckAndLogIsPublishable(IContent content)
|
||||
{
|
||||
//Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published
|
||||
if (content.ParentId != -1 && content.ParentId != -20 && IsPublishable(content) == false)
|
||||
{
|
||||
LogHelper.Info<ContentService>(
|
||||
string.Format(
|
||||
"Content '{0}' with Id '{1}' could not be published because its parent is not published.",
|
||||
content.Name, content.Id));
|
||||
return PublishStatusType.FailedPathNotPublished;
|
||||
}
|
||||
|
||||
return PublishStatusType.Success;
|
||||
}
|
||||
|
||||
private PublishStatusType CheckAndLogIsValid(IContent content)
|
||||
{
|
||||
//Content contains invalid property values and can therefore not be published - fire event?
|
||||
if (content.IsValid() == false)
|
||||
{
|
||||
LogHelper.Info<ContentService>(
|
||||
string.Format(
|
||||
"Content '{0}' with Id '{1}' could not be published because of invalid properties.",
|
||||
content.Name, content.Id));
|
||||
return PublishStatusType.FailedContentInvalid;
|
||||
}
|
||||
|
||||
return PublishStatusType.Success;
|
||||
}
|
||||
|
||||
private void CreateAndSavePreviewXml(XElement xml, int id, Guid version, UmbracoDatabase db)
|
||||
{
|
||||
var previewPoco = new PreviewXmlDto
|
||||
{
|
||||
NodeId = id,
|
||||
Timestamp = DateTime.Now,
|
||||
VersionId = version,
|
||||
Xml = xml.ToString(SaveOptions.None)
|
||||
};
|
||||
var previewExists =
|
||||
db.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version",
|
||||
new { Id = id, Version = version }) != 0;
|
||||
int previewResult = previewExists
|
||||
? db.Update<PreviewXmlDto>(
|
||||
"SET xml = @Xml, timestamp = @Timestamp WHERE nodeId = @Id AND versionId = @Version",
|
||||
new
|
||||
{
|
||||
Xml = previewPoco.Xml,
|
||||
Timestamp = previewPoco.Timestamp,
|
||||
Id = previewPoco.NodeId,
|
||||
Version = previewPoco.VersionId
|
||||
})
|
||||
: Convert.ToInt32(db.Insert(previewPoco));
|
||||
}
|
||||
|
||||
private void CreateAndSaveContentXml(XElement xml, int id, UmbracoDatabase db)
|
||||
{
|
||||
var contentPoco = new ContentXmlDto { NodeId = id, Xml = xml.ToString(SaveOptions.None) };
|
||||
var contentExists = db.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = id }) != 0;
|
||||
int contentResult = contentExists ? db.Update(contentPoco) : Convert.ToInt32(db.Insert(contentPoco));
|
||||
}
|
||||
|
||||
private IContentType FindContentTypeByAlias(string contentTypeAlias)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(_uowProvider.GetUnitOfWork()))
|
||||
@@ -1572,7 +1753,7 @@ namespace Umbraco.Core.Services
|
||||
var query = Query<IContentType>.Builder.Where(x => x.Alias == contentTypeAlias);
|
||||
var types = repository.GetByQuery(query);
|
||||
|
||||
if (!types.Any())
|
||||
if (types.Any() == false)
|
||||
throw new Exception(
|
||||
string.Format("No ContentType matching the passed in Alias: '{0}' was found",
|
||||
contentTypeAlias));
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -12,8 +11,13 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
|
||||
/// that this Content is based on.
|
||||
/// that this Content should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that using this method will simply return a new IContent without any identity
|
||||
/// as it has not yet been persisted. It is intended as a shortcut to creating new content objects
|
||||
/// that does not invoke a save operation against the database.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Content object</param>
|
||||
/// <param name="parentId">Id of Parent for the new Content</param>
|
||||
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
|
||||
@@ -23,8 +27,13 @@ namespace Umbraco.Core.Services
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
|
||||
/// that this Content is based on.
|
||||
/// that this Content should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that using this method will simply return a new IContent without any identity
|
||||
/// as it has not yet been persisted. It is intended as a shortcut to creating new content objects
|
||||
/// that does not invoke a save operation against the database.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Content object</param>
|
||||
/// <param name="parent">Parent <see cref="IContent"/> object for the new Content</param>
|
||||
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
|
||||
@@ -302,6 +311,18 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="content"><see cref="IContent"/> to retrieve ancestors for</param>
|
||||
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
|
||||
IEnumerable<IContent> GetAncestors(IContent content);
|
||||
/// Sorts a collection of <see cref="IContent"/> objects by updating the SortOrder according
|
||||
/// to the ordering of items in the passed in <see cref="IEnumerable{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Using this method will ensure that the Published-state is maintained upon sorting
|
||||
/// so the cache is updated accordingly - as needed.
|
||||
/// </remarks>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="raiseEvents"></param>
|
||||
/// <returns>True if sorting succeeded, otherwise False</returns>
|
||||
bool Sort(IEnumerable<IContent> items, int userId = 0, bool raiseEvents = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent of the current content as an <see cref="IContent"/> item.
|
||||
@@ -316,5 +337,33 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="content"><see cref="IContent"/> to retrieve the parent from</param>
|
||||
/// <returns>Parent <see cref="IContent"/> object</returns>
|
||||
IContent GetParent(IContent content);
|
||||
/// Creates and saves an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
|
||||
/// that this Content should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns an <see cref="IContent"/> object that has been persisted to the database
|
||||
/// and therefor has an identity.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Content object</param>
|
||||
/// <param name="parent">Parent <see cref="IContent"/> object for the new Content</param>
|
||||
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
|
||||
/// <param name="userId">Optional id of the user creating the content</param>
|
||||
/// <returns><see cref="IContent"/></returns>
|
||||
IContent CreateContentWithIdentity(string name, IContent parent, string contentTypeAlias, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and saves an <see cref="IContent"/> object using the alias of the <see cref="IContentType"/>
|
||||
/// that this Content should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns an <see cref="IContent"/> object that has been persisted to the database
|
||||
/// and therefor has an identity.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Content object</param>
|
||||
/// <param name="parentId">Id of Parent for the new Content</param>
|
||||
/// <param name="contentTypeAlias">Alias of the <see cref="IContentType"/></param>
|
||||
/// <param name="userId">Optional id of the user creating the content</param>
|
||||
/// <returns><see cref="IContent"/></returns>
|
||||
IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0);
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,13 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
|
||||
/// that this Media is based on.
|
||||
/// that this Media should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that using this method will simply return a new IMedia without any identity
|
||||
/// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
|
||||
/// that does not invoke a save operation against the database.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Media object</param>
|
||||
/// <param name="parentId">Id of Parent for the new Media item</param>
|
||||
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
|
||||
@@ -22,8 +27,13 @@ namespace Umbraco.Core.Services
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
|
||||
/// that this Media is based on.
|
||||
/// that this Media should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that using this method will simply return a new IMedia without any identity
|
||||
/// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
|
||||
/// that does not invoke a save operation against the database.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Media object</param>
|
||||
/// <param name="parent">Parent <see cref="IMedia"/> for the new Media item</param>
|
||||
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
|
||||
@@ -184,7 +194,7 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="mediaPath">Path of the media item to retreive (for example: /media/1024/koala_403x328.jpg)</param>
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
IMedia GetMediaByPath(string mediaPath);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IMedia"/> objects, which are ancestors of the current media.
|
||||
/// </summary>
|
||||
@@ -219,5 +229,45 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="media"><see cref="IMedia"/> to retrieve the parent from</param>
|
||||
/// <returns>Parent <see cref="IMedia"/> object</returns>
|
||||
IMedia GetParent(IMedia media);
|
||||
|
||||
/// <summary>
|
||||
/// Sorts a collection of <see cref="IMedia"/> objects by updating the SortOrder according
|
||||
/// to the ordering of items in the passed in <see cref="IEnumerable{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="raiseEvents"></param>
|
||||
/// <returns>True if sorting succeeded, otherwise False</returns>
|
||||
bool Sort(IEnumerable<IMedia> items, int userId = 0, bool raiseEvents = true);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
|
||||
/// that this Media should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns an <see cref="IMedia"/> object that has been persisted to the database
|
||||
/// and therefor has an identity.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Media object</param>
|
||||
/// <param name="parent">Parent <see cref="IMedia"/> for the new Media item</param>
|
||||
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
|
||||
/// <param name="userId">Optional id of the user creating the media item</param>
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTypeAlias, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
|
||||
/// that this Media should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns an <see cref="IMedia"/> object that has been persisted to the database
|
||||
/// and therefor has an identity.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Media object</param>
|
||||
/// <param name="parentId">Id of Parent for the new Media item</param>
|
||||
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
|
||||
/// <param name="userId">Optional id of the user creating the media item</param>
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
IMedia CreateMediaWithIdentity(string name, int parentId, string mediaTypeAlias, int userId = 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the MemberService, which is an easy access to operations involving (umbraco) members.
|
||||
/// </summary>
|
||||
internal interface IMemberService : IMembershipMemberService
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines part of the MemberService, 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 IMembershipMemberService : IService
|
||||
{}
|
||||
}
|
||||
@@ -4,31 +4,40 @@ using Umbraco.Core.Models.Membership;
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the UserService, which is an easy access to operations involving <see cref="IProfile"/> and eventually Users and Members.
|
||||
/// Defines the UserService, which is an easy access to operations involving <see cref="IProfile"/> and eventually Users.
|
||||
/// </summary>
|
||||
internal interface IUserService : IService
|
||||
internal interface IUserService : IMembershipUserService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an <see cref="IProfile"/> for the current BackOffice User
|
||||
/// </summary>
|
||||
/// <param name="httpContext">HttpContext to fetch the user through</param>
|
||||
/// <returns><see cref="IProfile"/> containing the Name and Id of the logged in BackOffice User</returns>
|
||||
IProfile GetCurrentBackOfficeUser(HttpContextBase httpContext);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an <see cref="IProfile"/> for the current BackOffice User.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Requests the current HttpContext, so this method will only work in a web context.
|
||||
/// </remarks>
|
||||
/// <returns><see cref="IProfile"/> containing the Name and Id of the logged in BackOffice User</returns>
|
||||
IProfile GetCurrentBackOfficeUser();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IProfile by User Id.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the User to retrieve</param>
|
||||
/// <returns><see cref="IProfile"/></returns>
|
||||
IProfile GetProfileById(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IUserType by its Alias
|
||||
/// </summary>
|
||||
/// <param name="alias">Alias of the UserType to retrieve</param>
|
||||
/// <returns><see cref="IUserType"/></returns>
|
||||
IUserType GetUserTypeByAlias(string alias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IUserType by its Name
|
||||
/// </summary>
|
||||
/// <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 = "");
|
||||
}
|
||||
}
|
||||
@@ -38,8 +38,13 @@ namespace Umbraco.Core.Services
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
|
||||
/// that this Media is based on.
|
||||
/// that this Media should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that using this method will simply return a new IMedia without any identity
|
||||
/// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
|
||||
/// that does not invoke a save operation against the database.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Media object</param>
|
||||
/// <param name="parentId">Id of Parent for the new Media item</param>
|
||||
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
|
||||
@@ -47,25 +52,7 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
public IMedia CreateMedia(string name, int parentId, string mediaTypeAlias, int userId = 0)
|
||||
{
|
||||
IMediaType mediaType;
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
var query = Query<IMediaType>.Builder.Where(x => x.Alias == mediaTypeAlias);
|
||||
var mediaTypes = repository.GetByQuery(query);
|
||||
|
||||
if (!mediaTypes.Any())
|
||||
throw new Exception(string.Format("No MediaType matching the passed in Alias: '{0}' was found",
|
||||
mediaTypeAlias));
|
||||
|
||||
mediaType = mediaTypes.First();
|
||||
|
||||
if (mediaType == null)
|
||||
throw new Exception(string.Format("MediaType matching the passed in Alias: '{0}' was null",
|
||||
mediaTypeAlias));
|
||||
}
|
||||
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parentId, mediaType);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId), this))
|
||||
@@ -85,8 +72,13 @@ namespace Umbraco.Core.Services
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
|
||||
/// that this Media is based on.
|
||||
/// that this Media should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that using this method will simply return a new IMedia without any identity
|
||||
/// as it has not yet been persisted. It is intended as a shortcut to creating new media objects
|
||||
/// that does not invoke a save operation against the database.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Media object</param>
|
||||
/// <param name="parent">Parent <see cref="IMedia"/> for the new Media item</param>
|
||||
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
|
||||
@@ -94,25 +86,7 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
public IMedia CreateMedia(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
|
||||
{
|
||||
IMediaType mediaType;
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
var query = Query<IMediaType>.Builder.Where(x => x.Alias == mediaTypeAlias);
|
||||
var mediaTypes = repository.GetByQuery(query);
|
||||
|
||||
if (!mediaTypes.Any())
|
||||
throw new Exception(string.Format("No MediaType matching the passed in Alias: '{0}' was found",
|
||||
mediaTypeAlias));
|
||||
|
||||
mediaType = mediaTypes.First();
|
||||
|
||||
if (mediaType == null)
|
||||
throw new Exception(string.Format("MediaType matching the passed in Alias: '{0}' was null",
|
||||
mediaTypeAlias));
|
||||
}
|
||||
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parent, mediaType);
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parent), this))
|
||||
{
|
||||
@@ -129,6 +103,94 @@ namespace Umbraco.Core.Services
|
||||
return media;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
|
||||
/// that this Media should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns an <see cref="IMedia"/> object that has been persisted to the database
|
||||
/// and therefor has an identity.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Media object</param>
|
||||
/// <param name="parentId">Id of Parent for the new Media item</param>
|
||||
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
|
||||
/// <param name="userId">Optional id of the user creating the media item</param>
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
public IMedia CreateMediaWithIdentity(string name, int parentId, string mediaTypeAlias, int userId = 0)
|
||||
{
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parentId, mediaType);
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId), this))
|
||||
{
|
||||
media.WasCancelled = true;
|
||||
return media;
|
||||
}
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
media.CreatorId = userId;
|
||||
repository.AddOrUpdate(media);
|
||||
uow.Commit();
|
||||
|
||||
var xml = media.ToXml();
|
||||
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
|
||||
}
|
||||
}
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", media.CreatorId, media.Id);
|
||||
|
||||
return media;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
|
||||
/// that this Media should based on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns an <see cref="IMedia"/> object that has been persisted to the database
|
||||
/// and therefor has an identity.
|
||||
/// </remarks>
|
||||
/// <param name="name">Name of the Media object</param>
|
||||
/// <param name="parent">Parent <see cref="IMedia"/> for the new Media item</param>
|
||||
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
|
||||
/// <param name="userId">Optional id of the user creating the media item</param>
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
public IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
|
||||
{
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parent, mediaType);
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parent), this))
|
||||
{
|
||||
media.WasCancelled = true;
|
||||
return media;
|
||||
}
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
media.CreatorId = userId;
|
||||
repository.AddOrUpdate(media);
|
||||
uow.Commit();
|
||||
|
||||
var xml = media.ToXml();
|
||||
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
|
||||
}
|
||||
}
|
||||
|
||||
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parent), this);
|
||||
|
||||
Audit.Add(AuditTypes.New, "", media.CreatorId, media.Id);
|
||||
|
||||
return media;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an <see cref="IMedia"/> object by Id
|
||||
/// </summary>
|
||||
@@ -651,18 +713,14 @@ namespace Umbraco.Core.Services
|
||||
uow.Commit();
|
||||
|
||||
var xml = media.ToXml();
|
||||
var poco = new ContentXmlDto {NodeId = media.Id, Xml = xml.ToString(SaveOptions.None)};
|
||||
var exists = uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new {Id = media.Id}) != null;
|
||||
int result = exists
|
||||
? uow.Database.Update(poco)
|
||||
: Convert.ToInt32(uow.Database.Insert(poco));
|
||||
CreateAndSaveMediaXml(xml, media.Id, uow.Database);
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
|
||||
|
||||
Audit.Add(AuditTypes.Save, "Save Media performed by user", media.CreatorId, media.Id);
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
|
||||
|
||||
Audit.Add(AuditTypes.Save, "Save Media performed by user", userId, media.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -679,6 +737,7 @@ namespace Umbraco.Core.Services
|
||||
return;
|
||||
}
|
||||
|
||||
var mediaXml = new Dictionary<int, Lazy<XElement>>();
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
@@ -690,6 +749,11 @@ namespace Umbraco.Core.Services
|
||||
|
||||
//commit the whole lot in one go
|
||||
uow.Commit();
|
||||
|
||||
foreach (var media in medias)
|
||||
{
|
||||
CreateAndSaveMediaXml(media.ToXml(), media.Id, uow.Database);
|
||||
}
|
||||
}
|
||||
|
||||
if(raiseEvents)
|
||||
@@ -698,6 +762,67 @@ namespace Umbraco.Core.Services
|
||||
Audit.Add(AuditTypes.Save, "Save Media items performed by user", userId, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts a collection of <see cref="IMedia"/> objects by updating the SortOrder according
|
||||
/// to the ordering of items in the passed in <see cref="IEnumerable{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="raiseEvents"></param>
|
||||
/// <returns>True if sorting succeeded, otherwise False</returns>
|
||||
public bool Sort(IEnumerable<IMedia> items, int userId = 0, bool raiseEvents = true)
|
||||
{
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMedia>(items), this))
|
||||
return false;
|
||||
}
|
||||
|
||||
var shouldBeCached = new List<IMedia>();
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var media in items)
|
||||
{
|
||||
//If the current sort order equals that of the media
|
||||
//we don't need to update it, so just increment the sort order
|
||||
//and continue.
|
||||
if (media.SortOrder == i)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
media.SortOrder = i;
|
||||
i++;
|
||||
|
||||
repository.AddOrUpdate(media);
|
||||
shouldBeCached.Add(media);
|
||||
}
|
||||
|
||||
uow.Commit();
|
||||
|
||||
foreach (var content in shouldBeCached)
|
||||
{
|
||||
//Create and Save ContentXml DTO
|
||||
var xml = content.ToXml();
|
||||
CreateAndSaveMediaXml(xml, content.Id, uow.Database);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(new SaveEventArgs<IMedia>(items, false), this);
|
||||
|
||||
Audit.Add(AuditTypes.Sort, "Sorting Media performed by user", userId, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds all xml content in the cmsContentXml table for all media
|
||||
/// </summary>
|
||||
@@ -790,6 +915,35 @@ namespace Umbraco.Core.Services
|
||||
return list;
|
||||
}
|
||||
|
||||
private void CreateAndSaveMediaXml(XElement xml, int id, UmbracoDatabase db)
|
||||
{
|
||||
var poco = new ContentXmlDto { NodeId = id, Xml = xml.ToString(SaveOptions.None) };
|
||||
var exists = db.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = id }) != null;
|
||||
int result = exists ? db.Update(poco) : Convert.ToInt32(db.Insert(poco));
|
||||
}
|
||||
|
||||
private IMediaType FindMediaTypeByAlias(string mediaTypeAlias)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
var query = Query<IMediaType>.Builder.Where(x => x.Alias == mediaTypeAlias);
|
||||
var mediaTypes = repository.GetByQuery(query);
|
||||
|
||||
if (mediaTypes.Any() == false)
|
||||
throw new Exception(string.Format("No MediaType matching the passed in Alias: '{0}' was found",
|
||||
mediaTypeAlias));
|
||||
|
||||
var mediaType = mediaTypes.First();
|
||||
|
||||
if (mediaType == null)
|
||||
throw new Exception(string.Format("MediaType matching the passed in Alias: '{0}' was null",
|
||||
mediaTypeAlias));
|
||||
|
||||
return mediaType;
|
||||
}
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the MemberService.
|
||||
/// </summary>
|
||||
internal class MemberService : IMemberService
|
||||
{
|
||||
private readonly RepositoryFactory _repositoryFactory;
|
||||
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
|
||||
|
||||
public MemberService(RepositoryFactory repositoryFactory)
|
||||
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public MemberService(IDatabaseUnitOfWorkProvider provider)
|
||||
: this(provider, new RepositoryFactory())
|
||||
{
|
||||
}
|
||||
|
||||
public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory)
|
||||
{
|
||||
_repositoryFactory = repositoryFactory;
|
||||
_uowProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,18 @@
|
||||
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.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
@@ -45,8 +48,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>
|
||||
@@ -183,15 +309,80 @@ namespace Umbraco.Core.Services
|
||||
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",
|
||||
new XElement("Name", contentType.Name),
|
||||
new XElement("Alias", contentType.Alias),
|
||||
new XElement("Icon", contentType.Icon),
|
||||
new XElement("Thumbnail", contentType.Thumbnail),
|
||||
new XElement("Description", contentType.Description),
|
||||
new XElement("AllowAtRoot", contentType.AllowedAsRoot.ToString()));
|
||||
|
||||
var masterContentType = contentType.CompositionAliases().FirstOrDefault();
|
||||
if(masterContentType != null)
|
||||
info.Add(new XElement("Master", masterContentType));
|
||||
|
||||
var allowedTemplates = new XElement("AllowedTemplates");
|
||||
foreach (var template in contentType.AllowedTemplates)
|
||||
{
|
||||
allowedTemplates.Add(new XElement("Template", template.Alias));
|
||||
}
|
||||
info.Add(allowedTemplates);
|
||||
if(contentType.DefaultTemplate != null && contentType.DefaultTemplate.Id != 0)
|
||||
info.Add(new XElement("DefaultTemplate", contentType.DefaultTemplate.Alias));
|
||||
else
|
||||
info.Add(new XElement("DefaultTemplate", ""));
|
||||
|
||||
var structure = new XElement("Structure");
|
||||
foreach (var allowedType in contentType.AllowedContentTypes)
|
||||
{
|
||||
structure.Add(new XElement("DocumentType", allowedType.Alias));
|
||||
}
|
||||
|
||||
var genericProperties = new XElement("GenericProperties");
|
||||
foreach (var propertyType in contentType.PropertyTypes)
|
||||
{
|
||||
var definition = _dataTypeService.GetDataTypeDefinitionById(propertyType.DataTypeDefinitionId);
|
||||
var propertyGroup = contentType.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 contentType.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("DocumentType",
|
||||
info,
|
||||
structure,
|
||||
genericProperties,
|
||||
tabs);
|
||||
return xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports and saves package xml as <see cref="IContentType"/>
|
||||
/// </summary>
|
||||
@@ -321,9 +512,10 @@ 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;
|
||||
allowedTemplates.Add(template);
|
||||
}
|
||||
else
|
||||
@@ -340,7 +532,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);
|
||||
@@ -482,6 +674,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>
|
||||
@@ -549,6 +765,7 @@ namespace Umbraco.Core.Services
|
||||
_dataTypeService.SavePreValues(dataTypeDefinition.Id, values);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dictionary Items
|
||||
@@ -564,9 +781,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
|
||||
|
||||
@@ -140,6 +140,21 @@ namespace Umbraco.Core.Services
|
||||
return repository.GetByQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their child or parent Id.
|
||||
/// Using this method will get you all relations regards of it being a child or parent relation.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the child or parent to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
public IEnumerable<Relation> GetByParentOrChildId(int id)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var query = new Query<Relation>().Where(x => x.ChildId == id || x.ParentId == id);
|
||||
return repository.GetByQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by the Name of the <see cref="RelationType"/>
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
private Lazy<ContentService> _contentService;
|
||||
private Lazy<UserService> _userService;
|
||||
private Lazy<MemberService> _memberService;
|
||||
private Lazy<MediaService> _mediaService;
|
||||
private Lazy<ContentTypeService> _contentTypeService;
|
||||
private Lazy<DataTypeService> _dataTypeService;
|
||||
@@ -56,6 +57,9 @@ namespace Umbraco.Core.Services
|
||||
if (_userService == null)
|
||||
_userService = new Lazy<UserService>(() => new UserService(provider, repositoryFactory.Value));
|
||||
|
||||
if (_memberService == null)
|
||||
_memberService = new Lazy<MemberService>(() => new MemberService(provider, repositoryFactory.Value));
|
||||
|
||||
if (_contentService == null)
|
||||
_contentService = new Lazy<ContentService>(() => new ContentService(provider, repositoryFactory.Value, publishingStrategy));
|
||||
|
||||
@@ -165,11 +169,19 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IMacroService"/>
|
||||
/// Gets the <see cref="UserService"/>
|
||||
/// </summary>
|
||||
internal IUserService UserService
|
||||
{
|
||||
get { return _userService.Value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="MemberService"/>
|
||||
/// </summary>
|
||||
internal IMemberService MemberService
|
||||
{
|
||||
get { return _memberService.Value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the UserService, which is an easy access to operations involving <see cref="IProfile"/> and eventually Users and Members.
|
||||
/// Represents the UserService, which is an easy access to operations involving <see cref="IProfile"/>, <see cref="IMembershipUser"/> and eventually Backoffice Users.
|
||||
/// </summary>
|
||||
internal class UserService : IUserService
|
||||
{
|
||||
@@ -28,69 +31,6 @@ namespace Umbraco.Core.Services
|
||||
|
||||
#region Implementation of IUserService
|
||||
|
||||
/// <summary>
|
||||
/// Gets an <see cref="IProfile"/> for the current BackOffice User.
|
||||
/// </summary>
|
||||
/// <param name="httpContext">HttpContext to fetch the user through</param>
|
||||
/// <returns><see cref="IProfile"/> containing the Name and Id of the logged in BackOffice User</returns>
|
||||
public IProfile GetCurrentBackOfficeUser(HttpContextBase httpContext)
|
||||
{
|
||||
Mandate.That(httpContext != null,
|
||||
() =>
|
||||
new ArgumentException(
|
||||
"The HttpContext which is used to retrieve information about the currently logged in backoffice user was null and can therefor not be used",
|
||||
"HttpContextBase"));
|
||||
if (httpContext == null) return null;
|
||||
|
||||
var cookie = httpContext.Request.Cookies["UMB_UCONTEXT"];
|
||||
Mandate.That(cookie != null, () => new ArgumentException("The Cookie containing the UserContext Guid Id was null", "Cookie"));
|
||||
if (cookie == null) return null;
|
||||
|
||||
string contextId = cookie.Value;
|
||||
string cacheKey = string.Concat("UmbracoUserContext", contextId);
|
||||
|
||||
int userId = 0;
|
||||
|
||||
if(HttpRuntime.Cache[cacheKey] == null)
|
||||
{
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
userId =
|
||||
uow.Database.ExecuteScalar<int>(
|
||||
"select userID from umbracoUserLogins where contextID = @ContextId",
|
||||
new { ContextId = new Guid(contextId) });
|
||||
|
||||
HttpRuntime.Cache.Insert(cacheKey, userId,
|
||||
null,
|
||||
System.Web.Caching.Cache.NoAbsoluteExpiration,
|
||||
new TimeSpan(0, (int)(Umbraco.Core.Configuration.GlobalSettings.TimeOutInMinutes / 10), 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
userId = (int) HttpRuntime.Cache[cacheKey];
|
||||
}
|
||||
|
||||
var profile = GetProfileById(userId);
|
||||
return profile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an <see cref="IProfile"/> for the current BackOffice User.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Requests the current HttpContext, so this method will only work in a web context.
|
||||
/// </remarks>
|
||||
/// <returns><see cref="IProfile"/> containing the Name and Id of the logged in BackOffice User</returns>
|
||||
public IProfile GetCurrentBackOfficeUser()
|
||||
{
|
||||
var context = HttpContext.Current;
|
||||
Mandate.That<Exception>(context != null);
|
||||
|
||||
var wrapper = new HttpContextWrapper(context);
|
||||
return GetCurrentBackOfficeUser(wrapper);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IProfile by User Id.
|
||||
/// </summary>
|
||||
@@ -104,6 +44,76 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IUserType by its Alias
|
||||
/// </summary>
|
||||
/// <param name="alias">Alias of the UserType to retrieve</param>
|
||||
/// <returns><see cref="IUserType"/></returns>
|
||||
public IUserType GetUserTypeByAlias(string alias)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateUserTypeRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var query = Query<IUserType>.Builder.Where(x => x.Alias == alias);
|
||||
var contents = repository.GetByQuery(query);
|
||||
return contents.SingleOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IUserType by its Name
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the UserType to retrieve</param>
|
||||
/// <returns><see cref="IUserType"/></returns>
|
||||
public IUserType GetUserTypeByName(string name)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateUserTypeRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var query = Query<IUserType>.Builder.Where(x => x.Name == name);
|
||||
var contents = repository.GetByQuery(query);
|
||||
return contents.SingleOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new user for logging into the umbraco backoffice
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="login"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <param name="userType"></param>
|
||||
/// <param name="email"></param>
|
||||
/// <returns></returns>
|
||||
public IMembershipUser CreateUser(string name, string login, string password, IUserType userType, string email = "")
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateUserRepository(uow))
|
||||
{
|
||||
var loginExists = uow.Database.ExecuteScalar<int>("SELECT COUNT(id) FROM umbracoUser WHERE userLogin = @Login", new { Login = login }) != 0;
|
||||
if (loginExists)
|
||||
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
|
||||
};
|
||||
|
||||
repository.AddOrUpdate(user);
|
||||
uow.Commit();
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Publishing;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Standalone
|
||||
{
|
||||
internal class ServiceContextManager : IDisposable
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
private readonly string _providerName;
|
||||
private ServiceContext _serviceContext;
|
||||
private readonly StandaloneCoreApplication _application;
|
||||
|
||||
public ServiceContextManager(string connectionString, string providerName, string baseDirectory)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
_providerName = providerName;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public ServiceContext Services
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_serviceContext == null)
|
||||
{
|
||||
var dbFactory = new DefaultDatabaseFactory(_connectionString, _providerName);
|
||||
var dbContext = new DatabaseContext(dbFactory);
|
||||
Database.Mapper = new PetaPocoMapper();
|
||||
_serviceContext = new ServiceContext(
|
||||
new PetaPocoUnitOfWorkProvider(dbFactory),
|
||||
new FileUnitOfWorkProvider(),
|
||||
new PublishingStrategy());
|
||||
|
||||
//initialize the DatabaseContext
|
||||
dbContext.Initialize(_providerName);
|
||||
}
|
||||
|
||||
return _serviceContext;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
((IDisposable)ApplicationContext.Current).Dispose();
|
||||
_application.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Standalone
|
||||
{
|
||||
internal class StandaloneCoreApplication : UmbracoApplicationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StandaloneCoreApplication"/> class.
|
||||
/// </summary>
|
||||
protected StandaloneCoreApplication(string baseDirectory)
|
||||
{
|
||||
_baseDirectory = baseDirectory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides the application boot manager.
|
||||
/// </summary>
|
||||
/// <returns>An application boot manager.</returns>
|
||||
protected override IBootManager GetBootManager()
|
||||
{
|
||||
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();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instance of the standalone Umbraco application.
|
||||
/// </summary>
|
||||
public static StandaloneCoreApplication GetApplication(string baseDirectory)
|
||||
{
|
||||
lock (AppLock)
|
||||
{
|
||||
return _application ?? (_application = new StandaloneCoreApplication(baseDirectory));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the application.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
lock (AppLock)
|
||||
{
|
||||
if (_started)
|
||||
throw new InvalidOperationException("Application has already started.");
|
||||
Application_Start(this, EventArgs.Empty);
|
||||
_started = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IApplicationEventHandler management
|
||||
|
||||
private readonly List<Type> _handlersToAdd = new List<Type>();
|
||||
private readonly List<Type> _handlersToRemove = new List<Type>();
|
||||
|
||||
/// <summary>
|
||||
/// Associates an <see cref="IApplicationEventHandler"/> type with the application.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to associate.</typeparam>
|
||||
/// <returns>The application.</returns>
|
||||
/// <remarks>Types implementing <see cref="IApplicationEventHandler"/> from within
|
||||
/// an executable are not automatically discovered by Umbraco and have to be
|
||||
/// explicitely associated with the application using this method.</remarks>
|
||||
public StandaloneCoreApplication WithApplicationEventHandler<T>()
|
||||
where T : IApplicationEventHandler
|
||||
{
|
||||
_handlersToAdd.Add(typeof(T));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dissociates an <see cref="IApplicationEventHandler"/> type from the application.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to dissociate.</typeparam>
|
||||
/// <returns>The application.</returns>
|
||||
public StandaloneCoreApplication WithoutApplicationEventHandler<T>()
|
||||
where T : IApplicationEventHandler
|
||||
{
|
||||
_handlersToRemove.Add(typeof(T));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Associates an <see cref="IApplicationEventHandler"/> type with the application.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to associate.</param>
|
||||
/// <returns>The application.</returns>
|
||||
/// <remarks>Types implementing <see cref="IApplicationEventHandler"/> from within
|
||||
/// an executable are not automatically discovered by Umbraco and have to be
|
||||
/// explicitely associated with the application using this method.</remarks>
|
||||
public StandaloneCoreApplication WithApplicationEventHandler(Type type)
|
||||
{
|
||||
if (type.Implements<IApplicationEventHandler>() == false)
|
||||
throw new ArgumentException("Type does not implement IApplicationEventHandler.", "type");
|
||||
_handlersToAdd.Add(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dissociates an <see cref="IApplicationEventHandler"/> type from the application.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to dissociate.</param>
|
||||
/// <returns>The application.</returns>
|
||||
public StandaloneCoreApplication WithoutApplicationEventHandler(Type type)
|
||||
{
|
||||
if (type.Implements<IApplicationEventHandler>() == false)
|
||||
throw new ArgumentException("Type does not implement IApplicationEventHandler.", "type");
|
||||
_handlersToRemove.Add(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Standalone
|
||||
{
|
||||
internal class StandaloneCoreBootManager : CoreBootManager
|
||||
{
|
||||
private readonly IEnumerable<Type> _handlersToAdd;
|
||||
private readonly IEnumerable<Type> _handlersToRemove;
|
||||
private readonly string _baseDirectory;
|
||||
|
||||
public StandaloneCoreBootManager(UmbracoApplicationBase umbracoApplication, IEnumerable<Type> handlersToAdd, IEnumerable<Type> handlersToRemove, string baseDirectory)
|
||||
: base(umbracoApplication)
|
||||
{
|
||||
_handlersToAdd = handlersToAdd;
|
||||
_handlersToRemove = handlersToRemove;
|
||||
_baseDirectory = baseDirectory;
|
||||
|
||||
base.InitializeApplicationRootPath(_baseDirectory);
|
||||
|
||||
// this is only here to ensure references to the assemblies needed for
|
||||
// the DataTypesResolver otherwise they won't be loaded into the AppDomain.
|
||||
var interfacesAssemblyName = typeof(IDataType).Assembly.FullName;
|
||||
}
|
||||
|
||||
protected override void InitializeApplicationEventsResolver()
|
||||
{
|
||||
base.InitializeApplicationEventsResolver();
|
||||
|
||||
foreach (var type in _handlersToAdd)
|
||||
ApplicationEventsResolver.Current.AddType(type);
|
||||
|
||||
foreach (var type in _handlersToRemove)
|
||||
ApplicationEventsResolver.Current.RemoveType(type);
|
||||
}
|
||||
|
||||
protected override void InitializeResolvers()
|
||||
{
|
||||
base.InitializeResolvers();
|
||||
|
||||
//Mappers are not resolved, which could be because of a known TypeMapper issue
|
||||
/*MappingResolver.Reset();
|
||||
MappingResolver.Current = new MappingResolver(
|
||||
() =>
|
||||
new List<Type>
|
||||
{
|
||||
typeof (ContentMapper),
|
||||
typeof (ContentTypeMapper),
|
||||
typeof (MediaMapper),
|
||||
typeof (MediaTypeMapper),
|
||||
typeof (DataTypeDefinitionMapper),
|
||||
typeof (UmbracoEntityMapper)
|
||||
});*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1035,5 +1035,34 @@ namespace Umbraco.Core
|
||||
{
|
||||
return ShortStringHelper.CleanStringForSafeFileName(text, culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An extension method that returns a new string in which all occurrences of a
|
||||
/// specified string in the current instance are replaced with another specified string.
|
||||
/// StringComparison specifies the type of search to use for the specified string.
|
||||
/// </summary>
|
||||
/// <param name="source">Current instance of the string</param>
|
||||
/// <param name="oldString">Specified string to replace</param>
|
||||
/// <param name="newString">Specified string to inject</param>
|
||||
/// <param name="stringComparison">String Comparison object to specify search type</param>
|
||||
/// <returns>Updated string</returns>
|
||||
public static string Replace(this string source, string oldString, string newString, StringComparison stringComparison)
|
||||
{
|
||||
var index = source.IndexOf(oldString, stringComparison);
|
||||
|
||||
// Determine if we found a match
|
||||
var matchFound = index >= 0;
|
||||
|
||||
if (matchFound)
|
||||
{
|
||||
// Remove the old text
|
||||
source = source.Remove(index, oldString.Length);
|
||||
|
||||
// Add the replacemenet text
|
||||
source = source.Insert(index, newString);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,10 @@ namespace Umbraco.Core
|
||||
{
|
||||
//NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have
|
||||
// already been loaded in to the app domain, instead we will look directly into the bin folder and load each one.
|
||||
var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
|
||||
var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
|
||||
var binFolder = IOHelper.GetRootDirectoryBinFolder();
|
||||
var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
|
||||
//var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
|
||||
//var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
|
||||
assemblies = new List<Assembly>();
|
||||
foreach (var a in binAssemblyFiles)
|
||||
{
|
||||
@@ -540,7 +542,7 @@ namespace Umbraco.Core
|
||||
foreach (var typeToSearch in subTypesToSearch)
|
||||
{
|
||||
//recursively find the types inheriting from this sub type in the other non-scanned assemblies.
|
||||
var foundTypes = GetClasses(typeToSearch, otherAssemblies, onlyConcreteClasses);
|
||||
var foundTypes = GetClasses(typeToSearch, otherAssemblies, onlyConcreteClasses, additionalFilter);
|
||||
foundAssignableTypes.AddRange(foundTypes);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
@@ -112,13 +113,15 @@
|
||||
<Compile Include="Auditing\IAuditWriteProvider.cs" />
|
||||
<Compile Include="CacheHelper.cs" />
|
||||
<Compile Include="Cache\CacheKeys.cs" />
|
||||
<Compile Include="Cache\CacheProviderBase.cs" />
|
||||
<Compile Include="Cache\CacheRefresherBase.cs" />
|
||||
<Compile Include="Cache\CacheRefresherEventArgs.cs" />
|
||||
<Compile Include="Cache\CacheProviderBase.cs" />
|
||||
<Compile Include="Cache\RuntimeCacheProviderBase.cs" />
|
||||
<Compile Include="Cache\HttpRuntimeCacheProvider.cs" />
|
||||
<Compile Include="Cache\IJsonCacheRefresher.cs" />
|
||||
<Compile Include="Cache\JsonCacheRefresherBase.cs" />
|
||||
<Compile Include="Cache\NullCacheProvider.cs" />
|
||||
<Compile Include="Cache\StaticCacheProvider.cs" />
|
||||
<Compile Include="Cache\TypedCacheRefresherBase.cs" />
|
||||
<Compile Include="CodeAnnotations\FriendlyNameAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoObjectTypeAttribute.cs" />
|
||||
@@ -193,6 +196,7 @@
|
||||
<Compile Include="Models\IDictionaryTranslation.cs" />
|
||||
<Compile Include="Models\IFile.cs" />
|
||||
<Compile Include="Models\ILanguage.cs" />
|
||||
<Compile Include="Models\Membership\UmbracoMembershipUser.cs" />
|
||||
<Compile Include="Models\ServerRegistration.cs" />
|
||||
<Compile Include="Models\ITemplate.cs" />
|
||||
<Compile Include="Models\Language.cs" />
|
||||
@@ -521,17 +525,11 @@
|
||||
<Compile Include="Persistence\UnitOfWork\IUnitOfWorkRepository.cs" />
|
||||
<Compile Include="Persistence\UnitOfWork\PetaPocoUnitOfWork.cs" />
|
||||
<Compile Include="Persistence\UnitOfWork\PetaPocoUnitOfWorkProvider.cs" />
|
||||
<Compile Include="Profiling\Profiler.cs" />
|
||||
<Compile Include="PropertyEditors\Attributes\PropertyEditorAttribute.cs" />
|
||||
<Compile Include="PropertyEditors\Attributes\ShowLabelAttribute.cs" />
|
||||
<Compile Include="PropertyEditors\BlankPreValueModel.cs" />
|
||||
<Compile Include="PropertyEditors\EditorModel.cs" />
|
||||
<Compile Include="PropertyEditors\EditorModel`T.cs" />
|
||||
<Compile Include="PropertyEditors\IValueModel.cs" />
|
||||
<Compile Include="PropertyEditors\PreValueDefinition.cs" />
|
||||
<Compile Include="PropertyEditors\PreValueModel.cs" />
|
||||
<Compile Include="PropertyEditors\PropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\PropertyEditor`T.cs" />
|
||||
<Compile Include="Profiling\IProfiler.cs" />
|
||||
<Compile Include="Profiling\LogProfiler.cs" />
|
||||
<Compile Include="Profiling\ProfilerExtensions.cs" />
|
||||
<Compile Include="Profiling\ProfilerResolver.cs" />
|
||||
<Compile Include="Profiling\WebProfiler.cs" />
|
||||
<Compile Include="PublishedContentExtensions.cs" />
|
||||
<Compile Include="Dictionary\ICultureDictionary.cs" />
|
||||
<Compile Include="Dynamics\ClassFactory.cs" />
|
||||
@@ -681,15 +679,20 @@
|
||||
<Compile Include="Services\IFileService.cs" />
|
||||
<Compile Include="Services\ILocalizationService.cs" />
|
||||
<Compile Include="Services\IMediaService.cs" />
|
||||
<Compile Include="Services\IMemberService.cs" />
|
||||
<Compile Include="Services\IService.cs" />
|
||||
<Compile Include="Services\IUserService.cs" />
|
||||
<Compile Include="Services\LocalizationService.cs" />
|
||||
<Compile Include="Services\MediaService.cs" />
|
||||
<Compile Include="Services\MemberService.cs" />
|
||||
<Compile Include="Services\RelationService.cs" />
|
||||
<Compile Include="Services\ServerRegistrationService.cs" />
|
||||
<Compile Include="Services\PackagingService.cs" />
|
||||
<Compile Include="Services\ServiceContext.cs" />
|
||||
<Compile Include="Services\UserService.cs" />
|
||||
<Compile Include="Standalone\ServiceContextManager.cs" />
|
||||
<Compile Include="Standalone\StandaloneCoreApplication.cs" />
|
||||
<Compile Include="Standalone\StandaloneCoreBootManager.cs" />
|
||||
<Compile Include="Strings\ContentBaseExtensions.cs" />
|
||||
<Compile Include="TopologicalSorter.cs" />
|
||||
<Compile Include="Strings\DefaultUrlSegmentProvider.cs" />
|
||||
@@ -748,7 +751,7 @@
|
||||
<Compile Include="IfExtensions.cs" />
|
||||
<Compile Include="PluginManager.cs" />
|
||||
<Compile Include="IO\FileSecurityException.cs" />
|
||||
<Compile Include="IO\FileSystemProvider.cs" />
|
||||
<Compile Include="IO\FileSystemProviderConstants.cs" />
|
||||
<Compile Include="IO\FileSystemProviderManager.cs" />
|
||||
<Compile Include="IO\IFileSystem.cs" />
|
||||
<Compile Include="IO\IOHelper.cs" />
|
||||
@@ -769,7 +772,6 @@
|
||||
<Compile Include="Xml\DynamicContext.cs" />
|
||||
<Compile Include="Xml\XmlNamespaces.cs" />
|
||||
<Compile Include="Xml\XmlNodeListFactory.cs" />
|
||||
<Compile Include="Xml\XmlNodeExtensions.cs" />
|
||||
<Compile Include="Xml\XPathNavigatorExtensions.cs" />
|
||||
<Compile Include="Xml\XPathVariable.cs" />
|
||||
</ItemGroup>
|
||||
@@ -785,6 +787,10 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Strings\Notes.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Packaging\" />
|
||||
<Folder Include="PropertyEditors\Attributes\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Mvc;
|
||||
@@ -25,6 +22,11 @@ namespace Umbraco.Core
|
||||
public static event EventHandler ApplicationStarting;
|
||||
public static event EventHandler ApplicationStarted;
|
||||
|
||||
/// <summary>
|
||||
/// Called when the HttpApplication.Init() is fired, allows developers to subscribe to the HttpApplication events
|
||||
/// </summary>
|
||||
public static event EventHandler ApplicationInit;
|
||||
|
||||
/// <summary>
|
||||
/// Boots up the Umbraco application
|
||||
/// </summary>
|
||||
@@ -50,22 +52,13 @@ namespace Umbraco.Core
|
||||
StartApplication(sender, e);
|
||||
}
|
||||
|
||||
protected void Application_BeginRequest()
|
||||
/// <summary>
|
||||
/// Override init and raise the event
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
if (GlobalSettings.DebugMode)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Request["umbDebug"]))
|
||||
Umbraco.Core.Profiling.Profiler.Instance.Start();
|
||||
}
|
||||
}
|
||||
|
||||
protected void Application_EndRequest()
|
||||
{
|
||||
if (GlobalSettings.DebugMode)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Request["umbDebug"]))
|
||||
Umbraco.Core.Profiling.Profiler.Instance.Stop();
|
||||
}
|
||||
base.Init();
|
||||
OnApplicationInit(this, new EventArgs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -90,6 +83,17 @@ namespace Umbraco.Core
|
||||
ApplicationStarted(sender, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called to raise the ApplicationInit event
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void OnApplicationInit(object sender, EventArgs e)
|
||||
{
|
||||
if (ApplicationInit != null)
|
||||
ApplicationInit(sender, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A method that can be overridden to invoke code when the application has an error.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core
|
||||
@@ -8,6 +10,19 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public static class UriExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a performance tweak to check if this is a .css, .js or .ico, .jpg, .jpeg, .png, .gif file request since
|
||||
/// .Net will pass these requests through to the module when in integrated mode.
|
||||
/// We want to ignore all of these requests immediately.
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsClientSideRequest(this Uri url)
|
||||
{
|
||||
var toIgnore = new[] { ".js", ".css", ".ico", ".png", ".jpg", ".jpeg", ".gif" };
|
||||
return toIgnore.Any(x => Path.GetExtension(url.LocalPath).InvariantEquals(x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewrites the path of uri.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
// source: mvpxml.codeplex.com
|
||||
|
||||
namespace Umbraco.Core.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extensions to XmlNode.
|
||||
/// </summary>
|
||||
internal static class XmlNodeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Selects a list of XmlNode matching an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The list of XmlNode matching the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectNodes(source, expression, av);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects a list of XmlNode matching an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The list of XmlNode matching the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectNodes(source, expression, av);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects a list of XmlNode matching an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The list of XmlNode matching the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectNodes(expression);
|
||||
|
||||
var iterator = source.CreateNavigator().Select(expression, variables);
|
||||
return XmlNodeListFactory.CreateNodeList(iterator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects a list of XmlNode matching an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The list of XmlNode matching the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectNodes(expression);
|
||||
|
||||
var iterator = source.CreateNavigator().Select(expression, variables);
|
||||
return XmlNodeListFactory.CreateNodeList(iterator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the first XmlNode that matches an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The first XmlNode that matches the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectSingleNode(source, expression, av);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the first XmlNode that matches an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The first XmlNode that matches the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, XPathExpression expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectSingleNode(source, expression, av);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the first XmlNode that matches an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The first XmlNode that matches the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectSingleNode(expression);
|
||||
|
||||
return SelectNodes(source, expression, variables).Cast<XmlNode>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the first XmlNode that matches an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The first XmlNode that matches the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, XPathExpression expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectSingleNode(expression);
|
||||
|
||||
return SelectNodes(source, expression, variables).Cast<XmlNode>().FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core.Xml;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -9,6 +13,160 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
internal static class XmlExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Selects a list of XmlNode matching an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The list of XmlNode matching the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectNodes(source, expression, av);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects a list of XmlNode matching an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The list of XmlNode matching the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectNodes(source, expression, av);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects a list of XmlNode matching an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The list of XmlNode matching the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectNodes(expression);
|
||||
|
||||
var iterator = source.CreateNavigator().Select(expression, variables);
|
||||
return XmlNodeListFactory.CreateNodeList(iterator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects a list of XmlNode matching an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The list of XmlNode matching the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectNodes(expression);
|
||||
|
||||
var iterator = source.CreateNavigator().Select(expression, variables);
|
||||
return XmlNodeListFactory.CreateNodeList(iterator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the first XmlNode that matches an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The first XmlNode that matches the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectSingleNode(source, expression, av);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the first XmlNode that matches an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The first XmlNode that matches the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, XPathExpression expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectSingleNode(source, expression, av);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the first XmlNode that matches an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The first XmlNode that matches the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectSingleNode(expression);
|
||||
|
||||
return SelectNodes(source, expression, variables).Cast<XmlNode>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the first XmlNode that matches an XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="source">A source XmlNode.</param>
|
||||
/// <param name="expression">An XPath expression.</param>
|
||||
/// <param name="variables">A set of XPathVariables.</param>
|
||||
/// <returns>The first XmlNode that matches the XPath expression.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <param name="variables" /> is <c>null</c>, or is empty, or contains only one single
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, XPathExpression expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectSingleNode(expression);
|
||||
|
||||
return SelectNodes(source, expression, variables).Cast<XmlNode>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts from an XDocument to an XmlDocument
|
||||
/// </summary>
|
||||
|
||||
@@ -7,29 +7,38 @@ using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Tests.BootManagers
|
||||
{
|
||||
[TestFixture]
|
||||
public class CoreBootManagerTests
|
||||
public class CoreBootManagerTests : BaseUmbracoApplicationTest
|
||||
{
|
||||
|
||||
private TestApp _testApp;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_testApp = new TestApp();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
_testApp = null;
|
||||
|
||||
ApplicationEventsResolver.Reset();
|
||||
SqlSyntaxProvidersResolver.Reset();
|
||||
//ApplicationEventsResolver.Reset();
|
||||
//SqlSyntaxProvidersResolver.Reset();
|
||||
}
|
||||
|
||||
protected override void FreezeResolution()
|
||||
{
|
||||
//don't freeze resolution, we'll do that in the boot manager
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -57,11 +58,35 @@ namespace Umbraco.Tests.CodeFirst
|
||||
#region Test setup
|
||||
public override void Initialize()
|
||||
{
|
||||
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
|
||||
var configPath = Path.Combine(currDir.Parent.Parent.FullName, "config");
|
||||
if (Directory.Exists(configPath) == false)
|
||||
Directory.CreateDirectory(configPath);
|
||||
|
||||
var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
if (System.IO.File.Exists(umbracoSettingsFile) == false)
|
||||
System.IO.File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
Core.Configuration.UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
|
||||
var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
if (System.IO.File.Exists(umbracoSettingsFile))
|
||||
System.IO.File.Delete(umbracoSettingsFile);
|
||||
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
@@ -17,8 +18,32 @@ namespace Umbraco.Tests.CoreStrings
|
||||
public void Setup()
|
||||
{
|
||||
_helper = new LegacyShortStringHelper();
|
||||
var currDir = new DirectoryInfo(TestHelpers.TestHelper.CurrentAssemblyDirectory);
|
||||
Directory.CreateDirectory(Path.Combine(currDir.Parent.Parent.FullName, "config"));
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
Core.Configuration.UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
//TODO: Deleting the umbracoSettings.config file makes a lot of tests fail
|
||||
|
||||
//var currDir = new DirectoryInfo(TestHelpers.TestHelper.CurrentAssemblyDirectory);
|
||||
|
||||
//var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
//if (File.Exists(umbracoSettingsFile))
|
||||
// File.Delete(umbracoSettingsFile);
|
||||
}
|
||||
|
||||
|
||||
#region Cases
|
||||
[TestCase("foo", "foo")]
|
||||
[TestCase(" foo ", "Foo")]
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Tests.IO
|
||||
[Test]
|
||||
public void Can_Get_Base_File_System()
|
||||
{
|
||||
var fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media);
|
||||
var fs = FileSystemProviderManager.Current.GetUnderlyingFileSystemProvider(FileSystemProviderConstants.Media);
|
||||
|
||||
Assert.NotNull(fs);
|
||||
}
|
||||
|
||||
@@ -27,19 +27,34 @@ namespace Umbraco.Tests
|
||||
UmbracoContext.Current = routingContext.UmbracoContext;
|
||||
|
||||
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
var configPath = Path.Combine(currDir.Parent.Parent.FullName, "config");
|
||||
if (Directory.Exists(configPath) == false)
|
||||
Directory.CreateDirectory(configPath);
|
||||
|
||||
var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
if (File.Exists(umbracoSettingsFile) == false)
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
Core.Configuration.UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
//TODO: Deleting the umbracoSettings.config file makes a lot of tests fail
|
||||
|
||||
//var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
|
||||
//var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
//if (File.Exists(umbracoSettingsFile))
|
||||
// File.Delete(umbracoSettingsFile);
|
||||
|
||||
base.TearDown();
|
||||
UmbracoContext.Current = null;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Caching;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Profiling;
|
||||
using umbraco;
|
||||
using umbraco.cms.businesslogic.macro;
|
||||
|
||||
@@ -20,11 +18,17 @@ namespace Umbraco.Tests.Macros
|
||||
{
|
||||
//we DO want cache enabled for these tests
|
||||
ApplicationContext.Current = new ApplicationContext(true);
|
||||
ProfilerResolver.Current = new ProfilerResolver(new LogProfiler())
|
||||
{
|
||||
CanResolveBeforeFrozen = true
|
||||
};
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
ProfilerResolver.Current.DisposeIfDisposable();
|
||||
ProfilerResolver.Reset();
|
||||
ApplicationContext.Current.ApplicationCache.ClearAllCache();
|
||||
ApplicationContext.Current.DisposeIfDisposable();
|
||||
ApplicationContext.Current = null;
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
using System.Xml.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
using umbraco.editorControls.tinyMCE3;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
|
||||
@@ -330,7 +330,7 @@ namespace Umbraco.Tests
|
||||
public void Resolves_RestExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveRestExtensions();
|
||||
Assert.AreEqual(2, types.Count());
|
||||
Assert.AreEqual(3, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Xml;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Tests.PublishedContent;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
@@ -77,6 +78,7 @@ namespace Umbraco.Tests.PublishedCache
|
||||
//ensure the StateHelper is using our custom context
|
||||
StateHelper.HttpContext = _httpContextFactory.HttpContext;
|
||||
|
||||
UmbracoSettings.UseLegacyXmlSchema = false;
|
||||
var cache = new PublishedContentCache
|
||||
{
|
||||
GetXmlDelegate = (context, preview) =>
|
||||
|
||||
@@ -30,13 +30,20 @@ namespace Umbraco.Tests.PublishedContent
|
||||
base.Initialize();
|
||||
//copy the umbraco settings file over
|
||||
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
var configPath = Path.Combine(currDir.Parent.Parent.FullName, "config");
|
||||
if (Directory.Exists(configPath) == false)
|
||||
Directory.CreateDirectory(configPath);
|
||||
|
||||
var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
if (File.Exists(umbracoSettingsFile) == false)
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
UmbracoSettings.SettingsFilePath = IOHelper.MapPath(SystemDirectories.Config + Path.DirectorySeparatorChar, false);
|
||||
|
||||
@@ -76,6 +83,14 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
//TODO: Deleting the umbracoSettings.config file makes a lot of tests fail
|
||||
|
||||
//var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
|
||||
//var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
//if (File.Exists(umbracoSettingsFile))
|
||||
// File.Delete(umbracoSettingsFile);
|
||||
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
@@ -6,6 +7,7 @@ using Umbraco.Web;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.PublishedCache.XmlPublishedCache;
|
||||
using File = Umbraco.Core.Models.File;
|
||||
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
@@ -13,9 +15,26 @@ namespace Umbraco.Tests.PublishedContent
|
||||
public class DynamicPublishedContentTests : DynamicDocumentTestsBase<DynamicPublishedContent, DynamicPublishedContentList>
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
{
|
||||
var currDir = new DirectoryInfo(TestHelpers.TestHelper.CurrentAssemblyDirectory);
|
||||
|
||||
var configPath = Path.Combine(currDir.Parent.Parent.FullName, "config");
|
||||
if (Directory.Exists(configPath) == false)
|
||||
Directory.CreateDirectory(configPath);
|
||||
|
||||
var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
if (System.IO.File.Exists(umbracoSettingsFile) == false)
|
||||
System.IO.File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
Core.Configuration.UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
//need to specify a custom callback for unit tests
|
||||
PublishedContentHelper.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
|
||||
{
|
||||
if (propertyAlias == "content")
|
||||
if (propertyAlias.InvariantEquals("content"))
|
||||
{
|
||||
//return the rte type id
|
||||
return Guid.Parse(Constants.PropertyEditors.TinyMCEv3);
|
||||
|
||||
@@ -240,6 +240,10 @@ namespace Umbraco.Tests.PublishedContent
|
||||
var propVal2 = doc.GetPropertyValue<IHtmlString>("content");
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(propVal2.GetType()));
|
||||
Assert.AreEqual("<div>This is some content</div>", propVal2.ToString());
|
||||
|
||||
var propVal3 = doc.GetPropertyValue("Content");
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(propVal3.GetType()));
|
||||
Assert.AreEqual("<div>This is some content</div>", propVal3.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -18,17 +18,36 @@ namespace Umbraco.Tests.Routing
|
||||
base.Initialize();
|
||||
|
||||
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
var configPath = Path.Combine(currDir.Parent.Parent.FullName, "config");
|
||||
if (Directory.Exists(configPath) == false)
|
||||
Directory.CreateDirectory(configPath);
|
||||
|
||||
var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
if (File.Exists(umbracoSettingsFile) == false)
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
SettingsForTests.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
|
||||
}
|
||||
|
||||
|
||||
public void TearDown()
|
||||
{
|
||||
//TODO: Deleting the umbracoSettings.config file makes a lot of tests fail
|
||||
|
||||
//var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
|
||||
//var umbracoSettingsFile = Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config");
|
||||
//if (File.Exists(umbracoSettingsFile))
|
||||
// File.Delete(umbracoSettingsFile);
|
||||
}
|
||||
|
||||
protected override void FreezeResolution()
|
||||
{
|
||||
SiteDomainHelperResolver.Current = new SiteDomainHelperResolver(new SiteDomainHelper());
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user