Compare commits

..

128 Commits

Author SHA1 Message Date
Mads Rasmussen 244ee646b9 Revert "update content when changing variation"
This reverts commit b487436d93.
2016-04-07 12:45:33 +02:00
Mads Rasmussen b487436d93 update content when changing variation 2016-04-07 12:38:05 +02:00
Mads Rasmussen 321b1a3964 disable autocomplete on editor name input 2016-04-07 11:17:05 +02:00
Mads Rasmussen f6b1971243 disable name input for a marketing variation 2016-04-07 11:05:21 +02:00
Simon Busborg ab1e412b4b Active in quickswitcher 2016-04-07 10:51:39 +02:00
Mads Rasmussen 2c866e8326 add spanish 2016-04-07 10:24:52 +02:00
Mads Rasmussen 433563c10b select first variation 2016-04-06 20:03:49 +02:00
Mads Rasmussen 95b91cb55f a bit fine tuning of selected variation and language 2016-04-06 19:29:29 +02:00
Mads Rasmussen d070b869a3 fix error in css 2016-04-06 16:09:26 +02:00
Mads Rasmussen 82bcb8bb8a Merge branch 'temp-maurice' of https://github.com/umbraco/Umbraco-CMS into temp-maurice 2016-04-06 16:07:49 +02:00
Mads Rasmussen 8cbd0281aa set limit on apps 2016-04-06 16:07:12 +02:00
Simon Busborg 148067f119 apps 2016-04-06 16:01:16 +02:00
Mads Rasmussen 9d79577833 add activity app 2016-04-06 15:05:16 +02:00
Simon Busborg c24918aeb7 standard width on apps 2016-04-06 14:15:10 +02:00
Simon Busborg f7a814714c even spacing between apps 2016-04-06 11:36:34 +02:00
Simon Busborg 3200a7fd1a Splitview close 2016-04-06 11:23:38 +02:00
Mads Rasmussen 7983aedf53 make tabs to apps 2016-04-06 11:22:18 +02:00
Mads Rasmussen c31efa3f54 only show variations for active language + add sortable on variations 2016-04-05 15:16:55 +02:00
Simon Busborg c98a98dd71 Tabs 2016-04-05 15:07:35 +02:00
Mads Rasmussen ee3965521d bring back old tabs markup to enable active state 2016-04-05 14:34:57 +02:00
Mads Rasmussen 3d90c0d3d7 add segments to create variation + fix edit variation 2016-04-05 12:31:00 +02:00
Mads Rasmussen bc60aa1688 remove analytics from content plugins 2016-04-05 11:46:08 +02:00
Mads Rasmussen 5c90043298 hide the split view divider when there is no split view open 2016-04-05 11:44:16 +02:00
Mads Rasmussen 0f784151cb close split view on route change 2016-04-05 09:47:58 +02:00
Mads Rasmussen 681512da8c Merge branch 'temp-maurice' of https://github.com/umbraco/Umbraco-CMS into temp-maurice 2016-04-04 19:04:53 +02:00
Mads Rasmussen b17770d6c7 fake split views 2016-04-04 19:04:36 +02:00
Simon Busborg 745b536f63 Fixed divider 2016-04-04 12:55:08 +02:00
Mads Rasmussen 738289cd78 comment out sync switcher and property overlay 2016-04-01 11:19:13 +02:00
Simon Busborg 77d30e8484 fixed colors 2016-03-30 15:02:53 +02:00
Simon Busborg 347fb3a90d demoed version of splitview (not pretty) 2016-03-30 12:24:01 +02:00
Mads Rasmussen 39bdc1bc78 handle 1sites with 1 language 2016-03-30 09:04:26 +02:00
Simon Busborg a3dcdb159b Removed tags, added tags checkboxes, styling in general for variations 2016-03-29 15:38:50 +02:00
Simon Busborg 9656659ecd overview 2016-03-29 13:46:11 +02:00
Mads Rasmussen d679a4e697 make it possible to fake variation content 2016-03-29 12:18:47 +02:00
Mads Rasmussen c81a034c69 only show variations toggle if there are any variations 2016-03-23 14:23:02 +01:00
Mads Rasmussen a519d38b54 Merge branch 'temp-maurice' of https://github.com/umbraco/Umbraco-CMS into temp-maurice 2016-03-23 14:13:10 +01:00
Mads Rasmussen cf4c09f41f When click on item in variation quick switcher - change context in header 2016-03-23 14:12:57 +01:00
Simon Busborg bd3096c3ec changed quick toggler 2016-03-23 13:49:07 +01:00
Simon Busborg 1bbf104b9f variations overview 2016-03-23 13:41:26 +01:00
Mads Rasmussen 4f1e44d42e get variations from helper service so they are in sync 2016-03-23 13:39:26 +01:00
Simon Busborg fa68a9472b quickswitcher update 2016-03-23 11:54:54 +01:00
Mads Rasmussen efb2b744fc Merge branch 'temp-maurice' of https://github.com/umbraco/Umbraco-CMS into temp-maurice 2016-03-23 11:52:26 +01:00
Mads Rasmussen 9018c4ef79 add functionality to create, edit and delete variations - missing styling + segments 2016-03-23 11:52:04 +01:00
Simon Busborg dfce0aa0cb changed width of container 2016-03-23 08:59:52 +01:00
Mads Rasmussen 131c9a6fe1 move description inline 2016-03-22 16:24:18 +01:00
Mads Rasmussen 555589ef3b change colour on tags + bring back create variation link 2016-03-22 15:10:46 +01:00
Mads Rasmussen b099d35981 Merge branch 'temp-maurice' of https://github.com/umbraco/Umbraco-CMS into temp-maurice
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/less/components/umb-variations.less
#	src/Umbraco.Web.UI.Client/src/views/components/umb-variations.html
2016-03-22 14:24:03 +01:00
Mads Rasmussen e3bc3091f7 add dynamic data to variations overview + clean up UI + add segments to variations overview 2016-03-22 14:17:20 +01:00
Simon Busborg 320ed93b14 active quick switcher 2016-03-22 13:50:39 +01:00
Simon Busborg c71ce7ef2a changed lang options 2016-03-22 10:59:12 +01:00
Mads Rasmussen c0ea46c9f1 split languages and variations in dropdown. Show selected in header 2016-03-22 10:55:33 +01:00
Mads Rasmussen 533443fd25 remove sidebar on variations 2016-03-22 10:47:00 +01:00
Simon Busborg e76658373f Added lang groups for variations 2016-03-22 10:13:05 +01:00
Mads Rasmussen a77330a592 add a bit a variations toggle styling 2016-03-21 10:39:48 +01:00
Mads Rasmussen 2f5e9ee8c4 change sync off label + smaller font size 2016-03-21 10:01:36 +01:00
Mads Rasmussen f252590a1c Merge branch 'temp-maurice' of https://github.com/umbraco/Umbraco-CMS into temp-maurice 2016-03-18 14:40:23 +01:00
Mads Rasmussen fa4bdac78a style editor overlay label 2016-03-18 14:39:18 +01:00
Simon Busborg e268945077 fixed animate bug 2016-03-18 14:38:04 +01:00
Simon Busborg b428fb2211 fixed search / scrollable area 2016-03-18 14:26:24 +01:00
Mads Rasmussen bfc098e5e0 make change variation work work editor view 2016-03-18 14:09:07 +01:00
Simon Busborg d9b58e80fe added search to variations 2016-03-18 12:40:16 +01:00
Simon Busborg a7a860bbcd fixed dropdown 2016-03-18 12:03:05 +01:00
Mads Rasmussen fa277a4a5d fix styling on dropdown 2016-03-18 11:58:57 +01:00
Mads Rasmussen 7e1df76db3 move dropdown logic 2016-03-18 11:26:46 +01:00
Simon Busborg 9c33e292ae moved component to label 2016-03-18 11:13:49 +01:00
Mads Rasmussen 75edd645c6 add basic functionality to edit content and change which variation to sync content from 2016-03-17 21:31:09 +01:00
Mads Rasmussen 6adfdbf7dd clear variations when a new master i set 2016-03-17 20:30:29 +01:00
Mads Rasmussen 5453d86a46 make sidebar title a little smaller 2016-03-17 20:09:58 +01:00
Mads Rasmussen 6d4146b9c6 add wrappers and title to sidebar 2016-03-17 20:07:57 +01:00
Simon Busborg a93d98933f fixed z-index on buttons 2016-03-17 15:20:34 +01:00
Mads Rasmussen cf28c0ca5e change text and icon on sync toggle 2016-03-17 15:12:56 +01:00
Mads Rasmussen 435434b859 position toggle top 0 and right 0 2016-03-17 15:10:07 +01:00
Mads Rasmussen e93b057a5f make sync button a bit smaller 2016-03-17 15:02:38 +01:00
Simon Busborg e8d167faf0 added get content 2016-03-17 14:42:26 +01:00
Mads Rasmussen ab1322f789 started on dropdown 2016-03-17 12:39:40 +01:00
Simon Busborg 36abb83ff2 moved psuedo element to the property editor markup 2016-03-17 11:54:01 +01:00
Simon Busborg 0d62e62fda changed inactive state 2016-03-17 11:41:38 +01:00
Simon Busborg d25a01d9c9 added overlay to variation picker 2016-03-17 11:22:52 +01:00
Simon Busborg 1da55e4dde Fixed subview editor header 2016-03-17 10:46:08 +01:00
Simon Busborg c346ec1282 search width 2016-03-14 11:06:03 +01:00
Simon Busborg 556d4b4c11 search 2016-03-11 14:07:05 +01:00
Mads Rasmussen 7d0d58f7c2 fix notifications width 2016-03-11 13:53:50 +01:00
Mads Rasmussen a0618f401f Merge remote-tracking branch 'origin/temp-maurice' into temp-maurice 2016-03-11 13:19:48 +01:00
Mads Rasmussen 34645460fb Set position relative to contain absolute elements 2016-03-11 13:19:15 +01:00
Simon Busborg 43b534c3b1 tabs activity 2016-03-11 10:57:44 +01:00
Mads Rasmussen bc29b2e235 copy search functionality to top bar 2016-03-11 10:52:45 +01:00
Simon Busborg d6c226d41a Added navigation to sidebars 2016-03-10 15:29:41 +01:00
Simon Busborg 14d8b634b5 Acitvity feed 2016-03-10 12:45:08 +01:00
Mads Rasmussen c4e41c1df6 add a content wrapper to add padding 2016-03-10 12:20:46 +01:00
Mads Rasmussen 788efeb098 remove horizontal scrollbar in media folders 2016-03-10 11:57:00 +01:00
Mads Rasmussen 71916af49c hide generic properties tab content 2016-03-10 11:56:31 +01:00
Mads Rasmussen 55e62c01e4 hide tab instead of removing it.. now we can save again 2016-03-10 11:43:53 +01:00
Mads Rasmussen fa8dc5ace4 remove console.logs 2016-03-10 11:22:08 +01:00
Simon Busborg 671d99f455 changed menu state 2016-03-10 11:09:51 +01:00
Mads Rasmussen d681a84800 Merge branch 'temp-maurice' of https://github.com/umbraco/Umbraco-CMS into temp-maurice 2016-03-10 10:59:07 +01:00
Mads Rasmussen 440e2a7d56 bring back dashboards 2016-03-10 10:58:45 +01:00
Simon Busborg 2f8ec7bd29 Added more and added sidebar navigation status 2016-03-10 10:58:07 +01:00
Simon Busborg 5105cf890d displaying apps center 2016-03-10 10:04:32 +01:00
Mads Rasmussen 88a0f21328 align sub view header content left and right 2016-03-10 09:58:52 +01:00
Mads Rasmussen cd1ea78825 contain absolute positioned elements inside content 2016-03-10 09:33:57 +01:00
Simon Busborg ca4ff98c5f navigation fluf 2016-03-10 09:18:26 +01:00
Mads Rasmussen 339e1dc94e WIP bring in variation ideas + a couple of placeholder subviews 2016-03-10 09:16:37 +01:00
Mads Rasmussen a84c6e9dff remove generic properties tab 2016-03-10 09:15:29 +01:00
Simon Busborg ba927d1962 fixed tree navigation 2016-03-09 20:40:34 +01:00
Simon Busborg ee30f10357 Dropdown 2016-03-09 20:21:14 +01:00
Simon Busborg 478fe51651 Added tree toggler 2016-03-09 15:21:43 +01:00
Mads Rasmussen 5694beafef add subviews to content 2016-03-08 14:49:04 +01:00
Mads Rasmussen 2a1e9e30ae add generic properties icon 2016-03-07 10:01:33 +01:00
Mads Rasmussen ef5bf29b07 remove background color on footer - wireframe style 2016-03-07 09:58:42 +01:00
Mads Rasmussen 7b521e6857 um tree nav - set overflow to auto 2016-03-07 09:51:35 +01:00
Mads Rasmussen 4135e30834 add tabs to media 2016-03-05 14:03:16 +01:00
Mads Rasmussen 2b1bf0b966 add scroll to tree 2016-03-04 18:42:06 +01:00
Mads Rasmussen 6bc2ce19f5 hide search in tree 2016-03-04 18:13:21 +01:00
Mads Rasmussen 67efc1906a add editor toolbar directive - move tabs outside header for content section 2016-03-04 18:12:53 +01:00
Mads Rasmussen 8b62d09e64 remove background from editor header - wireframe look 2016-03-04 18:09:34 +01:00
Mads Rasmussen 5c6bbfb423 remove background + add border to navigation bar - wireframe look 2016-03-04 18:09:04 +01:00
Mads Rasmussen 97ff32245d fix navigation height 2016-03-04 14:43:56 +01:00
Simon Busborg b7549ad644 Fixed second header 🌮 2016-03-04 11:31:56 +01:00
Mads Rasmussen 802fe45614 Merge branch 'temp-maurice' of https://github.com/umbraco/Umbraco-CMS into temp-maurice 2016-03-04 11:05:06 +01:00
Mads Rasmussen 253a4520b0 tighten up tree a bit 2016-03-04 11:04:41 +01:00
Simon Busborg b6877dc4ce fixed header size 2016-03-04 11:03:50 +01:00
Simon Busborg 27a031ea12 Updated recess – fixed content scroll 2016-03-04 10:59:19 +01:00
Mads Rasmussen 0e2212bd40 less padding and smaller font size on top navigation 2016-03-04 10:34:18 +01:00
Simon Busborg 8ee414793f flex - content 2016-03-04 10:26:33 +01:00
Simon Busborg 1dddc06ae7 added tree 🌳 2016-03-03 16:12:07 +01:00
Simon Busborg 3d253b79e4 Added very slick navigation 🔥 2016-03-03 14:26:37 +01:00
Mads Rasmussen e7542bc455 add functionality to top bar navigation - needs styling 2016-03-03 12:56:38 +01:00
Simon Busborg 43ab5a8e2e Nuked interface 2016-03-03 10:38:01 +01:00
7618 changed files with 428760 additions and 314920 deletions
-30
View File
@@ -1,30 +0,0 @@
# editorconfig.org
# top-most EditorConfig file
root = true
# Default settings:
# A newline ending every file
# Use 4 spaces as indentation
[*]
insert_final_newline = true
end_of_line = lf
indent_style = space
indent_size = 4
# Trim trailing whitespace, limited support.
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
trim_trailing_whitespace = true
[*.{cs,vb}]
dotnet_style_predefined_type_for_locals_parameters_members = true:error
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
dotnet_naming_rule.private_members_with_underscore.severity = suggestion
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _
-49
View File
@@ -1,49 +0,0 @@
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.jpg binary
*.png binary
*.gif binary
*.cs text=auto diff=csharp
*.vb text=auto
*.c text=auto
*.cpp text=auto
*.cxx text=auto
*.h text=auto
*.hxx text=auto
*.py text=auto
*.rb text=auto
*.java text=auto
*.html text=auto
*.htm text=auto
*.css text=auto
*.scss text=auto
*.sass text=auto
*.less text=auto
*.js text=auto
*.lisp text=auto
*.clj text=auto
*.sql text=auto
*.php text=auto
*.lua text=auto
*.m text=auto
*.asm text=auto
*.erl text=auto
*.fs text=auto
*.fsx text=auto
*.hs text=auto
*.csproj text=auto merge=union
*.vbproj text=auto merge=union
*.fsproj text=auto merge=union
*.dbproj text=auto merge=union
*.sln text=auto eol=crlf merge=union
+134 -173
View File
@@ -1,173 +1,134 @@
#
# Umbraco Cms Git Ignore
#
# common files
*.obj
*.pdb
*.user
*.aps
*.pch
*.vspscc
*.orig
*.suo
*.vs10x
*.ndproj
*.log
# common directories
.DS_Store
._.DS_Store
.vs/
/local/
# build directories
[Bb]in/
[Db]ebug*/
[Rr]elease*/
obj/
# tools
_ReSharper*/
_NCrunch_*/
*.ncrunchsolution
*.ncrunchsolution.user
*.ncrunchproject
*.crunchsolution.cache
tools/NDepend/
[Tt]est[Rr]esult*
[Bb]uild[Ll]og.*
*.[Pp]ublish.xml
[sS]ource
[sS]andbox
umbraco.config
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/[Mm]acro[Ss]cripts/[Ww]eb.[Cc]onfig
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
src/Umbraco.Tests/config/applications.config
src/Umbraco.Tests/config/trees.config
src/Umbraco.Web.UI/web.config
src/Umbraco.Web.UI/Config/ClientDependency.config
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
node_modules
lib-bower
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/app.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.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/[Jj]s/tuning.panel.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.palettes.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.front.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.config.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
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/
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
src/Umbraco.Web.UI/App_Plugins/*
src/*.psess
src/*.vspx
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js.*
NDependOut/*
QueryResult.htm
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
src/Umbraco.Web.UI/[Cc]onfig/appSettings.config
src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
src/Umbraco.Web.UI/umbraco/plugins/*
src/Umbraco.Web.UI/umbraco/js/init.js
build/ApiDocs/*
build/ApiDocs/Output/*
src/Umbraco.Web.UI.Client/bower_components/*
/src/Umbraco.Web.UI/Umbraco/preview
/src/Umbraco.Web.UI/Umbraco/preview.old
# ignore rule for clearing out Belle (avoid rebuilding all the time)
preserve.belle
#Ignore Rule for output of generated documentation files from Grunt docserve
src/Umbraco.Web.UI.Client/docs/api
src/*.boltdata/
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.loader.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.palettes.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.panel.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.config.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.front.js
src/umbraco.sln.ide/*
src/.vs/
src/Umbraco.Web.UI/umbraco/js/install.loader.js
src/Umbraco.Web.UI/js/*
src/Umbraco.Tests/media
tools/docfx/*
apidocs/_site/*
src/*/project.lock.json
src/.idea/*
apidocs/api/*
build/docs.zip
build/ui-docs.zip
build/csharp-docs.zip
src/packages/
src/PrecompiledWeb/*
# build
build.out/
build.tmp/
build/hooks/
build/temp/
# eof
*.obj
*.pdb
*.user
*.aps
*.pch
*.vspscc
.DS_Store
._.DS_Store
[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/[Mm]acro[Ss]cripts/[Ww]eb.[Cc]onfig
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/UmbracoExamine.PDF*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/app.dev.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.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/[Jj]s/tuning.panel.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.palettes.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.loader.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.front.js
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.config.js
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
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/
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
tools/NDepend/
src/Umbraco.Web.UI/App_Plugins/*
src/*.psess
src/*.vspx
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js.*
NDependOut/*
*.ndproj
QueryResult.htm
*.ndproj
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
src/Umbraco.Web.UI/[Cc]onfig/appSettings.config
src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
src/Umbraco.Web.UI/umbraco/plugins/*
src/Umbraco.Web.UI/umbraco/js/init.js
build/ApiDocs/*
build/ApiDocs/Output/*
src/Umbraco.Web.UI.Client/bower_components/*
/src/Umbraco.Web.UI/Umbraco/preview
#Ignore Rule for output of generated documentation files from Grunt docserve
src/Umbraco.Web.UI.Client/docs/api
src/*.boltdata/
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.loader.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.palettes.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.panel.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.config.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.front.js
src/umbraco.sln.ide/*
build/UmbracoCms.*/
src/.vs/
src/Umbraco.Web.UI/umbraco/js/install.loader.js
-164
View File
@@ -1,164 +0,0 @@
Umbraco Cms Build
--
----
# Quick!
To build Umbraco, fire PowerShell and move to Umbraco's repository root (the directory that contains `src`, `build`, `README.md`...). There, trigger the build with the following command:
build/build.ps1
## PowerShell Quirks
There is a good chance that running `build.ps1` ends up in error, with messages such as
>The file ...\build.ps1 is not digitally signed. You cannot run this script on the current system. For more information about running scripts and setting execution policy, see about_Execution_Policies.
PowerShell has *Execution Policies* that may prevent the script from running. You can check the current policies with:
PS> Get-ExecutionPolicy -List
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser Undefined
LocalMachine RemoteSigned
Policies can be `Restricted`, `AllSigned`, `RemoteSigned`, `Unrestricted` and `Bypass`. Scopes can be `MachinePolicy`, `UserPolicy`, `Process`, `CurrentUser`, `LocalMachine`. You need the current policy to be `RemoteSigned`—as long as it is `Undefined`, the script cannot run. You can change the current user policy with:
PS> Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
Alternatively, you can do it at machine level, from within an elevated PowerShell session:
PS> Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned
And *then* the script should run. It *might* however still complain about executing scripts, with messages such as:
>Security warning - Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your computer. If you trust this script, use the Unblock-File cmdlet to allow the script to run without this warning message. Do you want to run ...\build.ps1?
[D] Do not run [R] Run once [S] Suspend [?] Help (default is "D"):
This is usually caused by the scripts being *blocked*. And that usually happens when the source code has been downloaded as a Zip file. When Windows downloads Zip files, they are marked as *blocked* (technically, they have a Zone.Identifier alternate data stream, with a value of "3" to indicate that they were downloaded from the Internet). And when such a Zip file is un-zipped, each and every single file is also marked as blocked.
The best solution is to unblock the Zip file before un-zipping: right-click the files, open *Properties*, and there should be a *Unblock* checkbox at the bottom of the dialog. If, however, the Zip file has already been un-zipped, it is possible to recursively unblock all files from PowerShell with:
PS> Get-ChildItem -Recurse *.* | Unblock-File
## Git Quirks
Git might have issues dealing with long file paths during build. You may want/need to enable `core.longpaths` support (see [this page](https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path) for details).
# Build Infrastructure
The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with:
$ubuild = build/build.ps1 -get
The object exposes various properties and methods that can be used to fine-grain build Umbraco. Some, but not all, of them are detailed below.
## Properties
The object exposes the following properties:
* `SolutionRoot`: the absolute path to the solution root
* `VisualStudio`: a Visual Studio object (see below)
* `NuGet`: the absolute path to the NuGet executable
* `Zip`: the absolute path to the 7Zip executable
* `VsWhere`: the absolute path to the VsWhere executable
* `NodePath`: the absolute path to the Node install
* `NpmPath`: the absolute path to the Npm install
The Visual Studio object is `null` when Visual Studio has not been detected (eg on VSTS). When not null, the object exposes the following properties:
* `Path`: Visual Studio installation path (eg some place under `Program Files`)
* `Major`: Visual Studio major version (eg `15` for VS 2017)
* `Minor`: Visual Studio minor version
* `MsBUild`: the absolute path to the MsBuild executable
## GetUmbracoVersion
Gets an object representing the current Umbraco version. Example:
$v = $ubuild.GetUmbracoVersion()
Write-Host $v.Semver
The object exposes the following properties:
* `Semver`: the semver object representing the version
* `Release`: the main part of the version (eg `7.6.33`)
* `Comment`: the pre release part of the version (eg `alpha02`)
* `Build`: the build number part of the version (eg `1234`)
## SetUmbracoVersion
Modifies Umbraco files with the new version.
>This entirely replaces the legacy `UmbracoVersion.txt` file. Do *not* edit version infos in files.
The version must be a valid semver version. It can include a *pre release* part (eg `alpha02`) and/or a *build number* (eg `1234`). Examples:
$ubuild.SetUmbracoVersion("7.6.33")
$ubuild.SetUmbracoVersion("7.6.33-alpha.2")
$ubuild.SetUmbracoVersion("7.6.33+1234")
$ubuild.SetUmbracoVersion("7.6.33-beta.5+5678")
## Build
Builds Umbraco. Temporary files are generated in `build.tmp` while the actual artifacts (zip files, NuGet packages...) are produced in `build.out`. Example:
$ubuild.Build()
Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build.
### web.config
Building Umbraco requires a clean `web.config` file in the `Umbraco.Web.UI` project. If a `web.config` file already exists, the `pre-build` task (see below) will save it as `web.config.temp-build` and replace it with a clean copy of `web.Template.config`. The original file is replaced once it is safe to do so, by the `pre-packages` task.
## Build-UmbracoDocs
Builds umbraco documentation. Temporary files are generated in `build.tmp` while the actual artifacts (docs...) are produced in `build.out`. Example:
Build-UmbracoDocs
Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build.
## Verify-NuGet
Verifies that projects all require the same version of their dependencies, and that NuSpec files require versions that are consistent with projects. Example:
Verify-NuGet
# VSTS
Continuous integration, nightly builds and release builds run on VSTS.
VSTS uses the `Build-Umbraco` command several times, each time passing a different *target* parameter. The supported targets are:
* `pre-build`: prepares the build
* `compile-belle`: compiles Belle
* `compile-umbraco`: compiles Umbraco
* `pre-tests`: prepares the tests
* `compile-tests`: compiles the tests
* `pre-packages`: prepares the packages
* `pkg-zip`: creates the zip files
* `pre-nuget`: prepares NuGet packages
* `pkg-nuget`: creates NuGet packages
All these targets are executed when `Build-Umbraco` is invoked without a parameter (or with the `all` parameter). On VSTS, compilations (of Umbraco and tests) are performed by dedicated VSTS tasks. Similarly, creating the NuGet packages is also performed by dedicated VSTS tasks.
Finally, the produced artifacts are published in two containers that can be downloaded from VSTS: `zips` contains the zip files while `nuget` contains the NuGet packages.
>During a VSTS build, some environment `UMBRACO_*` variables are exported by the `pre-build` target and can be reused in other targets *and* in VSTS tasks. The `UMBRACO_TMP` environment variable is used in `Umbraco.Tests` to disable some tests that have issues with VSTS at the moment.
# Notes
*This part needs to be cleaned up*
Nightlies should use some sort of build number.
We should increment versions as soon as a version is released. Ie, as soon as `7.6.33` is released, we should `Set-UmbracoVersion 7.6.34-alpha` and push.
NuGet / NuSpec consistency checks are performed in tests. We should move it so it is done as part of the PowerShell script even before we try to compile and run the tests.
/eof
-80
View File
@@ -1,80 +0,0 @@
# Code of Conduct
## 1. Purpose
A primary goal of Umbraco CMS is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.
We invite all those who participate in Umbraco CMS to help us create safe and positive experiences for everyone.
## 2. Open Source Citizenship
A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.
Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.
If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.
## 3. Expected Behavior
The following behaviors are expected and requested of all community members:
* Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.
* Exercise consideration and respect in your speech and actions.
* Attempt collaboration before conflict.
* Refrain from demeaning, discriminatory, or harassing behavior and speech.
* Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.
* Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.
## 4. Unacceptable Behavior
The following behaviors are considered harassment and are unacceptable within our community:
* Violence, threats of violence or violent language directed against another person.
* Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.
* Posting or displaying sexually explicit or violent material.
* Posting or threatening to post other peoples personally identifying information ("doxing").
* Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.
* Inappropriate photography or recording.
* Inappropriate physical contact. You should have someones consent before touching them.
* Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.
* Deliberate intimidation, stalking or following (online or in person).
* Advocating for, or encouraging, any of the above behavior.
* Sustained disruption of community events, including talks and presentations.
## 5. Consequences of Unacceptable Behavior
Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated.
Anyone asked to stop unacceptable behavior is expected to comply immediately.
If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event).
## 6. Reporting Guidelines
If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. Please contact Sebastiaan Janssen - [sj@umbraco.dk](mailto:sj@umbraco.dk).
Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress.
## 7. Addressing Grievances
If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Umbraco with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies.
## 8. Scope
We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venuesonline and in-personas well as in all one-on-one communications pertaining to community business.
This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members.
## 9. Contact info
Sebastiaan Janssen - [sj@umbraco.dk](mailto:sj@umbraco.dk)
## 10. License and attribution
This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).
Retrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/)
-209
View File
@@ -1,209 +0,0 @@
# Contributing to Umbraco CMS
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
The following is a set of guidelines for contributing to Umbraco CMS.
These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
Remember, we're a friendly bunch and are happy with whatever contribution you might provide. Below are guidelines for success that we've gathered over the years. If you choose to ignore them then we still love you 💖.
#### Table Of Contents
__[Quick start guide for Umbraco v8](https://github.com/umbraco/Umbraco-CMS/blob/temp8/V8_GETTING_STARTED.md)__
[Code of Conduct](#code-of-conduct)
[How Can I Contribute?](#how-can-i-contribute)
* [Reporting Bugs](#reporting-bugs)
* [Suggesting Enhancements](#suggesting-enhancements)
* [Your First Code Contribution](#your-first-code-contribution)
* [Pull Requests](#pull-requests)
[Styleguides](#styleguides)
[What should I know before I get started?](#what-should-i-know-before-i-get-started)
* [Working with the source code](#working-with-the-source-code)
* [What branch should I target for my contributions?](#what-branch-should-i-target-for-my-contributions)
* [Building Umbraco from source code](#building-umbraco-from-source-code)
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
[How do I even begin?](#how-do-i-even-begin)
[Problems?](#problems)
[Credits](#credits)
## Code of Conduct
This project and everyone participating in it is governed by the [our Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
## How Can I Contribute?
### Reporting Bugs
This section guides you through submitting a bug report for Umbraco CMS. Following these guidelines helps maintainers and the community understand your report 📝, reproduce the behavior 💻 💻, and find related reports 🔎.
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](http://issues.umbraco.org/issues#newissue=61-30118), the information it asks for helps us resolve issues faster.
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
##### Before Submitting A Bug Report
* Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.org/download/). We might have already fixed your particular problem.
* It also helps tremendously to check if the issue you're experiencing is present in **a clean install** of the Umbraco version you're currently using. Custom code can have side-effects that don't occur in a clean install.
* **Use the Google**. Whatever you're experiencing, Google it plus "Umbraco" - usually you can get some pretty good hints from the search results, including open issues and further troubleshooting hints.
* If you do find and existing issue has **and the issue is still open**, add a comment to the existing issue if you have additional information. If you have the same problem and no new info to add, just "star" the issue.
Explain the problem and include additional details to help maintainers reproduce the problem. The following is a long description which we've boiled down into a few very simple question in the issue tracker when you create a new issue. We're listing the following hints to indicate that the most successful reports usually have a lot of this ground covered:
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining which steps you took in the backoffice to get to a certain undesireable result, e.g. you created a document type, inherting 3 levels deep, added a certain datatype, tried to save it and you got an error.
* **Provide specific examples to demonstrate the steps**. If you wrote some code, try to provide a code sample as specific as possible to be able to reproduce the behavior.
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
Provide more context by answering these questions:
* **Can you reproduce the problem** when `debug="false"` in your `web.config` file?
* **Did the problem start happening recently** (e.g. after updating to a new version of Umbraco) or was this always a problem?
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
Include details about your configuration and environment:
* **Which version of Umbraco are you using?**
* **What is the environment you're using Umbraco in?** Is this a problem on your local machine or on a server. Tell us about your configuration: Windows version, IIS/IISExpress, database type, etc.
* **Which packages do you have installed?**
### Suggesting Enhancements
This section guides you through submitting an enhancement suggestion for Atom, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion 📝 and find related suggestions 🔎.
Most of the suggestions in the [reporting bugs](#reporting-bugs) section also count for suggesting enhancements.
Some additional hints that may be helpful:
* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Umbraco which the suggestion is related to.
* **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.org/projects/).
### Your First Code Contribution
Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` and issues](http://issues.umbraco.org/issues/U4?q=%28project%3A+%7BU4%7D+Difficulty%3A+%7BVery+Easy%7D+%23Easy+%23Unresolved+Priority%3A+Normal+%23Major+%23Show-stopper+State%3A+-%7BIn+Progress%7D+sort+by%3A+votes+Affected+versions%3A+-6.*+Affected+versions%3A+-4.*%29+OR+%28tag%3A+%7BUp+For+Grabs%7D+%23Unresolved+%29).
The issue list is sorted by total number of upvotes. While not perfect, number of upvotes is a reasonable proxy for impact a given change will have.
### Pull Requests
The most successful pull requests usually look a like this:
* Fill in the required template
* Include screenshots and animated GIFs in your pull request whenever possible.
* Unit tests, while optional are awesome, thank you!
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.org/documentation/Reference/) is generated
Again, these are guidelines, not strict requirements.
## Styleguides
To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
## What should I know before I get started?
### Working with the source code
Some parts of our source code is over 10 years old now. And when we say "old", we mean "mature" of course!
There's two big areas that you should know about:
1. The Umbraco backoffice is a extensible AngularJS app and requires you to run a `gulp dev` command while you're working with it, so changes are copied over to the appropriate directories and you can refresh your browser to view the results of your changes.
You may need to run the following commands to set up gulp properly:
```
npm cache clean
npm install -g bower
npm install -g gulp
npm install -g gulp-cli
npm install
gulp build
```
2. "The rest" is a C# based codebase, with some traces of our WebForms past but mostly ASP.NET MVC based these days. You can make changes, build them in Visual Studio, and hit `F5` to see the result.
To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation.
* [The AngularJS based backoffice files](https://our.umbraco.org/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`)
* [The rest](https://our.umbraco.org/apidocs/csharp/)
### What branch should I target for my contributions?
We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `dev-v7`. Whatever the default is, that's where we'd like you to target your contributions.
![What branch do you want me to target?](tools/contributing/defaultbranch.png)
### Building Umbraco from source code
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
![Gulp build in Visual Studio](tools/contributing/gulpbuild.png)
After this build completes, you should be able to hit `F5` in Visual Studio to build and run the project. A IISExpress webserver will start and the Umbraco installer will pop up in your browser, follow the directions there to get a working Umbraco install up and running.
### Keeping your Umbraco fork in sync with the main repository
We recommend you sync with our repository before you submit your pull request. That way, you can fix any potential merge conflicts and make our lives a little bit easier.
Also, if you've submitted a pull request three weeks ago and want to work on something new, you'll want to get the latest code to build against of course.
To sync your fork with this original one, you'll have to add the upstream url, you only have to do this once:
```
git remote add upstream https://github.com/umbraco/Umbraco-CMS.git
```
Then when you want to get the changes from the main repository:
```
git fetch upstream
git rebase upstream/dev-v7
```
In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
## How do I even begin?
Great question! The short version goes like this:
* **Fork** - create a fork of [`Umbraco-CMS` on GitHub](https://github.com/umbraco/Umbraco-CMS)
![Fork the repository](tools/contributing/forkrepository.png)
* **Clone** - when GitHub has created your fork, you can clone it in your favorite Git tool
![Clone the fork](tools/contributing/clonefork.png)
* **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](#building-umbraco-from-source-code)
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will happily give feedback
* **Commit** - done? Yay! 🎉 It is recommended to create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-U4-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `U4-12345`
* **Push** - great, now you can push the changes up to your fork on GitHub
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
![Create a pull request](tools/contributing/createpullrequest.png)
The Umbraco development team can now start reviewing your proposed changes and give you feedback on them. If it's not perfect, we'll either fix up what we need or we can request you to make some additional changes.
If you make the corrections we ask for in the same branch and push them to your fork again, the pull request automatically updates with the additional commit(s) so we can review it again. If all is well, we'll merge the code and your commits are forever part of Umbraco!
Not all changes are wanted so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes at this and we'll be nice about it, thanking you for spending your valueable time.
Remember, if an issue is in the `Up for grabs` list or you've asked for some feedback before you send us a PR, your PR will not be closed as unwanted.
## Problems?
Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely!
## Credits
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
-12
View File
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--
this is Umbraco's NuGet configuration,
content of this file is merged with the system-wide configuration,
at %APPDATA%\NuGet\NuGet.config
-->
<packageSources>
<add key="UmbracoCoreMyGet" value="https://www.myget.org/F/umbracocore/api/v3/index.json" />
<add key="ExamineAppVeyor" value="https://ci.appveyor.com/nuget/examine-f73l6qv0oqfh/" />
</packageSources>
</configuration>
-11
View File
@@ -1,11 +0,0 @@
### Prerequisites
- [ ] I have written a descriptive pull-request title
- [ ] I have linked this PR to an issue on the tracker at http://issues.umbraco.org
### Description
<!-- A description of the changes proposed in the pull-request -->
<!-- Thanks for contributing to Umbraco CMS! -->
+19 -28
View File
@@ -1,49 +1,40 @@
_Looking for Umbraco version 7? [Click here](https://github.com/umbraco/Umbraco-CMS) to go to the v7 branch_
__Ready to try out Version 8? [See the quick start guide](https://github.com/umbraco/Umbraco-CMS/blob/temp8/V8_GETTING_STARTED.md).__
Umbraco CMS
===========
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
Umbraco is a free open source Content Management System built on the ASP.NET platform.
[![ScreenShot](vimeo.png)](https://vimeo.com/172382998/)
## Building Umbraco from source ##
The easiest way to get started is to run `build/build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `grunt dev` in `src\Umbraco.Web.UI.Client`.
If you're interested in making changes to Belle make sure to read the [Belle ReadMe file](src/Umbraco.Web.UI.Client/README.md). Note that you can always [download a nightly build](http://nightly.umbraco.org/umbraco%207.0.0/) so you don't have to build the code yourself.
## Umbraco CMS
Umbraco is a free open source Content Management System built on the ASP.NET platform. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
## Watch an introduction video
## Watch a introduction video ##
[![ScreenShot](http://umbraco.com/images/whatisumbraco.png)](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
## Umbraco - The Friendly CMS
## Umbraco - the simple, flexible and friendly ASP.NET CMS ##
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box.
**More than 177,000 sites trust Umbraco**
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box. It's a developer's dream and your users will love it too.
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
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 [https://umbraco.com/why-umbraco/#caseStudies](https://umbraco.com/why-umbraco/#caseStudies)
To view more examples, please visit [http://umbraco.com/why-umbraco/#caseStudies](http://umbraco.com/why-umbraco/#caseStudies)
## Why Open Source?
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible and community contributions and packages are available for all to use.
## Downloading ##
## Trying out Umbraco CMS
The downloadable Umbraco releases live at [http://our.umbraco.org/download](http://our.umbraco.org/download).
[Umbraco Cloud](https://umbraco.com) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
## Forums ##
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
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).
## Community
## Contribute to Umbraco ##
Our friendly community is available 24/7 at the community hub we call ["Our Umbraco"](https://our.umbraco.org). Our Umbraco feature forums for questions and answers, documentation, downloadable plugins for Umbraco and a rich collection of community resources.
If you want to contribute back to Umbraco you should check out our [guide to contributing](http://our.umbraco.org/contribute).
## Contribute to Umbraco
## Found a bug? ##
Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](CONTRIBUTING.md).
## 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](https://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
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).
-30
View File
@@ -1,30 +0,0 @@
## A quick start guide for getting up and runnning with Umbraco v8
### What you need:
* [Visual Studio 2017 Community (Free)](https://www.visualstudio.com/vs/community/), or Professional, Enterprise, etc...
* .NET Framework 4.7.2 installed, get it here: https://www.microsoft.com/net/download/thank-you/net472?survey=false
* .NET Framework 4.7.2 developer pack, get it here: https://www.microsoft.com/net/download/thank-you/net472-developer-pack _(be sure this is the ENU file which will be named `NDP472-DevPack-ENU.exe`)_
* Clone the Umbraco repository and ensure you have the `temp8` branch checked out
### Start the solution
* Open the `/src/umbraco.sln` Visual Studio solution
* Start the solution (easiest way is to use `ctrl + F5`)
* When the solution is first built this may take some time since it will restore all nuget, npm and bower packages, build the .net solution and also build the angular solution.
* When the website starts you'll see the Umbraco installer and just follow the prompts
* Your all set!
### Making code changes
* _The process for making code changes in v8 is the same as v7_
* Any .NET changes you make you just need to compile
* Any Angular/JS changes you make you will need to make sure you are running the Gulp build. Easiest way to do this is from within Visual Studio in the `Task Runner Explorer`. You can find this window by pressing `ctrl + q` and typing in `Task Runner Explorer`. In this window you'll see all Gulp tasks, double click on the `dev` task, this will compile the angular solution and start a file watcher, then any html/js changes you make are automatically built.
* When making js changes, you should have the chrome developer tools open to ensure that cache is disabled
### What to work on?
We are keeping track of [known issues and limitations here](http://issues.umbraco.org/issue/U4-11279). These line items will eventually be turned into actual tasks to be worked on. Feel free to help us keep this list updated if you find issues and even help fix some of these items. If there is a particular item you'd like to help fix please mention this on the task and we'll create a sub task for the item to continue discussion there.
There's [a list of tasks for v8 that haven't been completed](http://issues.umbraco.org/issues/U4?q=Due+in+version%3A+8.0.0+%23Unresolved+). If you are interested in helping out with any of these please mention this on the task. This list will be constantly updated as we begin to document and design some of the other tasks that still need to get done.
+170
View File
@@ -0,0 +1,170 @@
/* File : TOC.css
// Author : Eric Woodruff (Eric@EWoodruff.us)
// Updated : 09/07/2007
//
// Stylesheet for the table of content
*/
*
{
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
}
body
{
font-family: Segoe UI, Arial, Verdana, Helvetica, sans-serif;
font-size: 0.9em;
background-color: white;
color: White;
overflow: hidden;
}
input
{
padding:5px;
margin: 3px 0px 3px 0px
}
img
{
border: 0;
margin-left: 5px;
margin-right: 2px;
}
img.TreeNodeImg
{
cursor: pointer;
}
img.TOCLink
{
cursor: pointer;
margin-left: 0;
margin-right: 0;
}
a.SelectedNode, a.UnselectedNode
{
color: #333;
text-decoration: none;
padding: 1px 3px 1px 3px;
white-space: nowrap;
}
a.SelectedNode
{
background-color: #ffffff;
border: solid 1px #999999;
padding: 0px 2px 0px 2px;
}
a.UnselectedNode:hover, a.SelectedNode:hover
{
background-color: #cccccc;
border: solid 1px #999999;
padding: 0px 2px 0px 2px;
}
.Visible
{
display: block;
margin-left: 2em;
}
.Hidden
{
display: none;
}
.Tree
{
background-color: #fff;
color: #333;
width: 300px;
overflow: auto;
}
.TreeNode, .TreeItem
{
white-space: nowrap;
margin: 2px 2px 2px 2px;
}
.TOCDiv
{
position: relative;
float: left;
width: 300px;
height: 100%;
}
.TOCSizer
{
clear: none;
float: left;
width: 10px;
height: 100%;
background-image: url("Splitter.gif");
background-position:center center;
background-repeat:no-repeat;
position: relative;
cursor: w-resize;
border-left: solid 1px #CCC;
}
.TopicContent
{
position: relative;
float: right;
background-color: white;
height: 100%;
}
.SearchOpts
{
padding: 5px 5px 10px 5px;
color: black;
width: 300px;
border-bottom: solid lightgrey 1px;
height: 110px !important;
}
.NavOpts
{
padding: 5px 5px 6px 5px;
color: black;
width: 300px;
border-bottom: solid lightgrey 1px;
}
.NavOpts img {
display:inline-block;
margin: 0px 5px 0px 5px;
}
.IndexOpts
{
padding: 5px 5px 6px 5px;
color: black;
width: 300px;
border-bottom: solid lightgrey 1px;
}
.IndexItem
{
white-space: nowrap;
margin: 2px 2px 2px 2px;
}
.IndexSubItem
{
white-space: nowrap;
margin: 2px 2px 2px 12px;
}
.PaddedText
{
margin: 10px 10px 10px 10px;
}
+172
View File
@@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<!-- The configuration and platform will be used to determine which
assemblies to include from solution and project documentation
sources -->
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{cb4d85f1-7390-40ee-b41f-a724bb8fddea}</ProjectGuid>
<SHFBSchemaVersion>1.9.5.0</SHFBSchemaVersion>
<!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
Studio adds them anyway -->
<AssemblyName>Documentation</AssemblyName>
<RootNamespace>Documentation</RootNamespace>
<Name>Documentation</Name>
<!-- SHFB properties -->
<FrameworkVersion>.NET Framework 4.5</FrameworkVersion>
<OutputPath>.\Output\</OutputPath>
<HtmlHelpName>UmbracoClassLibrary</HtmlHelpName>
<Language>en-US</Language>
<BuildAssemblerVerbosity>OnlyErrors</BuildAssemblerVerbosity>
<BuildLogFile>csharp-api-docs.log</BuildLogFile>
<HelpFileFormat>Website</HelpFileFormat>
<IndentHtml>True</IndentHtml>
<KeepLogFile>False</KeepLogFile>
<DisableCodeBlockComponent>False</DisableCodeBlockComponent>
<CppCommentsFixup>False</CppCommentsFixup>
<CleanIntermediates>True</CleanIntermediates>
<SyntaxFilters>CSharp</SyntaxFilters>
<SdkLinkTarget>Blank</SdkLinkTarget>
<RootNamespaceContainer>False</RootNamespaceContainer>
<PresentationStyle>VS2010</PresentationStyle>
<Preliminary>False</Preliminary>
<NamingMethod>Guid</NamingMethod>
<HelpTitle>Umbraco .Net Class Library</HelpTitle>
<ContentPlacement>AboveNamespaces</ContentPlacement>
<VisibleItems>Attributes, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected</VisibleItems>
<ComponentConfigurations />
<DocumentationSources>
<DocumentationSource sourceFile="..\..\src\Umbraco.Core\Umbraco.Core.csproj" />
<DocumentationSource sourceFile="..\..\src\Umbraco.Core\bin\Release\Umbraco.Core.xml" />
<DocumentationSource sourceFile="..\..\src\Umbraco.Web\Umbraco.Web.csproj" />
<DocumentationSource sourceFile="..\..\src\Umbraco.Web\bin\Release\umbraco.xml" /></DocumentationSources>
<WebsiteSdkLinkType>None</WebsiteSdkLinkType>
<HtmlSdkLinkType>None</HtmlSdkLinkType>
<IncludeFavorites>False</IncludeFavorites>
<BinaryTOC>True</BinaryTOC>
<MissingTags>Summary, AutoDocumentCtors, AutoDocumentDispose</MissingTags>
<TransformComponentArguments>
<Argument Key="logoFile" Value="" />
<Argument Key="logoHeight" Value="" />
<Argument Key="logoWidth" Value="" />
<Argument Key="logoAltText" Value="" />
<Argument Key="logoPlacement" Value="left" />
<Argument Key="logoAlignment" Value="left" />
</TransformComponentArguments>
<ApiFilter>
<Filter entryType="Namespace" fullName="CookComputing.Blogger" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="CookComputing.MetaWeblog" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="dashboardUtilities" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="presentation.umbraco.webservices" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco" isExposed="False" xmlns="">
<Filter entryType="Class" fullName="umbraco.content" filterName="content" isExposed="True" />
<Filter entryType="Delegate" fullName="umbraco.content.ContentCacheDatabaseLoadXmlStringEventHandler" filterName="content.ContentCacheDatabaseLoadXmlStringEventHandler" isExposed="False" />
<Filter entryType="Delegate" fullName="umbraco.content.ContentCacheLoadNodeEventHandler" filterName="content.ContentCacheLoadNodeEventHandler" isExposed="False" />
<Filter entryType="Delegate" fullName="umbraco.content.DocumentCacheEventHandler" filterName="content.DocumentCacheEventHandler" isExposed="False" />
<Filter entryType="Delegate" fullName="umbraco.content.RefreshContentEventHandler" filterName="content.RefreshContentEventHandler" isExposed="False" />
<Filter entryType="Class" fullName="umbraco.ContentExtensions" filterName="ContentExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.ContentTypeExtensions" filterName="ContentTypeExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.item" filterName="item" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.library" filterName="library" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.macro" filterName="macro" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.MacroCacheContent" filterName="MacroCacheContent" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.MacroRenderingEventArgs" filterName="MacroRenderingEventArgs" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.MediaExtensions" filterName="MediaExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.MemberExtensions" filterName="MemberExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.page" filterName="page" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.PreValueExtensions" filterName="PreValueExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.RelationTypeExtensions" filterName="RelationTypeExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.template" filterName="template" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.UmbracoObjectTypeExtensions" filterName="UmbracoObjectTypeExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.uQuery" filterName="uQuery" isExposed="True" />
<Filter entryType="Interface" fullName="umbraco.uQuery.IGetProperty" filterName="uQuery.IGetProperty" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.uQuery.Members" filterName="uQuery.Members" isExposed="True" />
<Filter entryType="Enumeration" fullName="umbraco.uQuery.UmbracoObjectType" filterName="uQuery.UmbracoObjectType" isExposed="True" />
</Filter>
<Filter entryType="Namespace" fullName="umbraco.cms.presentation" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.create.controls" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.developer" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.developer.RelationTypes" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.developer.RelationTypes.TreeMenu" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.members" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.settings" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.settings.modal" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.settings.scripts" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.settings.stylesheet" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.user" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.controls" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.controls.GenericProperties" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.controls.Images" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.controls.Tree" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.developer" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.dialogs" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.js" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.layoutControls" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.NodeFactory" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.actions" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.channels" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.channels.businesslogic" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.create" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.developer.packages" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.dialogs" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.masterpages" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.members" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.nodeFactory" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.org.umbraco.update" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.plugins.tinymce3" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.preview" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.Search" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.settings" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.templateControls" isExposed="False" xmlns="">
<Filter entryType="Class" fullName="umbraco.presentation.templateControls.Item" filterName="Item" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.presentation.templateControls.ItemRenderer" filterName="ItemRenderer" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.presentation.templateControls.Macro" filterName="Macro" isExposed="True" />
<Filter entryType="Enumeration" fullName="umbraco.presentation.templateControls.Macro.RenderEvents" filterName="Macro.RenderEvents" isExposed="False" />
</Filter>
<Filter entryType="Namespace" fullName="umbraco.presentation.tinymce3" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.translation" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.channels" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.controls" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.create" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.developer.Xslt" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.dialogs" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.masterpages" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.members" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.plugins.tinymce3" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.Search" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.translation" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.webservices" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco_client.tinymce3.plugins.spellchecker" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.urlRewriter" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.Web.UI" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.webservices" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.scripting" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.settings" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="Umbraco.Web.org.umbraco.our" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.webservices" isExposed="False" xmlns="" /></ApiFilter>
</PropertyGroup>
<!-- There are no properties for these groups. AnyCPU needs to appear in
order for Visual Studio to perform the build. The others are optional
common platform types that may appear. -->
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
</PropertyGroup>
<!-- Import the SHFB build targets -->
<Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
</Project>
-59
View File
@@ -1,59 +0,0 @@
Param(
[string]$GitHubPersonalAccessToken,
[string]$Directory
)
$workingDirectory = $Directory
CD $workingDirectory
# Clone repo
$fullGitUrl = "https://$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
git clone $fullGitUrl 2>&1 | % { $_.ToString() }
# Remove everything so that unzipping the release later will update everything
# Don't remove the readme file nor the git directory
Write-Host "Cleaning up git directory before adding new version"
Remove-Item -Recurse $workingDirectory\$env:GIT_REPOSITORYNAME\* -Exclude README.md,.git
# Find release zip
$zipsDir = "$workingDirectory\$env:BUILD_DEFINITIONNAME\zips"
$pattern = "UmbracoCms.([0-9]{1,2}.[0-9]{1,3}.[0-9]{1,3}).zip"
Write-Host "Searching for Umbraco release files in $workingDirectory\$zipsDir for a file with pattern $pattern"
$file = (Get-ChildItem $zipsDir | Where-Object { $_.Name -match "$pattern" })
if($file)
{
# Get release name
$version = [regex]::Match($file.Name, $pattern).captures.groups[1].value
$releaseName = "Umbraco $version"
Write-Host "Found $releaseName"
# Unzip into repository to update release
Add-Type -AssemblyName System.IO.Compression.FileSystem
Write-Host "Unzipping $($file.FullName) to $workingDirectory\$env:GIT_REPOSITORYNAME"
[System.IO.Compression.ZipFile]::ExtractToDirectory("$($file.FullName)", "$workingDirectory\$env:GIT_REPOSITORYNAME")
# Telling git who we are
git config --global user.email "coffee@umbraco.com" 2>&1 | % { $_.ToString() }
git config --global user.name "Umbraco HQ" 2>&1 | % { $_.ToString() }
# Commit
CD $env:GIT_REPOSITORYNAME
Write-Host "Committing Umbraco $version Release from Build Output"
git add . 2>&1 | % { $_.ToString() }
git commit -m " Release $releaseName from Build Output" 2>&1 | % { $_.ToString() }
# Tag the release
git tag -a "v$version" -m "v$version"
# Push release to master
$fullGitAuthUrl = "https://$($env:GIT_USERNAME):$GitHubPersonalAccessToken@$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
git push $fullGitAuthUrl 2>&1 | % { $_.ToString() }
#Push tag to master
git push $fullGitAuthUrl --tags 2>&1 | % { $_.ToString() }
}
else
{
Write-Error "Umbraco release file not found, searched in $workingDirectory\$zipsDir for a file with pattern $pattern - cancelling"
}
+58
View File
@@ -0,0 +1,58 @@
@ECHO OFF
IF NOT EXIST UmbracoVersion.txt (
ECHO UmbracoVersion.txt missing!
GOTO :showerror
)
REM Get the version and comment from UmbracoVersion.txt lines 2 and 3
SET "release="
SET "comment="
FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i"
FOR /F "skip=2 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED comment SET "comment=%%i"
REM If there's arguments on the command line overrule UmbracoVersion.txt and use that as the version
IF [%1] NEQ [] (SET release=%1)
IF [%2] NEQ [] (SET comment=%2) ELSE (IF [%1] NEQ [] (SET "comment="))
SET version=%release%
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
ECHO Building Umbraco %version%
ReplaceIISExpressPortNumber.exe ..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj %release%
ECHO Removing the belle build folder and bower_components folder to make sure everything is clean as a whistle
RD ..\src\Umbraco.Web.UI.Client\build /Q /S
RD ..\src\Umbraco.Web.UI.Client\bower_components /Q /S
ECHO Removing existing built files to make sure everything is clean as a whistle
RMDIR /Q /S _BuildOutput
DEL /F /Q UmbracoCms.*.zip
DEL /F /Q UmbracoExamine.*.zip
DEL /F /Q UmbracoCms.*.nupkg
DEL /F /Q webpihash.txt
ECHO Making sure Git is in the path so that the build can succeed
CALL InstallGit.cmd
ECHO Performing MSBuild and producing Umbraco binaries zip files
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment% /verbosity:minimal
ECHO Setting node_modules folder to hidden to prevent VS13 from crashing on it while loading the websites project
attrib +h ..\src\Umbraco.Web.UI.Client\node_modules
ECHO Adding Web.config transform files to the NuGet package
REN .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
REN .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
ECHO Packing the NuGet release files
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version% -Symbols -Verbosity quiet
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %version% -Verbosity quiet
IF ERRORLEVEL 1 GOTO :showerror
ECHO No errors were detected but you still may see some in the output, then it's time to investigate.
ECHO You might see some warnings but that is completely normal.
GOTO :EOF
:showerror
PAUSE
+347
View File
@@ -0,0 +1,347 @@
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
****************************************************
INCLUDES
*****************************************************
-->
<PropertyGroup>
<MSBuildCommunityTasksPath>..\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
<UmbracoMSBuildTasksPath>..\UmbracoMSBuildTasks</UmbracoMSBuildTasksPath>
</PropertyGroup>
<Import Project="..\tools\UmbracoMSBuildTasks\Umbraco.MSBuild.Tasks.Targets" />
<Import Project="..\tools\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<UsingTask TaskName="GenerateHash" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<InputFiles ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<OutputFile ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System.IO" />
<Using Namespace="System.Linq" />
<Using Namespace="System.Security.Cryptography" />
<Code Type="Fragment" Language="cs">
<![CDATA[
using (var ms = new MemoryStream())
{
foreach (var item in InputFiles)
{
string path = item.ItemSpec;
using (FileStream stream = new FileStream(path, FileMode.Open))
{
using (var cryptoProvider = new SHA1CryptoServiceProvider())
{
var fileHash = cryptoProvider.ComputeHash(stream);
using (TextWriter w = new StreamWriter(OutputFile, false))
{
w.WriteLine(string.Join("", fileHash.Select(b => b.ToString("x2"))));
}
}
}
}
}
]]>
</Code>
</Task>
</UsingTask>
<!--
****************************************************
VARIABLES
*****************************************************
-->
<!-- NB: BUILD_NUMBER is passed in by the build server -->
<PropertyGroup Condition="'$(BUILD_NUMBER)'!=''">
<DECIMAL_BUILD_NUMBER>.$(BUILD_NUMBER)</DECIMAL_BUILD_NUMBER>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_RELEASE)'!=''">
<DECIMAL_BUILD_NUMBER>.$(BUILD_RELEASE)</DECIMAL_BUILD_NUMBER>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_RELEASE)'!='' AND '$(BUILD_COMMENT)'!=''">
<DECIMAL_BUILD_NUMBER>.$(BUILD_RELEASE)-$(BUILD_COMMENT)</DECIMAL_BUILD_NUMBER>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_RELEASE)'!='' AND '$(BUILD_NIGHTLY)'!=''">
<DECIMAL_BUILD_NUMBER>.$(BUILD_RELEASE)-$(BUILD_NIGHTLY)</DECIMAL_BUILD_NUMBER>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_RELEASE)'!='' AND '$(BUILD_COMMENT)'!='' AND '$(BUILD_NIGHTLY)'!=''">
<DECIMAL_BUILD_NUMBER>.$(BUILD_RELEASE)-$(BUILD_COMMENT)-$(BUILD_NIGHTLY)</DECIMAL_BUILD_NUMBER>
</PropertyGroup>
<PropertyGroup>
<BuildConfiguration>Release</BuildConfiguration>
<BuildFolder>_BuildOutput\</BuildFolder>
<BuildZipFileName>UmbracoCms$(DECIMAL_BUILD_NUMBER).zip</BuildZipFileName>
<BuildZipFileNameBin>UmbracoCms.AllBinaries$(DECIMAL_BUILD_NUMBER).zip</BuildZipFileNameBin>
<BuildZipFileNameWebPi>UmbracoCms.WebPI$(DECIMAL_BUILD_NUMBER).zip</BuildZipFileNameWebPi>
<IncludeSymbols>False</IncludeSymbols>
<BuildFolderRelativeToProjects>..\..\build\$(BuildFolder)</BuildFolderRelativeToProjects>
<BuildFolderAbsolutePath>$(MSBuildProjectDirectory)\$(BuildFolder)</BuildFolderAbsolutePath>
<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>
<WebAppFolderAbsolutePath>$(BuildFolderAbsolutePath)WebApp\</WebAppFolderAbsolutePath>
<WebPiFolderRelativeToProjects>$(BuildFolderRelativeToProjects)WebPi\</WebPiFolderRelativeToProjects>
<WebPiFolderAbsolutePath>$(BuildFolderAbsolutePath)WebPi\</WebPiFolderAbsolutePath>
</PropertyGroup>
<ItemGroup>
<SystemFolders Include="$(WebAppFolder)App_Data" />
<SystemFolders Include="$(WebAppFolder)Media" />
<SystemFolders Include="$(WebAppFolder)Views" />
</ItemGroup>
<!--
****************************************************
TARGETS
*****************************************************
-->
<Target Name="Build" DependsOnTargets="GenerateWebPiHash">
<Message Text="Build finished" />
</Target>
<Target Name="GenerateWebPiHash" DependsOnTargets="ZipWebPiApp">
<ItemGroup>
<WebPiFile Include="$(BuildZipFileNameWebPi)" />
</ItemGroup>
<Message Text="Calculating hash for $(BuildZipFileNameWebPi)" />
<GenerateHash InputFiles="@(WebPiFile)" OutputFile="webpihash.txt" />
</Target>
<Target Name="CleanUp" DependsOnTargets="ZipWebPiApp">
<Message Text="Deleting $(BuildFolder)" Importance="high" />
<RemoveDir Directories="$(BuildFolder)" />
<Message Text="Finished deleting $(BuildFolder)" Importance="high" />
</Target>
<Target Name="ZipWebPiApp" DependsOnTargets="ZipWebApp" >
<!-- Clean folders -->
<RemoveDir Directories="$(WebPiFolder)" />
<MakeDir Directories="$(WebPiFolder)" />
<MakeDir Directories="$(WebPiFolder)umbraco" />
<!-- Copy fresh built umbraco files -->
<Exec Command="xcopy %22$(WebAppFolderAbsolutePath)*%22 %22$(WebPiFolderAbsolutePath)umbraco%22 /S /E /Y /I" />
<!-- Copy Web Pi template files -->
<ItemGroup>
<WebPiFiles Include="..\src\WebPi\**\*.*" />
</ItemGroup>
<Copy SourceFiles="@(WebPiFiles)"
DestinationFiles="@(WebPiFiles->'$(WebPiFolder)%(RecursiveDir)%(Filename)%(Extension)')" />
<!-- Zip the files -->
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameWebPi)%22 %22$(WebPiFolderAbsolutePath)*%22 -x!dotLess.Core.dll -x![Content_Types].xml >NUL" />
</Target>
<Target Name="ZipWebApp" DependsOnTargets="CreateSystemFolders" >
<Message Text="Starting to zip to $(buildDate)-$(BuildZipFileName)" Importance="high" />
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameBin)%22 %22$(SolutionBinFolderAbsolutePath)*%22 -x!dotLess.Core.dll >NUL" />
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileName)%22 %22$(WebAppFolderAbsolutePath)*%22 -x!dotLess.Core.dll -x![Content_Types].xml >NUL" />
<Message Text="Finished zipping to build\$(BuildFolder)\$(buildDate)-$(BuildZipFileName)" Importance="high" />
</Target>
<Target Name="CreateSystemFolders" DependsOnTargets="CopyBelleBuild" Inputs="@(SystemFolders)" Outputs="%(Identity).Dummy">
<MakeDir Directories="@(SystemFolders)" />
</Target>
<Target Name="CopyBelleBuild" DependsOnTargets="CopyLibraries" >
<ItemGroup>
<BelleFiles Include="..\src\Umbraco.Web.UI.Client\build\belle\**\*.*" Exclude="..\src\Umbraco.Web.UI.Client\build\belle\index.html" />
</ItemGroup>
<Copy SourceFiles="@(BelleFiles)"
DestinationFiles="@(BelleFiles->'$(WebAppFolder)umbraco\%(RecursiveDir)%(Filename)%(Extension)')"
OverwriteReadOnlyFiles="true"
SkipUnchangedFiles="false" />
</Target>
<Target Name="CopyLibraries" DependsOnTargets="OffsetTimestamps" >
<!-- Copy SQL CE -->
<ItemGroup>
<SQLCE4Files
Include="..\src\packages\SqlServerCE.4.0.0.1\**\*.*"
Exclude="..\src\packages\SqlServerCE.4.0.0.1\lib\**\*;..\src\packages\SqlServerCE.4.0.0.1\**\*.nu*"
/>
</ItemGroup>
<Copy SourceFiles="@(SQLCE4Files)"
DestinationFiles="@(SQLCE4Files->'$(SolutionBinFolder)%(RecursiveDir)%(Filename)%(Extension)')"
OverwriteReadOnlyFiles="true"
SkipUnchangedFiles="false" />
<Copy SourceFiles="@(SQLCE4Files)"
DestinationFiles="@(SQLCE4Files->'$(WebAppFolder)bin\%(RecursiveDir)%(Filename)%(Extension)')"
OverwriteReadOnlyFiles="true"
SkipUnchangedFiles="false" />
</Target>
<!-- Offset the modified timestamps on all umbraco dlls, as WebResources break if date is in the future, which, due to timezone offsets can happen. -->
<Target Name="OffsetTimestamps" DependsOnTargets="CopyTransformedWebConfig">
<CreateItem Include="$(BuildFolder)**\umbraco.*.dll">
<Output TaskParameter="Include" ItemName="FilesToOffsetTimestamp" />
</CreateItem>
<Message Text="Starting to offset timestamps" Importance="high" />
<Umbraco.MSBuild.Tasks.TimestampOffset Files="@(FilesToOffsetTimestamp)" Offset="-11" />
<Message Text="Finished offsetting timestamps" Importance="high" />
</Target>
<!-- Copy the transformed web.config file to the root -->
<Target Name="CopyTransformedWebConfig" DependsOnTargets="CopyTransformedConfig">
<ItemGroup>
<WebConfigFile Include="..\src\Umbraco.Web.UI\web.$(BuildConfiguration).Config.transformed" />
</ItemGroup>
<Copy SourceFiles="@(WebConfigFile)"
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;$(WebAppFolder)config\*.js" />
<CustomLanguageFiles Include="$(WebAppFolder)config\lang\*.xml" />
<WebConfigTransformFile Include="$(WebAppFolder)Web.config" />
</ItemGroup>
<Copy SourceFiles="@(ConfigFiles)"
DestinationFiles="@(ConfigFiles->'$(ConfigsFolder)\%(RecursiveDir)%(Filename)%(Extension)')"
OverwriteReadOnlyFiles="true"
SkipUnchangedFiles="false" />
<Copy SourceFiles="@(CustomLanguageFiles)"
DestinationFiles="@(CustomLanguageFiles->'$(ConfigsFolder)Lang\%(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 -->
<Target Name="CopyXmlDocumentation" DependsOnTargets="CleanupPresentation">
<ItemGroup>
<XmlDocumentationFiles Include="$(SolutionBinFolder)*.xml" />
</ItemGroup>
<Copy SourceFiles="@(XmlDocumentationFiles)"
DestinationFiles="@(XmlDocumentationFiles->'$(WebAppFolder)bin\%(RecursiveDir)%(Filename)%(Extension)')"
OverwriteReadOnlyFiles="true"
SkipUnchangedFiles="false" />
<Message Text="CopyXmlDocumentation" />
</Target>
<!-- Unlike 2010, the VS2012 build targets file doesn't clean up the umbraco.presentation dir, do it manually -->
<Target Name="CleanupPresentation" DependsOnTargets="CompileProjects">
<ItemGroup>
<PresentationFolderToDelete Include="$(WebAppFolder)umbraco.presentation" />
</ItemGroup>
<RemoveDir Directories="@(PresentationFolderToDelete)" />
</Target>
<Target Name="CompileProjects" DependsOnTargets="SetVersionNumber">
<Message Text="Compiling web project to build\$(BuildFolder)" Importance="high" />
<!-- For UseWPP_CopyWebApplication=True see http://stackoverflow.com/questions/1983575/copywebapplication-with-web-config-transformations -->
<!-- Build the Umbraco.Web.UI project -->
<MSBuild Projects="..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj" Properties="WarningLevel=0;Configuration=$(BuildConfiguration);UseWPP_CopyWebApplication=True;PipelineDependsOnBuild=False;OutDir=$(SolutionBinFolderAbsolutePath);WebProjectOutputDir=$(WebAppFolderAbsolutePath);Verbosity=minimal" Targets="Clean;Rebuild;" BuildInParallel="False" ToolsVersion="4.0" UnloadProjectsOnCompletion="False">
</MSBuild>
<!-- DONE -->
<Message Text="Finished compiling projects" Importance="high" />
</Target>
<Target Name="SetVersionNumber" Condition="'$(BUILD_RELEASE)'!=''">
<PropertyGroup>
<NewVersion>$(BUILD_RELEASE)</NewVersion>
<NewVersion Condition="'$(BUILD_COMMENT)'!=''">$(BUILD_RELEASE)-$(BUILD_COMMENT)</NewVersion>
<NewVersion Condition="'$(BUILD_NIGHTLY)'!=''">$(BUILD_RELEASE)-$(BUILD_NIGHTLY)</NewVersion>
<NewVersion Condition="'$(BUILD_COMMENT)'!='' And '$(BUILD_NIGHTLY)'!=''">$(BUILD_RELEASE)-$(BUILD_COMMENT)-$(BUILD_NIGHTLY)</NewVersion>
</PropertyGroup>
<!-- Match & replace 3 and 4 digit version numbers and -beta and +nightly (if they're there) -->
<FileUpdate
Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
Regex="(\d+)\.(\d+)\.(\d+)(.(\d+))?"
ReplacementText="$(BUILD_RELEASE)"/>
<FileUpdate Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
Regex="CurrentComment { get { return &quot;(.+)?&quot;"
ReplacementText="CurrentComment { get { return &quot;$(BUILD_COMMENT)&quot;"/>
<FileUpdate Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
Condition="'$(BUILD_NIGHTLY)'!=''"
Regex="CurrentComment { get { return &quot;(.+)?&quot;"
ReplacementText="CurrentComment { get { return &quot;$(BUILD_NIGHTLY)&quot;"/>
<FileUpdate Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
Condition="'$(BUILD_COMMENT)'!='' AND '$(BUILD_NIGHTLY)'!=''"
Regex="CurrentComment { get { return &quot;(.+)?&quot;"
ReplacementText="CurrentComment { get { return &quot;$(BUILD_COMMENT)-$(BUILD_NIGHTLY)&quot;"/>
<!--This updates the AssemblyFileVersion for the solution to the umbraco version-->
<FileUpdate
Files="..\src\SolutionInfo.cs"
Regex="AssemblyFileVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyFileVersion(&quot;$(BUILD_RELEASE)&quot;)"/>
<!--This updates the AssemblyInformationalVersion for the solution to the umbraco version and comment-->
<FileUpdate
Condition="'$(BUILD_COMMENT)'!=''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)-$(BUILD_COMMENT)&quot;)"/>
<FileUpdate
Condition="'$(BUILD_COMMENT)'==''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)&quot;)"/>
<FileUpdate
Condition="'$(BUILD_NIGHTLY)'!=''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)-$(BUILD_NIGHTLY)&quot;)"/>
<FileUpdate
Condition="'$(BUILD_COMMENT)'!='' AND '$(BUILD_NIGHTLY)'!=''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)-$(BUILD_COMMENT)-$(BUILD_NIGHTLY)&quot;)"/>
<FileUpdate
Condition="'$(BUILD_COMMENT)'=='' AND '$(BUILD_NIGHTLY)'==''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)&quot;)"/>
<!--This updates the copyright year-->
<FileUpdate
Files="..\src\SolutionInfo.cs"
Regex="AssemblyCopyright\(&quot;Copyright © Umbraco (\d{4})&quot;\)"
ReplacementText="AssemblyCopyright(&quot;Copyright © Umbraco $([System.DateTime]::Now.ToString(`yyyy`))&quot;)"/>
<XmlPoke XmlInputPath=".\NuSpecs\build\UmbracoCms.props"
Namespaces="&lt;Namespace Prefix='x' Uri='http://schemas.microsoft.com/developer/msbuild/2003' /&gt;"
Query="//x:UmbracoVersion"
Value="$(NewVersion)" />
</Target>
</Project>
+32
View File
@@ -0,0 +1,32 @@
@ECHO OFF
SETLOCAL
SET release=%1
ECHO Installing Npm NuGet Package
SET nuGetFolder=%CD%\..\src\packages\
ECHO Configured packages folder: %nuGetFolder%
ECHO Current folder: %CD%
%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder% -Verbosity quiet
for /f "delims=" %%A in ('dir %nuGetFolder%node.js.* /b') do set "nodePath=%nuGetFolder%%%A\"
for /f "delims=" %%A in ('dir %nuGetFolder%npm.js.* /b') do set "npmPath=%nuGetFolder%%%A\tools\"
ECHO Adding Npm and Node to path
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
PATH=%npmPath%;%nodePath%;%PATH%
SET buildFolder=%CD%
ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
CD %CD%\..\src\Umbraco.Web.UI.Client\
ECHO Do npm install and the grunt build of Belle
call npm install --quiet
call npm install -g grunt-cli --quiet
call npm install -g bower --quiet
call grunt build --buildversion=%release%
ECHO Move back to the build folder
CD %buildFolder%
+27
View File
@@ -0,0 +1,27 @@
##We cannot continue if sandcastle is not installed determined by env variable: SHFBROOT
if (-not (Test-Path Env:\SHFBROOT))
{
throw "The docs cannot be build, install Sandcastle help file builder"
}
$PSScriptFilePath = (Get-Item $MyInvocation.MyCommand.Path).FullName
$BuildRoot = Split-Path -Path $PSScriptFilePath -Parent
$OutputPath = Join-Path -Path $BuildRoot -ChildPath "ApiDocs\Output"
$ProjFile = Join-Path -Path $BuildRoot -ChildPath "ApiDocs\csharp-api-docs.shfbproj"
"Building docs with project file: $ProjFile"
$MSBuild = "$Env:SYSTEMROOT\Microsoft.NET\Framework\v4.0.30319\msbuild.exe"
# build it!
& $MSBuild "$ProjFile"
# remove files left over
Remove-Item $BuildRoot\* -include csharp-api-docs.shfbproj_*
# copy our custom styles in
Copy-Item $BuildRoot\ApiDocs\TOC.css $OutputPath\TOC.css
""
"Done!"
+12 -43
View File
@@ -2,32 +2,22 @@
SETLOCAL
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
git.exe --version
IF %ERRORLEVEL%==9009 GOTO :trydefaultpath
REM OK, DONE
git.exe 2> NUL
if %ERRORLEVEL%==9009 GOTO :trydefaultpath
GOTO :EOF
:trydefaultpath
PATH=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
git.exe --version
IF %ERRORLEVEL%==9009 GOTO :showerror
REM OK, DONE
path=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
git.exe 2> NUL
if %ERRORLEVEL%==9009 GOTO :showerror
GOTO :EOF
:showerror
ECHO Git is not in your path and could not be found in C:\Program Files (x86)\Git\cmd nor in C:\Program Files\Git\cmd
SET /p install=" Do you want to install Git through Chocolatey [y/n]? " %=%
IF %install%==y (
:: Create a temporary batch file to execute either after elevating to admin or as-is when the user is already admin
ECHO @ECHO OFF > "%temp%\ChocoInstallGit.cmd"
ECHO SETLOCAL >> "%temp%\ChocoInstallGit.cmd"
ECHO ECHO Installing Chocolatey first >> "%temp%\ChocoInstallGit.cmd"
ECHO @powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" >> "%temp%\ChocoInstallGit.cmd"
ECHO SET PATH=%%PATH%%;%%ALLUSERSPROFILE%%\chocolatey\bin >> "%temp%\ChocoInstallGit.cmd"
ECHO choco install git -y >> "%temp%\ChocoInstallGit.cmd"
set /p install=" Do you want to install Git through Chocolatey [y/n]? " %=%
if %install%==y (
GOTO :installgit
) ELSE (
) else (
GOTO :cantcontinue
)
@@ -36,28 +26,7 @@ ECHO Can't complete the build without Git being in the path. Please add it to be
GOTO :EOF
:installgit
pushd %~dp0
:: Running prompt elevated
:: --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
:: --> If error flag set, we do not have admin.
IF '%errorlevel%' NEQ '0' (
GOTO UACPrompt
) ELSE ( GOTO gotAdmin )
:UACPrompt
ECHO You're not currently running this with admin privileges, we'll now try to execute the install of Git through Chocolatey after elevating to admin privileges
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
ECHO UAC.ShellExecute "%temp%\ChocoInstallGit.cmd", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
EXIT /B
:gotAdmin
IF EXIST "%temp%\getadmin.vbs" ( DEL "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
CALL "%temp%\ChocoInstallGit.cmd"
ECHO Installing Chocolatey first
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
ECHO Installing Git through Chocolatey
choco install git
+105 -87
View File
@@ -1,87 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="3.4.4">
<id>UmbracoCms.Core</id>
<version>8.0.0</version>
<title>Umbraco Cms Core Binaries</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="AutoMapper" version="[6.2.2,6.666666)" />
<dependency id="ClientDependency" version="[1.9.6,1.666666)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.666666)" />
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.666666)" />
<dependency id="Examine" version="[1.0.0-beta025,1.666666)" />
<dependency id="HtmlAgilityPack" version="[1.7.2,1.666666)" />
<dependency id="ImageProcessor" version="[2.6.1.19,2.666666)" />
<dependency id="ImageProcessor.Web" version="[4.9.2.19,4.666666)" />
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.666666)" />
<dependency id="LightInject" version="[5.1.2,5.666666)" />
<dependency id="LightInject.Annotation" version="[1.1.0,1.666666)" />
<dependency id="LightInject.Mvc" version="[2.0.0,2.666666)" />
<dependency id="LightInject.WebApi" version="[2.0.0,2.666666)" />
<dependency id="log4net" version="[2.0.8,2.666666)" />
<dependency id="Log4Net.Async" version="[2.0.4,2.666666)" />
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.666666)" />
<dependency id="Markdown" version="[2.2.1,2.666666)" />
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1,2.666666)" />
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.666666)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.666666)" />
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.666666)" />
<dependency id="Microsoft.CodeAnalysis.CSharp" version="[2.8.0,2.666666)" />
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[1.0.8,1.666666)" />
<dependency id="Microsoft.Net.Compilers" version="[2.8.0,2.666666)" />
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.666666)" />
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.666666)" />
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.666666)" />
<dependency id="Microsoft.Web.Xdt" version="[2.1.2,2.666666)" />
<dependency id="MiniProfiler" version="[3.2.0.157,3.666666)" />
<dependency id="MySql.Data" version="[6.10.7,6.666666)" />
<dependency id="Newtonsoft.Json" version="[11.0.2,11.666666)" />
<dependency id="NPoco" version="[3.9.3,3.666666)" />
<dependency id="Semver" version="[2.0.4,2.666666)" />
<dependency id="System.Reflection.Metadata" version="[1.5.0,1.666666)" />
<dependency id="System.Reflection.Primitives" version="[4.3.0,4.666666)" />
<dependency id="System.Runtime.Handles" version="[4.3.0,4.666666)" />
<dependency id="System.Security.Cryptography.Algorithms" version="[4.3.1,4.666666)" />
<dependency id="System.Security.Cryptography.X509Certificates" version="[4.3.2,4.666666)" />
<dependency id="System.Text.Encoding.CodePages" version="[4.4.0,4.666666)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.666666)" />
<dependency id="System.ValueTuple" version="[4.4.0,4.666666)" />
<dependency id="Umbraco.ModelsBuilder" version="[8.0.0-alpha.18,8.666666)" />
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.666666)" />
</dependencies>
</metadata>
<files>
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
<!-- docs -->
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
<file src="tools\install.core.ps1" target="tools\install.ps1" />
<!-- symbols -->
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
<file src="$BuildTmp$\bin\Umbraco.Web.UI.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Web.UI\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web.UI" />
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
</files>
</package>
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>UmbracoCms.Core</id>
<version>7.0.0</version>
<title>Umbraco Cms Core Binaries</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.3,6.0.0)" />
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.3,6.0.0)" />
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1, 3.0.0)" />
<dependency id="Microsoft.Owin.Security.Cookies" version="[3.0.1, 4.0.0)" />
<dependency id="Microsoft.Owin.Security.OAuth" version="[3.0.1, 4.0.0)" />
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[3.0.1, 4.0.0)" />
<dependency id="MiniProfiler" version="[2.1.0, 3.0.0)" />
<dependency id="HtmlAgilityPack" version="[1.4.9, 2.0.0)" />
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
<dependency id="MySql.Data" version="[6.9.8, 7.0.0)" />
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
<dependency id="ClientDependency" version="[1.8.4, 2.0.0)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.0.0, 3.1.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 9.0.0)" />
<dependency id="Examine" version="[0.1.68, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.3.3, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.5.3, 5.0.0)" />
<dependency id="semver" version="[1.1.2, 2.0.0)" />
<dependency id="UrlRewritingNet" version="[2.0.7, 3.0.0)" />
<dependency id="Markdown" version="[1.14.4, 2.0.0)" />
</dependencies>
</metadata>
<files>
<file src="..\_BuildOutput\WebApp\bin\businesslogic.dll" target="lib\businesslogic.dll" />
<file src="..\_BuildOutput\WebApp\bin\businesslogic.xml" target="lib\businesslogic.xml" />
<file src="..\_BuildOutput\WebApp\bin\cms.dll" target="lib\cms.dll" />
<file src="..\_BuildOutput\WebApp\bin\cms.xml" target="lib\cms.xml" />
<file src="..\_BuildOutput\WebApp\bin\controls.dll" target="lib\controls.dll" />
<file src="..\_BuildOutput\WebApp\bin\controls.xml" target="lib\controls.xml" />
<file src="..\_BuildOutput\WebApp\bin\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\Microsoft.ApplicationBlocks.Data.dll" target="lib\Microsoft.ApplicationBlocks.Data.dll" />
<file src="..\_BuildOutput\WebApp\bin\SQLCE4Umbraco.dll" target="lib\SQLCE4Umbraco.dll" />
<file src="..\_BuildOutput\WebApp\bin\SQLCE4Umbraco.xml" target="lib\SQLCE4Umbraco.xml" />
<file src="..\_BuildOutput\WebApp\bin\System.Data.SqlServerCe.dll" target="lib\System.Data.SqlServerCe.dll" />
<file src="..\_BuildOutput\WebApp\bin\System.Data.SqlServerCe.Entity.dll" target="lib\System.Data.SqlServerCe.Entity.dll" />
<file src="..\_BuildOutput\WebApp\bin\TidyNet.dll" target="lib\TidyNet.dll" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Core.dll" target="lib\Umbraco.Core.dll" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.DataLayer.dll" target="lib\umbraco.DataLayer.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.DataLayer.xml" target="lib\umbraco.DataLayer.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.dll" target="lib\umbraco.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.xml" target="lib\umbraco.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.editorControls.dll" target="lib\umbraco.editorControls.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.editorControls.xml" target="lib\umbraco.editorControls.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.MacroEngines.dll" target="lib\umbraco.MacroEngines.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.MacroEngines.xml" target="lib\umbraco.MacroEngines.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.providers.dll" target="lib\umbraco.providers.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.providers.xml" target="lib\umbraco.providers.xml" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Web.UI.dll" target="lib\Umbraco.Web.UI.dll" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.xml" target="lib\UmbracoExamine.xml" />
<file src="tools\install.core.ps1" target="tools\install.ps1" />
<file src="tools\uninstall.core.ps1" target="tools\uninstall.ps1" />
<!-- Added to be able to produce a symbols package -->
<file src="..\_BuildOutput\bin\SQLCE4Umbraco.pdb" target="lib" />
<file src="..\..\src\SQLCE4Umbraco\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\SQLCE4Umbraco" />
<file src="..\_BuildOutput\bin\businesslogic.pdb" target="lib" />
<file src="..\..\src\umbraco.businesslogic\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.businesslogic" />
<file src="..\_BuildOutput\bin\cms.pdb" target="lib" />
<file src="..\..\src\umbraco.cms\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.cms" />
<file src="..\_BuildOutput\bin\controls.pdb" target="lib" />
<file src="..\..\src\umbraco.controls\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.controls" />
<file src="..\_BuildOutput\bin\interfaces.pdb" target="lib" />
<file src="..\..\src\umbraco.interfaces\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.interfaces" />
<file src="..\_BuildOutput\bin\Umbraco.Core.pdb" target="lib" />
<file src="..\..\src\Umbraco.Core\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
<file src="..\_BuildOutput\bin\umbraco.DataLayer.pdb" target="lib" />
<file src="..\..\src\umbraco.datalayer\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.datalayer" />
<file src="..\_BuildOutput\bin\umbraco.editorControls.pdb" target="lib" />
<file src="..\..\src\umbraco.editorControls\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.editorControls" />
<file src="..\_BuildOutput\bin\umbraco.MacroEngines.pdb" target="lib" />
<file src="..\..\src\umbraco.MacroEngines\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.MacroEngines" />
<file src="..\_BuildOutput\bin\umbraco.providers.pdb" target="lib" />
<file src="..\..\src\umbraco.providers\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.providers" />
<file src="..\_BuildOutput\bin\umbraco.pdb" target="lib" />
<file src="..\..\src\Umbraco.Web\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
<file src="..\_BuildOutput\bin\Umbraco.Web.UI.pdb" target="lib" />
<file src="..\..\src\Umbraco.Web.UI\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web.UI" />
<file src="..\_BuildOutput\bin\UmbracoExamine.pdb" target="lib" />
<file src="..\..\src\UmbracoExamine\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\UmbracoExamine" />
</files>
</package>
+48 -49
View File
@@ -1,49 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="3.4.4">
<id>UmbracoCms</id>
<version>8.0.0</version>
<title>Umbraco Cms</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="Umbraco.ModelsBuilder" version="[8.0.0-alpha.18, 9.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 3.0.0)" />
</dependencies>
</metadata>
<files>
<file src="$BuildTmp$\Configs\**" target="Content\Config" exclude="$BuildTmp$\Configs\Web.config.transform" />
<file src="$BuildTmp$\WebApp\Views\**" target="Content\Views" exclude="$BuildTmp$\WebApp\Views\Web.config" />
<file src="$BuildTmp$\WebApp\default.aspx" target="Content\default.aspx" />
<file src="$BuildTmp$\WebApp\Global.asax" target="Content\Global.asax" />
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
<file src="$BuildTmp$\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="$BuildTmp$\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
<file src="tools\install.ps1" target="tools\install.ps1" />
<file src="tools\Readme.txt" target="tools\Readme.txt" />
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
<file src="tools\applications.config.install.xdt" target="Content\config\applications.config.install.xdt" />
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" />
<file src="build\**" target="build" />
</files>
</package>
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="2.8">
<id>UmbracoCms</id>
<version>7.0.0</version>
<title>Umbraco Cms</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 9.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.0, 4.0.0)" />
</dependencies>
</metadata>
<files>
<file src="..\_BuildOutput\Configs\**" target="Content\Config" exclude="..\_BuildOutput\Configs\Web.config.transform" />
<file src="..\_BuildOutput\WebApp\Views\**" target="Content\Views" exclude="..\_BuildOutput\WebApp\Views\Web.config" />
<file src="..\_BuildOutput\WebApp\default.aspx" target="Content\default.aspx" />
<file src="..\_BuildOutput\WebApp\Global.asax" target="Content\Global.asax" />
<file src="..\_BuildOutput\WebApp\Web.config" target="UmbracoFiles\Web.config" />
<file src="..\_BuildOutput\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
<file src="..\_BuildOutput\WebApp\bin\amd64\**" target="UmbracoFiles\bin\amd64" />
<file src="..\_BuildOutput\WebApp\bin\x86\**" target="UmbracoFiles\bin\x86" />
<file src="..\_BuildOutput\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
<file src="..\_BuildOutput\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="..\_BuildOutput\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
<file src="tools\install.ps1" target="tools\install.ps1" />
<file src="tools\uninstall.ps1" target="tools\uninstall.ps1" />
<file src="tools\Readme.txt" target="tools\Readme.txt" />
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
<file src="tools\applications.config.install.xdt" target="Content\config\applications.config.install.xdt" />
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" />
<file src="build\**" target="build" />
</files>
</package>
@@ -21,12 +21,6 @@
</section>
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<areas xdt:Transform="InsertIfMissing">
<area xdt:Transform="InsertIfMissing">developer</area>
</areas>
</section>
<section alias="StartupDeveloperDashboardSection">
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Replace">
<control showOnce="true" addPanel="true" panelCaption="">
views/dashboard/developer/developerdashboardvideos.html
@@ -36,11 +30,16 @@
</section>
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
<control>
views/dashboard/developer/examinemanagement.html
</control>
</tab>
</tab>
<tab caption="Xml Data Integrity Report" xdt:Transform="InsertIfMissing">
<control>
views/dashboard/developer/xmldataintegrityreport.html
</control>
</tab>
</section>
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
@@ -53,6 +52,19 @@
</tab>
</section>
<section alias="StartupDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Get Started" xdt:Transform="Insert">
<access>
<grant>admin</grant>
</access>
<control showOnce="true" addPanel="true" panelCaption="">
views/dashboard/default/startupdashboardintro.html
</control>
</tab>
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
</section>
<section alias="StartupMemberDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Get Started" xdt:Transform="Insert">
@@ -68,28 +80,5 @@
<section alias="StartupDashboardSection">
<tab caption="Change Password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
</section>
<section alias="RedirectUrlManagement" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<areas>
<area>content</area>
</areas>
<tab caption="Redirect URL Management">
<control>
views/dashboard/developer/redirecturls.html
</control>
</tab>
</section>
<section alias="UmbracoHealthCheck" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<areas>
<area>developer</area>
</areas>
<tab caption="Health Check">
<control>
views/dashboard/developer/healthcheck.html
</control>
</tab>
</section>
</dashBoard>
+1 -9
View File
@@ -8,17 +8,9 @@
----------------------------------------------------
*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
Be sure to read the version specific upgrade information before proceeding:
https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
Depending on the version you are upgrading from, you may need to make some changes to your web.config
and you will need to be aware of the breaking changes listed there to see if these affect your installation.
Don't forget to build!
We've done our best to transform your configuration files but in case something is not quite right: remember we
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
+193 -32
View File
@@ -4,8 +4,8 @@
<configSections>
<section name="BaseRestExtensions" xdt:Locator="Match(name)" xdt:Transform="Remove" />
<section name="FileSystemProviders" xdt:Locator="Match(name)" xdt:Transform="Remove" />
<section name="ExamineLuceneIndexSets" type="Umbraco.Examine.Config.IndexSets, Umbraco.Examine" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type,requirePermission)" />
<section name="ExamineLuceneIndexSets" type="Examine.LuceneEngine.Config.IndexSets, Examine" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type,requirePermission)" />
<sectionGroup name="applicationSettings" xdt:Locator="Match(name)">
<section name="umbraco.presentation.Properties.Settings" xdt:Locator="Match(name)" xdt:Transform="Remove" />
</sectionGroup>
@@ -15,16 +15,12 @@
<section name="BaseRestExtensions" type="Umbraco.Core.Configuration.BaseRest.BaseRestSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
<section name="FileSystemProviders" type="Umbraco.Core.Configuration.FileSystemProvidersSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
<section name="dashBoard" type="Umbraco.Core.Configuration.Dashboard.DashboardSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
<section name="HealthChecks" type="Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
</sectionGroup>
</configSections>
<appSettings xdt:Transform="InsertIfMissing" />
<appSettings>
<add key="owin:appStartup" value="UmbracoDefaultOwinStartup" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
<add key="Umbraco.ModelsBuilder.Enable" value="false" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
<add key="Umbraco.ModelsBuilder.ModelsMode" value="Nothing" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
<add key="umbracoDefaultUILanguage" value="en-US" xdt:Locator="Match(key)" xdt:Transform="SetAttributes(value)" />
</appSettings>
<umbracoConfiguration xdt:Transform="InsertIfMissing">
@@ -32,7 +28,6 @@
<BaseRestExtensions configSource="config\BaseRestExtensions.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
<FileSystemProviders configSource="config\FileSystemProviders.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
<dashBoard configSource="config\Dashboard.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
<HealthChecks configSource="config\HealthChecks.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
</umbracoConfiguration>
<FileSystemProviders xdt:Transform="Remove" />
@@ -67,6 +62,190 @@
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
<sessionState customProvider="DefaultSessionProvider" xdt:Locator="Match(customProvider)" xdt:Transform="Remove"/>
<compilation xdt:Transform="InsertIfMissing" />
<compilation>
<assemblies xdt:Transform="InsertIfMissing" />
<assemblies>
<add assembly="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Collections, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Collections.Concurrent, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ComponentModel.Annotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ComponentModel.EventBasedAsync, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Diagnostics.Contracts, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Diagnostics.Debug, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Diagnostics.Tools, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Diagnostics.Tracing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Dynamic.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Globalization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.IO, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Linq.Expressions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Linq.Parallel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Linq.Queryable, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Net.NetworkInformation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Net.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Net.Requests, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ObjectModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Emit, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Emit.ILGeneration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Emit.Lightweight, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Resources.ResourceManager, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.InteropServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.InteropServices.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Serialization.Json, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Serialization.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Serialization.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Security.Principal, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.Duplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.NetTcp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Text.Encoding, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Text.Encoding.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Text.RegularExpressions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Threading, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Threading.Tasks, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Threading.Tasks.Parallel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Xml.ReaderWriter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Xml.XDocument, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Xml.XmlSerializer, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
</assemblies>
</compilation>
<compilation>
<assemblies>
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Collections" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Collections.Concurrent" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ComponentModel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ComponentModel.Annotations" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ComponentModel.EventBasedAsync" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Diagnostics.Contracts" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Diagnostics.Debug" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Diagnostics.Tools" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Diagnostics.Tracing" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Dynamic.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Globalization" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.IO" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Linq" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Linq.Expressions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Linq.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Linq.Queryable" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Net.NetworkInformation" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Net.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Net.Requests" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ObjectModel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Emit" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Emit.ILGeneration" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Emit.Lightweight" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Resources.ResourceManager" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.InteropServices" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.InteropServices.WindowsRuntime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Numerics" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Serialization.Json" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Serialization.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Serialization.Xml" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Security.Principal" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.Duplex" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.NetTcp" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.Security" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Text.Encoding" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Text.Encoding.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Text.RegularExpressions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Threading" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Threading.Tasks" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Threading.Tasks.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Xml.ReaderWriter" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Xml.XDocument" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Xml.XmlSerializer" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
</assemblies>
</compilation>
<compilation>
<assemblies>
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Collections" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Collections.Concurrent" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ComponentModel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ComponentModel.Annotations" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ComponentModel.EventBasedAsync" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Diagnostics.Contracts" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Diagnostics.Debug" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Diagnostics.Tools" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Diagnostics.Tracing" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Dynamic.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Globalization" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.IO" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Linq" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Linq.Expressions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Linq.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Linq.Queryable" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.NetworkInformation" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.Requests" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ObjectModel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Emit" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Emit.ILGeneration" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Emit.Lightweight" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Resources.ResourceManager" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.InteropServices" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.InteropServices.WindowsRuntime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Numerics" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Serialization.Json" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Serialization.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Serialization.Xml" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Security.Principal" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.Duplex" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.NetTcp" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.Security" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Text.Encoding" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Text.Encoding.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Text.RegularExpressions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Threading" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Threading.Tasks" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Threading.Tasks.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Xml.ReaderWriter" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Xml.XDocument" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Xml.XmlSerializer" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
</assemblies>
</compilation>
<xhtmlConformance xdt:Transform="Remove" />
@@ -111,8 +290,6 @@
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<remove fileExtension=".woff" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<mimeMap fileExtension=".woff" mimeType="application/x-font-woff" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<remove fileExtension=".woff2" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<mimeMap fileExtension=".woff2" mimeType="application/x-font-woff2" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<remove fileExtension=".less" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<mimeMap fileExtension=".less" mimeType="text/css" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
</staticContent>
@@ -138,7 +315,6 @@
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='HtmlAgilityPack')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='AutoMapper')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="Remove" />
@@ -149,21 +325,14 @@
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security.Cookies')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http.Formatting')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.CodeAnalysis.CSharp')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='log4net')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Data.SqlServerCe')" xdt:Transform="Remove" />
</assemblyBinding>
</runtime>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Transform="Insert">
<dependentAssembly>
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.5.1.0" newVersion="1.5.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.3.1.0" newVersion="3.3.1.0" />
<bindingRedirect oldVersion="0.0.0.0-1.4.9.0" newVersion="1.4.9.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
@@ -171,7 +340,7 @@
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
@@ -187,32 +356,24 @@
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0"/>
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
@@ -1,6 +0,0 @@
<?xml version="1.0"?>
<caching xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<caches>
<cache name="DiskCache" trimCache="false" xdt:Transform="SetAttributes(trimCache)" xdt:Locator="Match(name)" />
</caches>
</caching>
+14 -4
View File
@@ -33,16 +33,27 @@ if ($project) {
robocopy $umbracoBinFolder $umbracoBinBackupPath /e /LOG:$copyLogsPath\UmbracoBinBackup.log
# Delete files Umbraco ships with
if(Test-Path $umbracoBinFolder\businesslogic.dll) { Remove-Item $umbracoBinFolder\businesslogic.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\cms.dll) { Remove-Item $umbracoBinFolder\cms.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\controls.dll) { Remove-Item $umbracoBinFolder\controls.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\interfaces.dll) { Remove-Item $umbracoBinFolder\interfaces.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\log4net.dll) { Remove-Item $umbracoBinFolder\log4net.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll) { Remove-Item $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\SQLCE4Umbraco.dll) { Remove-Item $umbracoBinFolder\SQLCE4Umbraco.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.Web.dll) { Remove-Item $umbracoBinFolder\Umbraco.Web.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\TidyNet.dll) { Remove-Item $umbracoBinFolder\TidyNet.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.dll) { Remove-Item $umbracoBinFolder\umbraco.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.Core.dll) { Remove-Item $umbracoBinFolder\Umbraco.Core.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.DataLayer.dll) { Remove-Item $umbracoBinFolder\umbraco.DataLayer.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.editorControls.dll) { Remove-Item $umbracoBinFolder\umbraco.editorControls.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.MacroEngines.dll) { Remove-Item $umbracoBinFolder\umbraco.MacroEngines.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.ModelsBuilder.dll) { Remove-Item $umbracoBinFolder\Umbraco.ModelsBuilder.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.ModelsBuilder.AspNet.dll) { Remove-Item $umbracoBinFolder\Umbraco.ModelsBuilder.AspNet.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.providers.dll) { Remove-Item $umbracoBinFolder\umbraco.providers.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.Web.UI.dll) { Remove-Item $umbracoBinFolder\Umbraco.Web.UI.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.Examine.dll) { Remove-Item $umbracoBinFolder\Umbraco.Examine.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\UmbracoExamine.dll) { Remove-Item $umbracoBinFolder\UmbracoExamine.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll) { Remove-Item $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll -Force -Confirm:$false }
# Delete files Umbraco depends upon
$amd64Folder = Join-Path $umbracoBinFolder "amd64"
@@ -60,7 +71,6 @@ if ($project) {
if(Test-Path $umbracoBinFolder\ImageProcessor.dll) { Remove-Item $umbracoBinFolder\ImageProcessor.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\ImageProcessor.Web.dll) { Remove-Item $umbracoBinFolder\ImageProcessor.Web.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Lucene.Net.dll) { Remove-Item $umbracoBinFolder\Lucene.Net.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.IO.RecyclableMemoryStream.dll) { Remove-Item $umbracoBinFolder\Microsoft.IO.RecyclableMemoryStream.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.AspNet.Identity.Core.dll) { Remove-Item $umbracoBinFolder\Microsoft.AspNet.Identity.Core.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.AspNet.Identity.Owin.dll) { Remove-Item $umbracoBinFolder\Microsoft.AspNet.Identity.Owin.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.CodeAnalysis.CSharp.dll) { Remove-Item $umbracoBinFolder\Microsoft.CodeAnalysis.CSharp.dll -Force -Confirm:$false }
@@ -92,4 +102,4 @@ if ($project) {
if(Test-Path $umbracoBinFolder\System.Web.WebPages.Deployment.dll) { Remove-Item $umbracoBinFolder\System.Web.WebPages.Deployment.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\System.Web.WebPages.Razor.dll) { Remove-Item $umbracoBinFolder\System.Web.WebPages.Razor.dll -Force -Confirm:$false }
}
}
}
+1 -67
View File
@@ -77,74 +77,8 @@ if ($project) {
{
$packageWebConfigSource = Join-Path $installPath "UmbracoFiles\Web.config"
Copy-Item $packageWebConfigSource $destinationWebConfig -Force
}
# Copy files that don't get automatically copied for Website projects
# We do this here, when copyWebconfig is true because we only want to do it for new installs
# If this is an upgrade then the files should already be there
$splashesSource = Join-Path $installPath "UmbracoFiles\Config\splashes\*.*"
$splashesDestination = Join-Path $projectPath "Config\splashes\"
New-Item $splashesDestination -Type directory
Copy-Item $splashesSource $splashesDestination -Force
$sqlCe64Source = Join-Path $installPath "UmbracoFiles\bin\amd64\*"
$sqlCe64Destination = Join-Path $projectPath "bin\amd64\"
Copy-Item $sqlCe64Source $sqlCe64Destination -Force
$sqlCex86Source = Join-Path $installPath "UmbracoFiles\bin\x86\*"
$sqlCex86Destination = Join-Path $projectPath "bin\x86\"
Copy-Item $sqlCex86source $sqlCex86Destination -Force
$umbracoUIXMLSource = Join-Path $installPath "UmbracoFiles\Umbraco\Config\Create\UI.xml"
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
} else {
# This part only runs for upgrades
$upgradeViewSource = Join-Path $umbracoFolderSource "Views\install\*"
$upgradeView = Join-Path $umbracoFolder "Views\install\"
Write-Host "Copying2 ${upgradeViewSource} to ${upgradeView}"
Copy-Item $upgradeViewSource $upgradeView -Force
Try
{
# Disable tours for upgrades, presumably Umbraco experience is already available
$umbracoSettingsConfigPath = Join-Path $configFolder "umbracoSettings.config"
$content = (Get-Content $umbracoSettingsConfigPath).Replace('<tours enable="true">','<tours enable="false">')
# Saves with UTF-8 encoding without BOM which makes sure Umbraco can still read it
# Reference: https://stackoverflow.com/a/32951824/5018
[IO.File]::WriteAllLines($umbracoSettingsConfigPath, $content)
}
Catch
{
# Not a big problem if this fails, let it go
}
Try
{
$uiXmlConfigPath = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
$uiXmlFile = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
$uiXml = New-Object System.Xml.XmlDocument
$uiXml.PreserveWhitespace = $true
$uiXml.Load($uiXmlFile)
$createExists = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks/create")
if($createExists.Count -eq 0)
{
$macrosTasksNode = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks")
#Creating: <create assembly="umbraco" type="macroTasks" />
$createNode = $uiXml.CreateElement("create")
$createNode.SetAttribute("assembly", "umbraco")
$createNode.SetAttribute("type", "macroTasks")
$macrosTasksNode.AppendChild($createNode)
$uiXml.Save($uiXmlFile)
}
}
Catch { }
}
$installFolder = Join-Path $projectPath "Install"
if(Test-Path $installFolder) {
Remove-Item $installFolder -Force -Recurse -Confirm:$false
@@ -1 +0,0 @@
<processing xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xdt:Transform="SetAttributes(preserveExifMetaData)" preserveExifMetaData="true" />
+26 -42
View File
@@ -34,16 +34,11 @@
xdt:Transform="SetAttributes()" />
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="partialViews" type="Umbraco.Web.Trees.PartialViewsTree, umbraco"
xdt:Locator="Match(application,alias,type)"
xdt:Transform="Remove()" />
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTreeController, umbraco" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<add application="settings" alias="scripts" title="Scripts" type="Umbraco.Web.Trees.ScriptTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTree, umbraco" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="scripts" title="Scripts" type="umbraco.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="dictionary" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6"
@@ -60,55 +55,44 @@
xdt:Transform="SetAttributes()" />
<!--Developer-->
<add alias="packager" application="developer"
<add alias="datatype" application="developer"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add alias="packagerPackages" application="developer"
<add initialize="true" sortOrder="0" alias="datatypes" application="developer" title="Data Types" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add initialize="true" sortOrder="0" alias="packager" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.PackagesTreeController, umbraco"
xdt:Transform="InsertIfMissing" />
<add application="developer" alias="macros" title="Macros" type="umbraco.loadMacros, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<!-- Before 7.4 this tree had the alias 'dataType', without the 's' on the end, this is here to rename it -->
<add sortOrder="1" alias="dataTypes" application="developer" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco"
xdt:Locator="Match(application,type)"
xdt:Transform="SetAttributes(alias,sortOrder)" />
<!-- Yes, set the sortOrder again, like above because.. sometimes apparently we already have a dataTypes node and we can't remove more than one.. if they're equal though (same alias,application and sortOrder) it doesn't throw an error -->
<add sortOrder="1" alias="dataTypes" application="developer"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="packager" title="Packages" type="umbraco.loadPackager, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes(sortOrder)" />
<add initialize="true" sortOrder="2" alias="macros" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MacroTreeController, umbraco"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="packagerPackages" title="Packager Packages" type="umbraco.loadPackages, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" initialize="false" sortOrder="3"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco"
xdt:Locator="Match(application,alias,type)"
xdt:Transform="Remove()" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTreeController, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<add application="developer" alias="xslt" title="XSLT Files" type="umbraco.loadXslt, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="5"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="python"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<!--Users-->
<add initialize="true" sortOrder="0" alias="users" application="users" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.UserTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="users" alias="userTypes"
<add application="users" alias="users" title="Users" type="umbraco.loadUsers, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add application="users" alias="userPermissions"
xdt:Transform="SetAttributes()" />
<add application="users" alias="userTypes" title="User Types" type="umbraco.cms.presentation.Trees.UserTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="1"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
xdt:Transform="SetAttributes()" />
<add application="users" alias="userPermissions" title="User Permissions" type="umbraco.cms.presentation.Trees.UserPermissions, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<!--Members-->
<add initialize="true" sortOrder="0" alias="member" application="member" title="Members" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTreeController, umbraco"
@@ -5,6 +5,4 @@
</content>
<webservices xdt:Transform="Remove" />
<repositories xdt:Transform="Remove" />
</settings>
+48
View File
@@ -0,0 +1,48 @@
param($installPath, $toolsPath, $package, $project)
Write-Host "installPath:" "${installPath}"
Write-Host "toolsPath:" "${toolsPath}"
Write-Host " "
if ($project) {
# Create paths and list them
$projectPath = (Get-Item $project.Properties.Item("FullPath").Value).FullName
Write-Host "projectPath:" "${projectPath}"
$backupPath = Join-Path $projectPath "App_Data\NuGetBackup"
Write-Host "backupPath:" "${backupPath}"
$umbracoBinFolder = Join-Path $projectPath "bin"
Write-Host "umbracoBinFolder:" "${umbracoBinFolder}"
# Remove backups
Write-Host "removing backups:" "${backupPath}"
if(Test-Path $backupPath) { Remove-Item -Recurse -Force $backupPath -Confirm:$false }
# Delete files Umbraco ships with
Write-Host "removing dlls:" "${umbracoBinFolder}"
if(Test-Path $umbracoBinFolder\businesslogic.dll) { Remove-Item $umbracoBinFolder\businesslogic.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\cms.dll) { Remove-Item $umbracoBinFolder\cms.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\controls.dll) { Remove-Item $umbracoBinFolder\controls.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\interfaces.dll) { Remove-Item $umbracoBinFolder\interfaces.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\log4net.dll) { Remove-Item $umbracoBinFolder\log4net.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll) { Remove-Item $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\SQLCE4Umbraco.dll) { Remove-Item $umbracoBinFolder\SQLCE4Umbraco.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\TidyNet.dll) { Remove-Item $umbracoBinFolder\TidyNet.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.dll) { Remove-Item $umbracoBinFolder\umbraco.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.Core.dll) { Remove-Item $umbracoBinFolder\Umbraco.Core.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.DataLayer.dll) { Remove-Item $umbracoBinFolder\umbraco.DataLayer.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.editorControls.dll) { Remove-Item $umbracoBinFolder\umbraco.editorControls.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.MacroEngines.dll) { Remove-Item $umbracoBinFolder\umbraco.MacroEngines.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\umbraco.providers.dll) { Remove-Item $umbracoBinFolder\umbraco.providers.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.Web.UI.dll) { Remove-Item $umbracoBinFolder\Umbraco.Web.UI.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\UmbracoExamine.dll) { Remove-Item $umbracoBinFolder\UmbracoExamine.dll -Force -Confirm:$false }
$amd64Folder = Join-Path $umbracoBinFolder "amd64"
if(Test-Path $amd64Folder) { Remove-Item $amd64Folder -Force -Recurse -Confirm:$false }
$x86Folder = Join-Path $umbracoBinFolder "x86"
if(Test-Path $x86Folder) { Remove-Item $x86Folder -Force -Recurse -Confirm:$false }
}
+39
View File
@@ -0,0 +1,39 @@
param($installPath, $toolsPath, $package, $project)
Write-Host "installPath:" "${installPath}"
Write-Host "toolsPath:" "${toolsPath}"
Write-Host " "
if ($project) {
# Create paths and list them
$projectPath = (Get-Item $project.Properties.Item("FullPath").Value).FullName
Write-Host "projectPath:" "${projectPath}"
$backupPath = Join-Path $projectPath "App_Data\NuGetBackup"
Write-Host "backupPath:" "${backupPath}"
$appBrowsers = Join-Path $projectPath "App_Browsers"
Write-Host "appBrowsers:" "${appBrowsers}"
$appData = Join-Path $projectPath "App_Data"
Write-Host "appData:" "${appData}"
# Remove backups
Write-Host "removing backups:" "${backupPath}"
if(Test-Path $backupPath) { Remove-Item -Recurse -Force $backupPath -Confirm:$false }
# Remove app_data files
Write-Host "removing app_data files:" "${appData}"
if(Test-Path $appData\packages) { Remove-Item $appData\packages -Recurse -Force -Confirm:$false }
Write-Host "removing app_browsers:" "${appBrowsers}"
if(Test-Path $appBrowsers\Form.browser) { Remove-Item $appBrowsers\Form.browser -Force -Confirm:$false }
if(Test-Path $appBrowsers\w3cvalidator.browser) { Remove-Item $appBrowsers\w3cvalidator.browser -Force -Confirm:$false }
# Remove umbraco and umbraco_files
$umbracoFolder = Join-Path $projectPath "Umbraco"
Write-Host "removing umbraco folder:" "${umbracoFolder}"
if(Test-Path $umbracoFolder) { Remove-Item $umbracoFolder -Recurse -Force -Confirm:$false }
$umbracoClientFolder = Join-Path $projectPath "Umbraco_Client"
Write-Host "removing umbraco client folder:" "${umbracoClientFolder}"
if(Test-Path $umbracoClientFolder) { Remove-Item $umbracoClientFolder -Recurse -Force -Confirm:$false }
}
Binary file not shown.
+2 -2
View File
@@ -22,7 +22,7 @@ echo Removing bin files
del ..\src\Umbraco.Web.UI\bin\*.*
echo Building solution
"%ProgramFiles(x86)%"\MSBuild\14.0\Bin\MSBuild.exe ..\src\umbraco.sln /t:Clean,Build
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe ..\src\umbraco.sln /t:Clean,Build
echo Resetting installedPackages.config
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
@@ -86,7 +86,7 @@ echo Removing bin files
FOR %%A IN (..\src\Umbraco.Web.UI\bin\*.*) DO DEL %%A
echo Building solution
"%ProgramFiles(x86)%"\MSBuild\14.0\Bin\MSBuild.exe ..\src\umbraco.sln /t:Clean,Build
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe ..\src\umbraco.sln /t:Clean,Build
echo Resetting installedPackages.config
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
+2
View File
@@ -0,0 +1,2 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.4.1
-92
View File
@@ -1,92 +0,0 @@
# this script should be dot-sourced into the build.ps1 scripts
# right after the parameters declaration
# ie
# . "$PSScriptRoot\build-bootstrap.ps1"
# THIS FILE IS DISTRIBUTED AS PART OF UMBRACO.BUILD
# DO NOT MODIFY IT - ALWAYS USED THE COMMON VERSION
# ################################################################
# BOOTSTRAP
# ################################################################
# reset errors
$error.Clear()
# ensure we have temp folder for downloads
$scriptRoot = "$PSScriptRoot"
$scriptTemp = "$scriptRoot\temp"
if (-not (test-path $scriptTemp)) { mkdir $scriptTemp > $null }
# get NuGet
$cache = 4
$nuget = "$scriptTemp\nuget.exe"
if (-not $local)
{
$source = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
if ((test-path $nuget) -and ((ls $nuget).CreationTime -lt [DateTime]::Now.AddDays(-$cache)))
{
Remove-Item $nuget -force -errorAction SilentlyContinue > $null
}
if (-not (test-path $nuget))
{
Write-Host "Download NuGet..."
Invoke-WebRequest $source -OutFile $nuget
if (-not $?) { throw "Failed to download NuGet." }
}
}
elseif (-not (test-path $nuget))
{
throw "Failed to locate NuGet.exe."
}
# NuGet notes
# As soon as we use -ConfigFile, NuGet uses that file, and only that file, and does not
# merge configuration from system level. See comments in NuGet.Client solution, class
# NuGet.Configuration.Settings, method LoadDefaultSettings.
# For NuGet to merge configurations, it needs to "find" the file in the current directory,
# or above. Which means we cannot really use -ConfigFile but instead have to have Umbraco's
# NuGet.config file at root, and always run NuGet.exe while at root or in a directory below
# root.
$solutionRoot = "$scriptRoot\.."
$testPwd = [System.IO.Path]::GetFullPath($pwd.Path) + "\"
$testRoot = [System.IO.Path]::GetFullPath($solutionRoot) + "\"
if (-not $testPwd.ToLower().StartsWith($testRoot.ToLower()))
{
throw "Cannot run outside of the solution's root."
}
# get the build system
if (-not $local)
{
$params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease"
&$nuget install Umbraco.Build @params
if (-not $?) { throw "Failed to download Umbraco.Build." }
}
# ensure we have the build system
$ubuildPath = ls "$scriptTemp\Umbraco.Build.*" | sort -property CreationTime -descending | select -first 1
if (-not $ubuildPath)
{
throw "Failed to locate the build system."
}
# boot the build system
# this creates $global:ubuild
return &"$ubuildPath\ps\Boot.ps1"
# at that point the build.ps1 script must boot the build system
# eg
# $ubuild.Boot($ubuildPath.FullName, [System.IO.Path]::GetFullPath("$scriptRoot\.."),
# @{ Local = $local; With7Zip = $false; WithNode = $false },
# @{ continue = $continue })
# if (-not $?) { throw "Failed to boot the build system." }
#
# and it's good practice to report
# eg
# Write-Host "Umbraco.Whatever Build"
# Write-Host "Umbraco.Build v$($ubuild.BuildVersion)"
# eof
-469
View File
@@ -1,469 +0,0 @@
param (
# get, don't execute
[Parameter(Mandatory=$false)]
[Alias("g")]
[switch] $get = $false,
# run local, don't download, assume everything is ready
[Parameter(Mandatory=$false)]
[Alias("l")]
[Alias("loc")]
[switch] $local = $false,
# keep the build directories, don't clear them
[Parameter(Mandatory=$false)]
[Alias("c")]
[Alias("cont")]
[switch] $continue = $false
)
# ################################################################
# BOOTSTRAP
# ################################################################
# create and boot the buildsystem
$ubuild = &"$PSScriptRoot\build-bootstrap.ps1"
if (-not $?) { return }
$ubuild.Boot($PSScriptRoot,
@{ Local = $local; },
@{ Continue = $continue })
if ($ubuild.OnError()) { return }
Write-Host "Umbraco Cms Build"
Write-Host "Umbraco.Build v$($ubuild.BuildVersion)"
# ################################################################
# TASKS
# ################################################################
$ubuild.DefineMethod("SetMoreUmbracoVersion",
{
param ( $semver )
$release = "" + $semver.Major + "." + $semver.Minor + "." + $semver.Patch
Write-Host "Update UmbracoVersion.cs"
$this.ReplaceFileText("$($this.SolutionRoot)\src\Umbraco.Core\Configuration\UmbracoVersion.cs", `
"(\d+)\.(\d+)\.(\d+)(.(\d+))?", `
"$release")
$this.ReplaceFileText("$($this.SolutionRoot)\src\Umbraco.Core\Configuration\UmbracoVersion.cs", `
"CurrentComment => `"(.+)`"", `
"CurrentComment => `"$($semver.PreRelease)`"")
Write-Host "Update IIS Express port in csproj"
$updater = New-Object "Umbraco.Build.ExpressPortUpdater"
$csproj = "$($this.SolutionRoot)\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj"
$updater.Update($csproj, $release)
})
$ubuild.DefineMethod("SandboxNode",
{
$global:node_path = $env:path
$nodePath = $this.BuildEnv.NodePath
$gitExe = (Get-Command git).Source
$gitPath = [System.IO.Path]::GetDirectoryName($gitExe)
$env:path = "$nodePath;$gitPath"
$global:node_nodepath = $this.ClearEnvVar("NODEPATH")
$global:node_npmcache = $this.ClearEnvVar("NPM_CONFIG_CACHE")
$global:node_npmprefix = $this.ClearEnvVar("NPM_CONFIG_PREFIX")
})
$ubuild.DefineMethod("RestoreNode",
{
$env:path = $node_path
$this.SetEnvVar("NODEPATH", $node_nodepath)
$this.SetEnvVar("NPM_CONFIG_CACHE", $node_npmcache)
$this.SetEnvVar("NPM_CONFIG_PREFIX", $node_npmprefix)
})
$ubuild.DefineMethod("CompileBelle",
{
$src = "$($this.SolutionRoot)\src"
$log = "$($this.BuildTemp)\belle.log"
Write-Host "Compile Belle"
Write-Host "Logging to $log"
# get a temp clean node env (will restore)
$this.SandboxNode()
# stupid PS is going to gather all "warnings" in $error
# so we have to take care of it else they'll bubble and kill the build
if ($error.Count -gt 0) { return }
Push-Location "$($this.SolutionRoot)\src\Umbraco.Web.UI.Client"
Write-Output "" > $log
Write-Output "### node version is:" > $log
&node -v >> $log 2>&1
if (-not $?) { throw "Failed to report node version." }
Write-Output "### npm version is:" >> $log 2>&1
&npm -v >> $log 2>&1
if (-not $?) { throw "Failed to report npm version." }
Write-Output "### clean npm cache" >> $log 2>&1
&npm cache clean --force >> $log 2>&1
$error.Clear() # that one can fail 'cos security bug - ignore
Write-Output "### npm install" >> $log 2>&1
&npm install >> $log 2>&1
Write-Output ">> $? $($error.Count)" >> $log 2>&1
Write-Output "### install bower" >> $log 2>&1
&npm install -g bower >> $log 2>&1
$error.Clear() # that one fails 'cos bower is deprecated - ignore
Write-Output "### install gulp" >> $log 2>&1
&npm install -g gulp >> $log 2>&1
$error.Clear() # that one fails 'cos deprecated stuff - ignore
Write-Output "### install gulp-cli" >> $log 2>&1
&npm install -g gulp-cli --quiet >> $log 2>&1
if (-not $?) { throw "Failed to install gulp-cli" } # that one is expected to work
Write-Output "### gulp build for version $($this.Version.Release)" >> $log 2>&1
&gulp build --buildversion=$this.Version.Release >> $log 2>&1
if (-not $?) { throw "Failed to build" } # that one is expected to work
Pop-Location
# fixme - should we filter the log to find errors?
#get-content .\build.tmp\belle.log | %{ if ($_ -match "build") { write $_}}
# restore
$this.RestoreNode()
# setting node_modules folder to hidden
# used to prevent VS13 from crashing on it while loading the websites project
# also makes sure aspnet compiler does not try to handle rogue files and chokes
# in VSO with Microsoft.VisualC.CppCodeProvider -related errors
# use get-item -force 'cos it might be hidden already
Write-Host "Set hidden attribute on node_modules"
$dir = Get-Item -force "$src\Umbraco.Web.UI.Client\node_modules"
$dir.Attributes = $dir.Attributes -bor ([System.IO.FileAttributes]::Hidden)
})
$ubuild.DefineMethod("CompileUmbraco",
{
$buildConfiguration = "Release"
$src = "$($this.SolutionRoot)\src"
$log = "$($this.BuildTemp)\msbuild.umbraco.log"
if ($this.BuildEnv.VisualStudio -eq $null)
{
throw "Build environment does not provide VisualStudio."
}
Write-Host "Compile Umbraco"
Write-Host "Logging to $log"
# beware of the weird double \\ at the end of paths
# see http://edgylogic.com/blog/powershell-and-external-commands-done-right/
&$this.BuildEnv.VisualStudio.MsBuild "$src\Umbraco.Web.UI\Umbraco.Web.UI.csproj" `
/p:WarningLevel=0 `
/p:Configuration=$buildConfiguration `
/p:Platform=AnyCPU `
/p:UseWPP_CopyWebApplication=True `
/p:PipelineDependsOnBuild=False `
/p:OutDir="$($this.BuildTemp)\bin\\" `
/p:WebProjectOutputDir="$($this.BuildTemp)\WebApp\\" `
/p:Verbosity=minimal `
/t:Clean`;Rebuild `
/tv:"$($this.BuildEnv.VisualStudio.ToolsVersion)" `
/p:UmbracoBuild=True `
> $log
if (-not $?) { throw "Failed to compile Umbraco.Web.UI." }
# /p:UmbracoBuild tells the csproj that we are building from PS, not VS
})
$ubuild.DefineMethod("PrepareTests",
{
Write-Host "Prepare Tests"
# fixme - idea is to avoid rebuilding everything for tests
# but because of our weird assembly versioning (with .* stuff)
# everything gets rebuilt all the time...
#Copy-Files "$tmp\bin" "." "$tmp\tests"
# data
Write-Host "Copy data files"
if (-not (Test-Path -Path "$($this.BuildTemp)\tests\Packaging" ))
{
Write-Host "Create packaging directory"
mkdir "$($this.BuildTemp)\tests\Packaging" > $null
}
$this.CopyFiles("$($this.SolutionRoot)\src\Umbraco.Tests\Packaging\Packages", "*", "$($this.BuildTemp)\tests\Packaging\Packages")
# required for package install tests
if (-not (Test-Path -Path "$($this.BuildTemp)\tests\bin" ))
{
Write-Host "Create bin directory"
mkdir "$($this.BuildTemp)\tests\bin" > $null
}
})
$ubuild.DefineMethod("CompileTests",
{
$buildConfiguration = "Release"
$log = "$($this.BuildTemp)\msbuild.tests.log"
if ($this.BuildEnv.VisualStudio -eq $null)
{
throw "Build environment does not provide VisualStudio."
}
Write-Host "Compile Tests"
Write-Host "Logging to $log"
# beware of the weird double \\ at the end of paths
# see http://edgylogic.com/blog/powershell-and-external-commands-done-right/
&$this.BuildEnv.VisualStudio.MsBuild "$($this.SolutionRoot)\src\Umbraco.Tests\Umbraco.Tests.csproj" `
/p:WarningLevel=0 `
/p:Configuration=$buildConfiguration `
/p:Platform=AnyCPU `
/p:UseWPP_CopyWebApplication=True `
/p:PipelineDependsOnBuild=False `
/p:OutDir="$($this.BuildTemp)\tests\\" `
/p:Verbosity=minimal `
/t:Build `
/tv:"$($this.BuildEnv.VisualStudio.ToolsVersion)" `
/p:UmbracoBuild=True `
> $log
if (-not $?) { throw "Failed to compile tests." }
# /p:UmbracoBuild tells the csproj that we are building from PS
})
$ubuild.DefineMethod("PreparePackages",
{
Write-Host "Prepare Packages"
$src = "$($this.SolutionRoot)\src"
$tmp = "$($this.BuildTemp)"
$out = "$($this.BuildOutput)"
$buildConfiguration = "Release"
# restore web.config
$this.TempRestoreFile("$src\Umbraco.Web.UI\web.config")
# cleanup build
Write-Host "Clean build"
$this.RemoveFile("$tmp\bin\*.dll.config")
$this.RemoveFile("$tmp\WebApp\bin\*.dll.config")
# cleanup presentation
Write-Host "Cleanup presentation"
$this.RemoveDirectory("$tmp\WebApp\umbraco.presentation")
# create directories
Write-Host "Create directories"
mkdir "$tmp\Configs" > $null
mkdir "$tmp\Configs\Lang" > $null
mkdir "$tmp\WebApp\App_Data" > $null
#mkdir "$tmp\WebApp\Media" > $null
#mkdir "$tmp\WebApp\Views" > $null
# copy various files
Write-Host "Copy xml documentation"
Copy-Item -force "$tmp\bin\*.xml" "$tmp\WebApp\bin"
Write-Host "Copy transformed configs and langs"
# note: exclude imageprocessor/*.config as imageprocessor pkg installs them
$this.CopyFiles("$tmp\WebApp\config", "*.config", "$tmp\Configs", `
{ -not $_.RelativeName.StartsWith("imageprocessor") })
$this.CopyFiles("$tmp\WebApp\config", "*.js", "$tmp\Configs")
$this.CopyFiles("$tmp\WebApp\config\lang", "*.xml", "$tmp\Configs\Lang")
$this.CopyFile("$tmp\WebApp\web.config", "$tmp\Configs\web.config.transform")
Write-Host "Copy transformed web.config"
$this.CopyFile("$src\Umbraco.Web.UI\web.$buildConfiguration.Config.transformed", "$tmp\WebApp\web.config")
# offset the modified timestamps on all umbraco dlls, as WebResources
# break if date is in the future, which, due to timezone offsets can happen.
Write-Host "Offset dlls timestamps"
Get-ChildItem -r "$tmp\*.dll" | ForEach-Object {
$_.CreationTime = $_.CreationTime.AddHours(-11)
$_.LastWriteTime = $_.LastWriteTime.AddHours(-11)
}
# copy libs
Write-Host "Copy SqlCE libraries"
$nugetPackages = [System.Environment]::ExpandEnvironmentVariables("%userprofile%\.nuget\packages")
$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x86\native", "*.*", "$tmp\bin\x86")
$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x64\native", "*.*", "$tmp\bin\amd64")
$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x86\native", "*.*", "$tmp\WebApp\bin\x86")
$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x64\native", "*.*", "$tmp\WebApp\bin\amd64")
# copy Belle
Write-Host "Copy Belle"
$this.CopyFiles("$src\Umbraco.Web.UI\umbraco\assets", "*", "$tmp\WebApp\umbraco\assets")
$this.CopyFiles("$src\Umbraco.Web.UI\umbraco\js", "*", "$tmp\WebApp\umbraco\js")
$this.CopyFiles("$src\Umbraco.Web.UI\umbraco\lib", "*", "$tmp\WebApp\umbraco\lib")
$this.CopyFiles("$src\Umbraco.Web.UI\umbraco\views", "*", "$tmp\WebApp\umbraco\views")
})
$ubuild.DefineMethod("PackageZip",
{
Write-Host "Create Zip packages"
$src = "$($this.SolutionRoot)\src"
$tmp = $this.BuildTemp
$out = $this.BuildOutput
Write-Host "Zip all binaries"
&$this.BuildEnv.Zip a -r "$out\UmbracoCms.AllBinaries.$($this.Version.Semver).zip" `
"$tmp\bin\*" `
"-x!dotless.Core.*" `
> $null
if (-not $?) { throw "Failed to zip UmbracoCms.AllBinaries." }
Write-Host "Zip cms"
&$this.BuildEnv.Zip a -r "$out\UmbracoCms.$($this.Version.Semver).zip" `
"$tmp\WebApp\*" `
"-x!dotless.Core.*" "-x!Content_Types.xml" "-x!*.pdb" `
> $null
if (-not $?) { throw "Failed to zip UmbracoCms." }
})
$ubuild.DefineMethod("PrepareBuild",
{
Write-Host "Clear folders and files"
$this.RemoveDirectory("$($this.SolutionRoot)\src\Umbraco.Web.UI.Client\bower_components")
$this.TempStoreFile("$($this.SolutionRoot)\src\Umbraco.Web.UI\web.config")
Write-Host "Create clean web.config"
$this.CopyFile("$($this.SolutionRoot)\src\Umbraco.Web.UI\web.Template.config", "$($this.SolutionRoot)\src\Umbraco.Web.UI\web.config")
Write-host "Set environment"
$env:UMBRACO_VERSION=$this.Version.Semver.ToString()
$env:UMBRACO_RELEASE=$this.Version.Release
$env:UMBRACO_COMMENT=$this.Version.Comment
$env:UMBRACO_BUILD=$this.Version.Build
if ($args -and $args[0] -eq "vso")
{
Write-host "Set VSO environment"
# set environment variable for VSO
# https://github.com/Microsoft/vsts-tasks/issues/375
# https://github.com/Microsoft/vsts-tasks/blob/master/docs/authoring/commands.md
Write-Host ("##vso[task.setvariable variable=UMBRACO_VERSION;]$($this.Version.Semver.ToString())")
Write-Host ("##vso[task.setvariable variable=UMBRACO_RELEASE;]$($this.Version.Release)")
Write-Host ("##vso[task.setvariable variable=UMBRACO_COMMENT;]$($this.Version.Comment)")
Write-Host ("##vso[task.setvariable variable=UMBRACO_BUILD;]$($this.Version.Build)")
Write-Host ("##vso[task.setvariable variable=UMBRACO_TMP;]$($this.SolutionRoot)\build.tmp")
}
})
$ubuild.DefineMethod("PrepareNuGet",
{
Write-Host "Prepare NuGet"
# add Web.config transform files to the NuGet package
Write-Host "Add web.config transforms to NuGet package"
mv "$($this.BuildTemp)\WebApp\Views\Web.config" "$($this.BuildTemp)\WebApp\Views\Web.config.transform"
})
$ubuild.DefineMethod("RestoreNuGet",
{
Write-Host "Restore NuGet"
Write-Host "Logging to $($this.BuildTemp)\nuget.restore.log"
&$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log"
if (-not $?) { throw "Failed to restore NuGet packages." }
})
$ubuild.DefineMethod("PackageNuGet",
{
$nuspecs = "$($this.SolutionRoot)\build\NuSpecs"
Write-Host "Create NuGet packages"
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Core.nuspec" `
-Properties BuildTmp="$($this.BuildTemp)" `
-Version "$($this.Version.Semver.ToString())" `
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmscore.log"
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Core." }
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.nuspec" `
-Properties BuildTmp="$($this.BuildTemp)" `
-Version $this.Version.Semver.ToString() `
-Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cms.log"
if (-not $?) { throw "Failed to pack NuGet UmbracoCms." }
# run hook
if ($this.HasMethod("PostPackageNuGet"))
{
Write-Host "Run PostPackageNuGet hook"
$this.PostPackageNuGet();
if (-not $?) { throw "Failed to run hook." }
}
})
$ubuild.DefineMethod("VerifyNuGet",
{
$this.VerifyNuGetConsistency(
("UmbracoCms", "UmbracoCms.Core"),
("Umbraco.Core", "Umbraco.Web", "Umbraco.Web.UI", "Umbraco.Examine"))
if ($this.OnError()) { return }
})
$ubuild.DefineMethod("PrepareAzureGallery",
{
Write-Host "Prepare Azure Gallery"
$this.CopyFile("$($this.SolutionRoot)\build\Azure\azuregalleryrelease.ps1", $this.BuildOutput)
})
$ubuild.DefineMethod("Build",
{
$this.PrepareBuild()
if ($this.OnError()) { return }
$this.RestoreNuGet()
if ($this.OnError()) { return }
$this.CompileBelle()
if ($this.OnError()) { return }
$this.CompileUmbraco()
if ($this.OnError()) { return }
$this.PrepareTests()
if ($this.OnError()) { return }
$this.CompileTests()
if ($this.OnError()) { return }
# not running tests
$this.PreparePackages()
if ($this.OnError()) { return }
$this.PackageZip()
if ($this.OnError()) { return }
$this.VerifyNuGet()
if ($this.OnError()) { return }
$this.PrepareNuGet()
if ($this.OnError()) { return }
$this.PackageNuGet()
if ($this.OnError()) { return }
$this.PrepareAzureGallery()
if ($this.OnError()) { return }
})
# ################################################################
# RUN
# ################################################################
# configure
$ubuild.ReleaseBranches = @( "master" )
# run
if (-not $get)
{
$ubuild.Build()
if ($ubuild.OnError()) { return }
}
Write-Host "Done"
if ($get) { return $ubuild }
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
</configuration>
Binary file not shown.
+138
View File
@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
<!-- Enable the restore command to run before builds -->
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
<!-- Property that enables building a package from a project -->
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
<!-- Determines if package restore consent is required to restore packages -->
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
<!-- Download NuGet.exe if it does not already exist -->
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageSources)' == '' ">
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
<!--
<PackageSource Include="https://www.nuget.org/api/v2/" />
<PackageSource Include="https://my-nuget-source/nuget/" />
-->
<PackageSource Include="https://nuget.org/api/v2/" />
<PackageSource Include="http://www.myget.org/F/umbracocore/" />
</ItemGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
<!-- Windows specific commands -->
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
<PackagesConfig>packages.config</PackagesConfig>
</PropertyGroup>
<PropertyGroup>
<!-- NuGet command -->
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
<!-- Commands -->
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
<!-- We need to ensure packages are restored prior to assembly resolve -->
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
RestorePackages;
$(BuildDependsOn);
</BuildDependsOn>
<!-- Make the build depend on restore packages -->
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
$(BuildDependsOn);
BuildPackage;
</BuildDependsOn>
</PropertyGroup>
<Target Name="CheckPrerequisites">
<!-- Raise an error if we're unable to locate nuget.exe -->
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
<!--
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
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;DownloadNuGetExe=$(DownloadNuGetExe)" />
</Target>
<Target Name="_DownloadNuGet">
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
</Target>
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(RestoreCommand)"
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
<Exec Command="$(RestoreCommand)"
LogStandardErrorAsError="true"
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
</Target>
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(BuildCommand)"
Condition=" '$(OS)' != 'Windows_NT' " />
<Exec Command="$(BuildCommand)"
LogStandardErrorAsError="true"
Condition=" '$(OS)' == 'Windows_NT' " />
</Target>
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<OutputFilename ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Net" />
<Using Namespace="Microsoft.Build.Framework" />
<Using Namespace="Microsoft.Build.Utilities" />
<Code Type="Fragment" Language="cs">
<![CDATA[
try {
OutputFilename = Path.GetFullPath(OutputFilename);
Log.LogMessage("Downloading latest version of NuGet.exe...");
WebClient webClient = new WebClient();
webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
return true;
}
catch (Exception ex) {
Log.LogErrorFromException(ex);
return false;
}
]]>
</Code>
</Task>
</UsingTask>
</Project>
-18
View File
@@ -1,18 +0,0 @@
apiRules:
- include:
uidRegex: ^Umbraco\.Core
- exclude:
uidRegex: ^umbraco\.Web\.org
- include:
uidRegex: ^Umbraco\.Web
- exclude:
hasAttribute:
uid: System.ComponentModel.EditorBrowsableAttribute
ctorArguments:
- System.ComponentModel.EditorBrowsableState.Never
- exclude:
uidRegex: ^umbraco\.
- exclude:
uidRegex: ^CookComputing\.
- exclude:
uidRegex: ^.*$
-75
View File
@@ -1,75 +0,0 @@
{
"metadata": [
{
"src": [
{
"files": [
"Umbraco.Core/Umbraco.Core.csproj",
"Umbraco.Web/Umbraco.Web.csproj"
],
"exclude": [
"**/obj/**",
"**/bin/**",
"_site/**"
],
"cwd": "../src"
}
],
"dest": "../apidocs/api",
"filter": "../apidocs/docfx.filter.yml"
}
],
"build": {
"content": [
{
"files": [
"api/**.yml",
"api/index.md"
]
},
{
"files": [
"articles/**.md",
"articles/**/toc.yml",
"toc.yml",
"*.md"
],
"exclude": [
"obj/**",
"_site/**"
]
}
],
"resource": [
{
"files": [
"images/**"
],
"exclude": [
"obj/**",
"_site/**"
]
}
],
"overwrite": [
{
"files": [
"**.md"
],
"exclude": [
"obj/**",
"_site/**"
]
}
],
"globalMetadata": {
"_appTitle": "Umbraco c# Api docs",
"_enableSearch": true,
"_disableContribution": false
},
"dest": "_site",
"template": [
"default", "umbracotemplate"
]
}
}
-7
View File
@@ -1,7 +0,0 @@
# Umbraco c# API reference
## Quick Links:
### [Umbraco.Core](api/Umbraco.Core.html) docs
### [Umbraco.Web](api/Umbraco.Web.html) docs
-5
View File
@@ -1,5 +0,0 @@
- name: Umbraco.Core Documentation
href: https://our.umbraco.org/apidocs/csharp/api/Umbraco.Core.html
- name: Umbraco.Web Documentation
href: https://our.umbraco.org/apidocs/csharp/api/Umbraco.Web.html
@@ -1,257 +0,0 @@
{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
{{^_disableContribution}}
{{#sourceurl}}<a href="{{sourceurl}}" class="btn btn-primary pull-right mobile-hide">{{__global.viewSource}}</a>{{/sourceurl}}
{{/_disableContribution}}
<h1 id="{{id}}" data-uid="{{uid}}">{{>partials/title}}</h1>
<div class="markdown level0 summary">{{{summary}}}</div>
<div class="markdown level0 conceptual">{{{conceptual}}}</div>
{{#inheritance.0}}
<div class="inheritance">
<h5>{{__global.inheritance}}</h5>
{{#inheritance}}
<div class="level{{index}}">{{{specName.0.value}}}</div>
{{/inheritance}}
<div class="level{{item.level}}"><span class="xref">{{item.name.0.value}}</span></div>
</div>
{{/inheritance.0}}
<h6><strong>{{__global.namespace}}</strong>:{{namespace}}</h6>
<h6><strong>{{__global.assembly}}</strong>:{{assemblies.0}}.dll</h6>
<h5 id="{{id}}_syntax">{{__global.syntax}}</h5>
<div class="codewrapper">
<pre><code class="lang-{{_lang}} hljs">{{syntax.content.0.value}}</code></pre>
</div>
{{#syntax.parameters.0}}
<h5 class="parameters">{{__global.parameters}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.type}}</th>
<th>{{__global.name}}</th>
<th>{{__global.description}}</th>
</tr>
</thead>
<tbody>
{{/syntax.parameters.0}}
{{#syntax.parameters}}
<tr>
<td>{{{type.specName.0.value}}}</td>
<td><em>{{{id}}}</em></td>
<td>{{{description}}}</td>
</tr>
{{/syntax.parameters}}
{{#syntax.parameters.0}}
</tbody>
</table>
{{/syntax.parameters.0}}
{{#syntax.return}}
<h5 class="returns">{{__global.returns}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.type}}</th>
<th>{{__global.description}}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{{type.specName.0.value}}}</td>
<td>{{{description}}}</td>
</tr>
</tbody>
</table>
{{/syntax.return}}
{{#syntax.typeParameters.0}}
<h5 class="typeParameters">{{__global.typeParameters}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.name}}</th>
<th>{{__global.description}}</th>
</tr>
</thead>
<tbody>
{{/syntax.typeParameters.0}}
{{#syntax.typeParameters}}
<tr>
<td><em>{{{id}}}</em></td>
<td>{{{description}}}</td>
</tr>
{{/syntax.typeParameters}}
{{#syntax.typeParameters.0}}
</tbody>
</table>
{{/syntax.typeParameters.0}}
{{#remarks}}
<h5 id="{{id}}_remarks"><strong>{{__global.remarks}}</strong></h5>
<div class="markdown level0 remarks">{{{remarks}}}</div>
{{/remarks}}
{{#example.0}}
<h5 id="{{id}}_examples"><strong>{{__global.examples}}</strong></h5>
{{/example.0}}
{{#example}}
{{{.}}}
{{/example}}
{{#children}}
<h3 id="{{id}}">{{>partials/classSubtitle}}</h3>
{{#children}}
{{^_disableContribution}}
{{#sourceurl}}
<span class="small pull-right mobile-hide">
<a href="{{sourceurl}}">{{__global.viewSource}}</a>
</span>{{/sourceurl}}
{{/_disableContribution}}
<h4 id="{{id}}" data-uid="{{uid}}">{{name.0.value}}</h4>
<div class="markdown level1 summary">{{{summary}}}</div>
<div class="markdown level1 conceptual">{{{conceptual}}}</div>
<h5 class="decalaration">{{__global.declaration}}</h5>
{{#syntax}}
<div class="codewrapper">
<pre><code class="lang-{{_lang}} hljs">{{syntax.content.0.value}}</code></pre>
</div>
{{#parameters.0}}
<h5 class="parameters">{{__global.parameters}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.type}}</th>
<th>{{__global.name}}</th>
<th>{{__global.description}}</th>
</tr>
</thead>
<tbody>
{{/parameters.0}}
{{#parameters}}
<tr>
<td>{{{type.specName.0.value}}}</td>
<td><em>{{{id}}}</em></td>
<td>{{{description}}}</td>
</tr>
{{/parameters}}
{{#parameters.0}}
</tbody>
</table>
{{/parameters.0}}
{{#return}}
<h5 class="returns">{{__global.returns}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.type}}</th>
<th>{{__global.description}}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{{type.specName.0.value}}}</td>
<td>{{{description}}}</td>
</tr>
</tbody>
</table>
{{/return}}
{{#typeParameters.0}}
<h5 class="typeParameters">{{__global.typeParameters}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.name}}</th>
<th>{{__global.description}}</th>
</tr>
</thead>
<tbody>
{{/typeParameters.0}}
{{#typeParameters}}
<tr>
<td><em>{{{id}}}</em></td>
<td>{{{description}}}</td>
</tr>
{{/typeParameters}}
{{#typeParameters.0}}
</tbody>
</table>
{{/typeParameters.0}}
{{#fieldValue}}
<h5 class="fieldValue">{{__global.fieldValue}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.type}}</th>
<th>{{__global.description}}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{{type.specName.0.value}}}</td>
<td>{{{description}}}</td>
</tr>
</tbody>
</table>
{{/fieldValue}}
{{#propertyValue}}
<h5 class="propertyValue">{{__global.propertyValue}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.type}}</th>
<th>{{__global.description}}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{{type.specName.0.value}}}</td>
<td>{{{description}}}</td>
</tr>
</tbody>
</table>
{{/propertyValue}}
{{#eventType}}
<h5 class="eventType">{{__global.eventType}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.type}}</th>
<th>{{__global.description}}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{{type.specName.0.value}}}</td>
<td>{{{description}}}</td>
</tr>
</tbody>
</table>
{{/eventType}}
{{/syntax}}
{{#remarks}}
<h5 id="{{id}}_remarks">{{__global.remarks}}</h5>
<div class="markdown level1 remarks">{{{remarks}}}</div>
{{/remarks}}
{{#example.0}}
<h5 id="{{id}}_examples">{{__global.examples}}</h5>
{{/example.0}}
{{#example}}
{{{.}}}
{{/example}}
{{#exceptions.0}}
<h5 class="exceptions">{{__global.exceptions}}</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{{__global.type}}</th>
<th>{{__global.condition}}</th>
</tr>
</thead>
<tbody>
{{/exceptions.0}}
{{#exceptions}}
<tr>
<td>{{{type.specName.0.value}}}</td>
<td>{{{description}}}</td>
</tr>
{{/exceptions}}
{{#exceptions.0}}
</tbody>
</table>
{{/exceptions.0}}
{{/children}}
{{/children}}
@@ -1,13 +0,0 @@
{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
<footer>
<div class="grad-bottom"></div>
<div class="footer">
<div class="container">
<span class="pull-right">
<a href="#top">Back to top</a>
</span>
<span>Copyright © 2016 Umbraco<br>Generated by <strong>DocFX</strong></span>
</div>
</div>
</footer>
@@ -1,18 +0,0 @@
{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>{{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}</title>
<meta name="viewport" content="width=device-width">
<meta name="title" content="{{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}">
<meta name="generator" content="docfx {{_docfxVersion}}">
{{#_description}}<meta name="description" content="{{_description}}">{{/_description}}
<link rel="icon" type="image/png" href="https://our.umbraco.org/assets/images/app-icons/favicon.png">
<link rel="stylesheet" href="{{_rel}}styles/docfx.vendor.css">
<link rel="stylesheet" href="{{_rel}}styles/docfx.css">
<link rel="stylesheet" href="{{_rel}}styles/main.css">
<meta property="docfx:navrel" content="{{_navRel}}">
<meta property="docfx:tocrel" content="{{_tocRel}}">
{{#_enableSearch}}<meta property="docfx:rel" content="{{_rel}}">{{/_enableSearch}}
</head>
@@ -1,18 +0,0 @@
{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
{{^_disableContribution}}
{{#sourceurl}}
<a href="{{sourceurl}}" class="btn btn-primary pull-right mobile-hide">{{__global.viewSource}}</a>
{{/sourceurl}}
{{/_disableContribution}}
<h1 id="{{id}}" data-uid="{{uid}}">{{>partials/title}}</h1>
<div class="markdown level0 summary">{{{summary}}}</div>
<div class="markdown level0 conceptual">{{{conceptual}}}</div>
<div class="markdown level0 remarks">{{{remarks}}}</div>
{{#children}}
<h3 id="{{id}}">{{>partials/namespaceSubtitle}}</h3>
{{#children}}
<h4>{{{specName.0.value}}}</h4>
<section>{{{summary}}}</section>
{{/children}}
{{/children}}
@@ -1,22 +0,0 @@
{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
<nav id="autocollapse" class="navbar navbar-inverse ng-scope" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/" alt="Our Umbraco"></a>
</div>
<div class="collapse navbar-collapse" id="navbar">
<form class="navbar-form navbar-right" role="search" id="search">
<div class="form-group">
<input type="text" class="form-control" id="search-query" placeholder="Search" autocomplete="off">
</div>
</form>
</div>
</div>
</nav>
@@ -1,101 +0,0 @@
{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
{{^_disableContribution}}
{{#sourceurl}}<a href="{{sourceurl}}" class="btn btn-primary pull-right mobile-hide">View Source</a>{{/sourceurl}}
{{/_disableContribution}}
<h1 id="{{htmlId}}" data-uid="{{uid}}" class="text-capitalize">{{name}}</h1>
{{#summary}}
<div class="markdown level0 summary">{{{summary}}}</div>
{{/summary}}
{{#description}}
<div class="markdown level0 description">{{{description}}}</div>
{{/description}}
{{#conceptual}}
<div class="markdown level0 conceptual">{{{conceptual}}}</div>
{{/conceptual}}
{{#children}}
{{^_disableContribution}}
{{#sourceurl}}
<span class="small pull-right mobile-hide">
<a href="{{sourceurl}}">View Source</a>
</span>{{/sourceurl}}
{{/_disableContribution}}
<h3 id="{{htmlId}}" data-uid="{{uid}}" class="text-capitalize">{{operationId}}</h3>
{{#summary}}
<div class="markdown level1 summary">{{{summary}}}</div>
{{/summary}}
{{#description}}
<div class="markdown level1 description">{{{description}}}</div>
{{/description}}
{{#conceptual}}
<div class="markdown level1 conceptual">{{{conceptual}}}</div>
{{/conceptual}}
<h5>Request</h5>
<div class="codewrapper">
<pre><code class="lang-restApi hljs">{{operation}} {{path}}</code></pre>
</div>
{{#parameters.0}}
<h5>Parameters</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Value</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
{{/parameters.0}}
{{#parameters}}
<tr>
<td><em>{{#required}}*{{/required}}{{name}}</em></td>
<td>{{type}}</td>
<td>{{default}}</td>
<td>{{{description}}}</td>
</tr>
{{/parameters}}
{{#parameters.0}}
</tbody>
</table>
{{/parameters.0}}
{{#responses.0}}
<div class="responses">
<h5>Responses</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Status Code</th>
<th>Description</th>
<th>Samples</th>
</tr>
</thead>
<tbody>
{{/responses.0}}
{{#responses}}
<tr>
<td><span class="status">{{statusCode}}</span></td>
<td>{{{description}}}</td>
<td class="sample-response">
{{#examples}}
<div class="mime-type">
<i>Mime type: </i><span class="mime">{{mimeType}}</span>
</div>
<pre class="response-content"><code class="lang-js json hljs">{{content}}</code></pre>
{{/examples}}
</td>
</tr>
{{/responses}}
{{#responses.0}}
</tbody>
</table>
</div>
{{/responses.0}}
{{#footer}}
<div class="markdown level1 api-footer">{{{footer}}}</div>
{{/footer}}
{{/children}}
{{#footer}}
<div class="markdown level0 api-footer">{{{footer}}}</div>
{{/footer}}
@@ -1,73 +0,0 @@
body {
color: rgba(0,0,0,.8);
}
.navbar-inverse {
background: #a3db78;
}
.navbar-inverse .navbar-nav>li>a, .navbar-inverse .navbar-text {
color: rgba(0,0,0,.8);
}
.navbar-inverse {
border-color: transparent;
}
.sidetoc {
background-color: #f5fbf1;
}
body .toc {
background-color: #f5fbf1;
}
.sidefilter {
background-color: #daf0c9;
}
.subnav {
background-color: #f5fbf1;
}
.navbar-inverse .navbar-nav>.active>a {
color: rgba(0,0,0,.8);
background-color: #daf0c9;
}
.navbar-inverse .navbar-nav>.active>a:focus, .navbar-inverse .navbar-nav>.active>a:hover {
color: rgba(0,0,0,.8);
background-color: #daf0c9;
}
.btn-primary {
color: rgba(0,0,0,.8);
background-color: #fff;
border-color: rgba(0,0,0,.8);
}
.btn-primary:hover {
background-color: #daf0c9;
color: rgba(0,0,0,.8);
border-color: rgba(0,0,0,.8);
}
.toc .nav > li > a {
color: rgba(0,0,0,.8);
}
button, a {
color: #f36f21;
}
button:hover,
button:focus,
a:hover,
a:focus {
color: #143653;
text-decoration: none;
}
.navbar-header .navbar-brand {
background: url(https://our.umbraco.org/assets/images/logo.svg) left center no-repeat;
background-size: 40px auto;
width:50px;
}
.toc .nav > li.active > a {
color: #f36f21;
}
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
<add key="umbracocore" value="http://www.myget.org/f/umbracocore/" />
</packageSources>
</configuration>
@@ -0,0 +1,21 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SqlCE4Umbraco")]
[assembly: AssemblyDescription("Umbraco specific Sql Ce Provider")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("Umbraco CMS")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("04436b0a-1dc6-4ee1-9d96-4c04f1a9f429")]
[assembly: InternalsVisibleTo("Umbraco.Tests")]
+106
View File
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{5BA5425F-27A7-4677-865E-82246498AA2E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SQLCE4Umbraco</RootNamespace>
<AssemblyName>SQLCE4Umbraco</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\SQLCE4Umbraco.XML</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\SolutionInfo.cs">
<Link>Properties\SolutionInfo.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SqlCeApplicationBlock.cs" />
<Compile Include="SqlCeContextGuardian.cs" />
<Compile Include="SqlCEDataReader.cs" />
<Compile Include="SqlCEHelper.cs" />
<Compile Include="SqlCEInstaller.cs" />
<Compile Include="SqlCEParameter.cs" />
<Compile Include="SqlCeProviderException.cs" />
<Compile Include="SqlCETableUtility.cs" />
<Compile Include="SqlCEUtility.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config">
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\umbraco.datalayer\umbraco.datalayer.csproj">
<Project>{C7CB79F0-1C97-4B33-BFA7-00731B579AE2}</Project>
<Name>umbraco.datalayer</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp50</s:String></wpf:ResourceDictionary>
+44
View File
@@ -0,0 +1,44 @@
/************************************************************************************
*
* Umbraco Data Layer
* MIT Licensed work
* ©2008 Ruben Verborgh
*
***********************************************************************************/
using System.Data.SqlServerCe;
using umbraco.DataLayer;
namespace SqlCE4Umbraco
{
/// <summary>
/// Class that adapts a SqlDataReader.SqlDataReader to a RecordsReaderAdapter.
/// </summary>
public class SqlCeDataReaderHelper : RecordsReaderAdapter<SqlCeDataReader>
{
#region Public Constructors
/// <summary>
/// Initializes a new instance of the <see cref="SqlServerDataReader"/> class.
/// </summary>
/// <param name="dataReader">The data reader.</param>
public SqlCeDataReaderHelper(System.Data.SqlServerCe.SqlCeDataReader dataReader) : base(dataReader) { }
#endregion
#region RecordsReaderAdapter Members
/// <summary>
/// Gets a value indicating whether this instance has records.
/// </summary>
/// <value>
/// <c>true</c> if this instance has records; otherwise, <c>false</c>.
/// </value>
public override bool HasRecords
{
get { return DataReader.HasRows; }
}
#endregion
}
}
+245
View File
@@ -0,0 +1,245 @@
/************************************************************************************
*
* Umbraco Data Layer
* MIT Licensed work
* ©2008 Ruben Verborgh
*
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlServerCe;
using System.Linq;
using System.Xml;
using System.Diagnostics;
using umbraco.DataLayer;
using umbraco.DataLayer.SqlHelpers.SqlServer;
namespace SqlCE4Umbraco
{
/// <summary>
/// Sql Helper for an SQL Server database.
/// </summary>
public class SqlCEHelper : SqlHelper<SqlCeParameter>
{
/// <summary>
/// Initializes a new instance of the <see cref="SqlCEHelper"/> class.
/// </summary>
/// <param name="connectionString">The connection string.</param>
public SqlCEHelper(string connectionString) : base(connectionString)
{
m_Utility = new SqlCEUtility(this);
}
/// <summary>
/// Checks if the actual database exists, if it doesn't then it will create it
/// </summary>
internal void CreateEmptyDatabase()
{
var localConnection = new SqlCeConnection(ConnectionString);
if (!System.IO.File.Exists(ReplaceDataDirectory(localConnection.Database)))
{
var sqlCeEngine = new SqlCeEngine(ConnectionString);
sqlCeEngine.CreateDatabase();
// SD: Pretty sure this should be in a using clause but i don't want to cause unknown side-effects here
// since it's been like this for quite some time
//using (var sqlCeEngine = new SqlCeEngine(ConnectionString))
//{
// sqlCeEngine.CreateDatabase();
//}
}
}
/// <summary>
/// Most likely only will be used for unit tests but will remove all tables from the database
/// </summary>
internal void ClearDatabase()
{
// drop constraints before tables to avoid exceptions
// looping on try/catching exceptions was not really nice
// http://stackoverflow.com/questions/536350/drop-all-the-tables-stored-procedures-triggers-constriants-and-all-the-depend
var localConnection = new SqlCeConnection(ConnectionString);
if (System.IO.File.Exists(ReplaceDataDirectory(localConnection.Database)))
{
List<string> tables;
// drop foreign keys
// SQL may need "where constraint_catalog=DB_NAME() and ..."
tables = new List<string>();
using (var reader = ExecuteReader("select table_name from information_schema.table_constraints where constraint_type = 'FOREIGN KEY' order by table_name"))
{
while (reader.Read()) tables.Add(reader.GetString("table_name").Trim());
}
foreach (var table in tables)
{
var constraints = new List<string>();
using (var reader = ExecuteReader("select constraint_name from information_schema.table_constraints where constraint_type = 'FOREIGN KEY' and table_name = '" + table + "' order by constraint_name"))
{
while (reader.Read()) constraints.Add(reader.GetString("constraint_name").Trim());
}
foreach (var constraint in constraints)
{
// SQL may need "[dbo].[table]"
ExecuteNonQuery("alter table [" + table + "] drop constraint [" + constraint + "]");
}
}
// drop primary keys
// SQL may need "where constraint_catalog=DB_NAME() and ..."
tables = new List<string>();
using (var reader = ExecuteReader("select table_name from information_schema.table_constraints where constraint_type = 'PRIMARY KEY' order by table_name"))
{
while (reader.Read()) tables.Add(reader.GetString("table_name").Trim());
}
foreach (var table in tables)
{
var constraints = new List<string>();
using (var reader = ExecuteReader("select constraint_name from information_schema.table_constraints where constraint_type = 'PRIMARY KEY' and table_name = '" + table + "' order by constraint_name"))
{
while (reader.Read()) constraints.Add(reader.GetString("constraint_name").Trim());
}
foreach (var constraint in constraints)
{
// SQL may need "[dbo].[table]"
ExecuteNonQuery("alter table [" + table + "] drop constraint [" + constraint + "]");
}
}
// drop tables
tables = new List<string>();
using (var reader = ExecuteReader("select table_name from information_schema.tables where table_type <> 'VIEW' order by table_name"))
{
while (reader.Read()) tables.Add(reader.GetString("table_name").Trim());
}
foreach (var table in tables)
{
ExecuteNonQuery("drop table [" + table + "]");
}
}
}
/// <summary>
/// Drops all foreign keys on a table.
/// </summary>
/// <param name="table">The name of the table.</param>
/// <remarks>To be used in unit tests.</remarks>
internal void DropForeignKeys(string table)
{
var constraints = new List<string>();
using (var reader = ExecuteReader("select constraint_name from information_schema.table_constraints where constraint_type = 'FOREIGN KEY' and table_name = '" + table + "' order by constraint_name"))
{
while (reader.Read()) constraints.Add(reader.GetString("constraint_name").Trim());
}
foreach (var constraint in constraints)
{
// SQL may need "[dbo].[table]"
ExecuteNonQuery("alter table [" + table + "] drop constraint [" + constraint + "]");
}
}
/// <summary>
/// Replaces the data directory with a local path.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>A local path with the resolved 'DataDirectory' mapping.</returns>
private string ReplaceDataDirectory(string path)
{
if (!string.IsNullOrWhiteSpace(path) && path.Contains("|DataDirectory|"))
{
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory") as string;
if (!string.IsNullOrEmpty(dataDirectory))
{
path = path.Contains(@"|\")
? path.Replace("|DataDirectory|", dataDirectory)
: path.Replace("|DataDirectory|", dataDirectory + System.IO.Path.DirectorySeparatorChar);
}
}
return path;
}
/// <summary>
/// Creates a new parameter for use with this specific implementation of ISqlHelper.
/// </summary>
/// <param name="parameterName">Name of the parameter.</param>
/// <param name="value">Value of the parameter.</param>
/// <returns>A new parameter of the correct type.</returns>
/// <remarks>Abstract factory pattern</remarks>
public override IParameter CreateParameter(string parameterName, object value)
{
return new SqlCEParameter(parameterName, value);
}
/// <summary>
/// Executes a command that returns a single value.
/// </summary>
/// <param name="commandText">The command text.</param>
/// <param name="parameters">The parameters.</param>
/// <returns>The return value of the command.</returns>
protected override object ExecuteScalar(string commandText, SqlCeParameter[] parameters)
{
#if DEBUG && DebugDataLayer
// Log Query Execution
Trace.TraceInformation(GetType().Name + " SQL ExecuteScalar: " + commandText);
#endif
return SqlCeApplicationBlock.ExecuteScalar(ConnectionString, CommandType.Text, commandText, parameters);
}
/// <summary>
/// Executes a command and returns the number of rows affected.
/// </summary>
/// <param name="commandText">The command text.</param>
/// <param name="parameters">The parameters.</param>
/// <returns>
/// The number of rows affected by the command.
/// </returns>
protected override int ExecuteNonQuery(string commandText, SqlCeParameter[] parameters)
{
#if DEBUG && DebugDataLayer
// Log Query Execution
Trace.TraceInformation(GetType().Name + " SQL ExecuteNonQuery: " + commandText);
#endif
return SqlCeApplicationBlock.ExecuteNonQuery(ConnectionString, CommandType.Text, commandText, parameters);
}
/// <summary>
/// Executes a command and returns a records reader containing the results.
/// </summary>
/// <param name="commandText">The command text.</param>
/// <param name="parameters">The parameters.</param>
/// <returns>
/// A data reader containing the results of the command.
/// </returns>
protected override IRecordsReader ExecuteReader(string commandText, SqlCeParameter[] parameters)
{
#if DEBUG && DebugDataLayer
// Log Query Execution
Trace.TraceInformation(GetType().Name + " SQL ExecuteReader: " + commandText);
#endif
return new SqlCeDataReaderHelper(SqlCeApplicationBlock.ExecuteReader(ConnectionString, CommandType.Text,
commandText, parameters));
}
internal IRecordsReader ExecuteReader(string commandText)
{
return ExecuteReader(commandText, new SqlCEParameter(string.Empty, string.Empty));
}
internal int ExecuteNonQuery(string commandText)
{
return ExecuteNonQuery(commandText, new SqlCEParameter(string.Empty, string.Empty));
}
}
}
+139
View File
@@ -0,0 +1,139 @@
/************************************************************************************
*
* Umbraco Data Layer
* MIT Licensed work
* ©2008 Ruben Verborgh
*
***********************************************************************************/
using System;
using System.Resources;
using SQLCE4Umbraco;
using umbraco.DataLayer.Utility.Installer;
using System.Diagnostics;
namespace SqlCE4Umbraco
{
/// <summary>
/// Database installer for an SQL Server data source.
/// </summary>
[Obsolete("The legacy installers are no longer used and will be removed from the codebase in the future")]
public class SqlCEInstaller : DefaultInstallerUtility<SqlCEHelper>
{
#region Private Constants
/// <summary>The latest database version this installer supports.</summary>
private const DatabaseVersion LatestVersionSupported = DatabaseVersion.Version4_8;
/// <summary>The specifications to determine the database version.</summary>
private static readonly VersionSpecs[] m_VersionSpecs = new VersionSpecs[] {
new VersionSpecs("SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS LEFT OUTER JOIN umbracoApp ON appAlias = appAlias WHERE CONSTRAINT_NAME = 'FK_umbracoUser2app_umbracoApp'", 0, DatabaseVersion.Version4_8),
new VersionSpecs("SELECT id FROM umbracoNode WHERE id = -21", 1, DatabaseVersion.Version4_1),
new VersionSpecs("SELECT action FROM umbracoAppTree",DatabaseVersion.Version4),
new VersionSpecs("SELECT description FROM cmsContentType",DatabaseVersion.Version3),
new VersionSpecs("SELECT id FROM sysobjects",DatabaseVersion.None) };
#endregion
#region Public Properties
/// <summary>
/// This ensures that the database exists, then runs the base method
/// </summary>
public override bool CanConnect
{
get
{
SqlHelper.CreateEmptyDatabase();
return base.CanConnect;
}
}
/// <summary>
/// Gets a value indicating whether the installer can upgrade the data source.
/// </summary>
/// <value>
/// <c>true</c> if the installer can upgrade the data source; otherwise, <c>false</c>.
/// </value>
/// <remarks>Empty data sources can't be upgraded, just installed.</remarks>
public override bool CanUpgrade
{
get
{
return CurrentVersion == DatabaseVersion.Version4_1;
}
}
#endregion
#region Protected Properties
/// <summary>
/// Gets the version specification for evaluation by DetermineCurrentVersion.
/// Only first matching specification is taken into account.
/// </summary>
/// <value>The version specifications.</value>
protected override VersionSpecs[] VersionSpecs
{
get { return m_VersionSpecs; }
}
#endregion
#region Public Constructors
/// <summary>
/// Initializes a new instance of the <see cref="SqlCEInstaller"/> class.
/// </summary>
/// <param name="sqlHelper">The SQL helper.</param>
public SqlCEInstaller(SqlCEHelper sqlHelper) : base(sqlHelper, LatestVersionSupported)
{ }
#endregion
#region DefaultInstaller Members
/// <summary>
/// Returns the sql to do a full install
/// </summary>
protected override string FullInstallSql
{
get { return string.Empty; }
}
/// <summary>
/// Returns the sql to do an upgrade
/// </summary>
protected override string UpgradeSql
{
get { return string.Empty; }
}
// We need to override this as the default way of detection a db connection checks for systables that doesn't exist
// in a CE db
protected override DatabaseVersion DetermineCurrentVersion()
{
DatabaseVersion version = base.DetermineCurrentVersion();
if (version != DatabaseVersion.Unavailable)
{
return version;
}
// verify connection
try
{
if (SqlCeApplicationBlock.VerifyConnection(base.SqlHelper.ConnectionString))
return DatabaseVersion.None;
}
catch (Exception e)
{
Trace.WriteLine(e.ToString());
}
return DatabaseVersion.Unavailable;
}
#endregion
}
}
+34
View File
@@ -0,0 +1,34 @@
/************************************************************************************
*
* Umbraco Data Layer
* MIT Licensed work
* ©2008 Ruben Verborgh
*
***********************************************************************************/
using System;
using System.Data.SqlServerCe;
using System.Data.SqlTypes;
using umbraco.DataLayer;
namespace SqlCE4Umbraco
{
/// <summary>
/// Parameter class for the SqlCEHelper.
/// </summary>
public class SqlCEParameter : SqlParameterAdapter<SqlCeParameter>
{
#region Public Constructors
/// <summary>
/// Initializes a new instance of the <see cref="SqlCEParameter"/> class.
/// </summary>
/// <param name="parameterName">Name of the parameter.</param>
/// <param name="value">Value of the parameter.</param>
public SqlCEParameter(string parameterName, object value)
: base(new SqlCeParameter(parameterName, value))
{ }
#endregion
}
}
+244
View File
@@ -0,0 +1,244 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using umbraco.DataLayer.Utility.Table;
using umbraco.DataLayer;
using umbraco;
namespace SqlCE4Umbraco
{
/// <summary>
/// SQL Server implementation of <see cref="DefaultTableUtility&lt;S&gt;"/>.
/// </summary>
[Obsolete("The legacy installers are no longer used and will be removed from the codebase in the future")]
public class SqlCETableUtility : DefaultTableUtility<SqlCEHelper>
{
/// <summary>
/// Initializes a new instance of the <see cref="SqlCETableUtility"/> class.
/// </summary>
/// <param name="sqlHelper">The SQL helper.</param>
public SqlCETableUtility(SqlCEHelper sqlHelper)
: base(sqlHelper)
{ }
#region DefaultTableUtility<SqlCEHelper> members
/// <summary>
/// Gets the table with the specified name.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>The table, or <c>null</c> if no table with that name exists.</returns>
public override ITable GetTable(string name)
{
if (name == null)
throw new ArgumentNullException("name");
ITable table = null;
// get name in correct casing
name = SqlHelper.ExecuteScalar<string>("SELECT name FROM sys.tables WHERE name=@name",
SqlHelper.CreateParameter("name", name));
if (name != null)
{
table = new DefaultTable(name);
using (IRecordsReader reader = SqlHelper.ExecuteReader(
@"SELECT c.name AS Name, st.name AS DataType, c.max_length, c.is_nullable, c.is_identity
FROM sys.tables AS t
JOIN sys.columns AS c ON t.object_id = c.object_id
JOIN sys.schemas AS s ON s.schema_id = t.schema_id
JOIN sys.types AS ty ON ty.user_type_id = c.user_type_id
JOIN sys.types st ON ty.system_type_id = st.user_type_id
WHERE t.name = @name
ORDER BY c.column_id", SqlHelper.CreateParameter("name", name)))
{
while (reader.Read())
{
table.AddField(table.CreateField(reader.GetString("Name"), GetType(reader)));
}
}
}
return table;
}
/// <summary>
/// Saves or updates the table.
/// </summary>
/// <param name="table">The table to be saved.</param>
public override void SaveTable(ITable table)
{
if (table == null)
throw new ArgumentNullException("table");
ITable oldTable = GetTable(table.Name);
// create the table if it didn't exist, update fields otherwise
if (oldTable == null)
{
CreateTable(table);
}
else
{
foreach (IField field in table)
{
// create the field if it did't exist in the old table
if (oldTable.FindField(field.Name)==null)
{
CreateColumn(table, field);
}
}
}
}
#endregion
#region Protected Helper Methods
/// <summary>
/// Creates the table in the data source.
/// </summary>
/// <param name="table">The table.</param>
protected virtual void CreateTable(ITable table)
{
Debug.Assert(table != null);
// create enumerator and check for first field
IEnumerator<IField> fieldEnumerator = table.GetEnumerator();
bool hasNext = fieldEnumerator.MoveNext();
if(!hasNext)
throw new ArgumentException("The table must contain at least one field.");
// create query
StringBuilder createTableQuery = new StringBuilder();
createTableQuery.AppendFormat("CREATE TABLE [{0}] (", SqlHelper.EscapeString(table.Name));
// add fields
while (hasNext)
{
// add field name and type
IField field = fieldEnumerator.Current;
createTableQuery.Append('[').Append(field.Name).Append(']');
createTableQuery.Append(' ').Append(GetDatabaseType(field));
// append comma if a following field exists
hasNext = fieldEnumerator.MoveNext();
if (hasNext)
{
createTableQuery.Append(',');
}
}
// close CREATE TABLE x (...) bracket
createTableQuery.Append(')');
// execute query
try
{
SqlHelper.ExecuteNonQuery(createTableQuery.ToString());
}
catch (Exception executeException)
{
throw new UmbracoException(String.Format("Could not create table '{0}'.", table), executeException);
}
}
/// <summary>
/// Creates a new column in the table.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="field">The field used to create the column.</param>
protected virtual void CreateColumn(ITable table, IField field)
{
Debug.Assert(table != null && field != null);
StringBuilder addColumnQuery = new StringBuilder();
addColumnQuery.AppendFormat("ALTER TABLE [{0}] ADD [{1}] {2}",
SqlHelper.EscapeString(table.Name),
SqlHelper.EscapeString(field.Name),
SqlHelper.EscapeString(GetDatabaseType(field)));
try
{
SqlHelper.ExecuteNonQuery(addColumnQuery.ToString());
}
catch (Exception executeException)
{
throw new UmbracoException(String.Format("Could not create column '{0}' in table '{1}'.",
field, table.Name), executeException);
}
}
/// <summary>
/// Gets the .Net type corresponding to the specified database data type.
/// </summary>
/// <param name="dataTypeReader">The data type reader.</param>
/// <returns>The .Net type</returns>
protected virtual Type GetType(IRecordsReader dataTypeReader)
{
string typeName = dataTypeReader.GetString("DataType");
switch (typeName)
{
case "bit": return typeof(bool);
case "tinyint": return typeof(byte);
case "datetime": return typeof(DateTime);
// TODO: return different decimal type according to field precision
case "decimal": return typeof(decimal);
case "uniqueidentifier": return typeof(Guid);
case "smallint": return typeof(Int16);
case "int": return typeof(Int32);
case "bigint": return typeof(Int64);
case "nvarchar": return typeof(string);
default:
throw new ArgumentException(String.Format("Cannot convert database type '{0}' to a .Net type.",
typeName));
}
}
/// <summary>
/// Gets the database type corresponding to the field, complete with field properties.
/// </summary>
/// <param name="field">The field.</param>
/// <returns>The database type.</returns>
protected virtual string GetDatabaseType(IField field)
{
StringBuilder fieldBuilder = new StringBuilder();
fieldBuilder.Append(GetDatabaseTypeName(field));
fieldBuilder.Append(field.HasProperty(FieldProperties.Identity) ? " IDENTITY(1,1)" : String.Empty);
fieldBuilder.Append(field.HasProperty(FieldProperties.NotNull) ? " NOT NULL" : " NULL");
return fieldBuilder.ToString();
}
/// <summary>
/// Gets the name of the database type, without field properties.
/// </summary>
/// <param name="field">The field.</param>
/// <returns></returns>
protected virtual string GetDatabaseTypeName(IField field)
{
switch (field.DataType.FullName)
{
case "System.Boolean": return "bit";
case "System.Byte": return "tinyint";
case "System.DateTime": return "datetime";
case "System.Decimal": return "decimal(28)";
case "System.Double": return "decimal(15)";
case "System.Single": return "decimal(7)";
case "System.Guid": return "uniqueidentifier";
case "System.Int16": return "smallint";
case "System.Int32": return "int";
case "System.Int64": return "bigint";;
case "System.String":
string type = "nvarchar";
return field.Size == 0 ? type : String.Format("{0}({1})", type, field.Size);
default:
throw new ArgumentException(String.Format("Cannot convert '{0}' to a database type.", field));
}
}
#endregion
}
}
+56
View File
@@ -0,0 +1,56 @@
/************************************************************************************
*
* Umbraco Data Layer
* MIT Licensed work
* ©2008 Ruben Verborgh
*
***********************************************************************************/
using System;
using umbraco.DataLayer.SqlHelpers.SqlServer;
using umbraco.DataLayer.Utility;
using umbraco.DataLayer.Utility.Installer;
using umbraco.DataLayer.Utility.Table;
namespace SqlCE4Umbraco
{
/// <summary>
/// Utility for an SQL Server data source.
/// </summary>
[Obsolete("The legacy installers are no longer used and will be removed from the codebase in the future")]
public class SqlCEUtility : DefaultUtility<SqlCEHelper>
{
#region Public Constructors
/// <summary>
/// Initializes a new instance of the <see cref="SqlServerUtility"/> class.
/// </summary>
/// <param name="sqlHelper">The SQL helper.</param>
public SqlCEUtility(SqlCEHelper sqlHelper) : base(sqlHelper)
{ }
#endregion
#region DefaultUtility Members
/// <summary>
/// Creates an installer.
/// </summary>
/// <returns>The SQL Server installer.</returns>
public override IInstallerUtility CreateInstaller()
{
return new SqlCEInstaller(SqlHelper);
}
/// <summary>
/// Creates a table utility.
/// </summary>
/// <returns>The table utility</returns>
public override ITableUtility CreateTableUtility()
{
return new SqlCETableUtility(SqlHelper);
}
#endregion
}
}
+188
View File
@@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlServerCe;
using System.Data;
using System.Diagnostics;
using SQLCE4Umbraco;
namespace SqlCE4Umbraco
{
public class SqlCeApplicationBlock
{
/// <summary>
///
/// </summary>
/// <param name="connectionString"></param>
/// <param name="commandType"></param>
/// <param name="commandText"></param>
/// <param name="commandParameters"></param>
/// <returns></returns>
public static object ExecuteScalar(
string connectionString,
CommandType commandType,
string commandText,
params SqlCeParameter[] commandParameters
)
{
object retVal;
try
{
using (SqlCeConnection conn = SqlCeContextGuardian.Open(connectionString))
{
using (SqlCeCommand cmd = new SqlCeCommand(commandText, conn))
{
AttachParameters(cmd, commandParameters);
Debug.WriteLine("---------------------------------SCALAR-------------------------------------");
Debug.WriteLine(commandText);
Debug.WriteLine("----------------------------------------------------------------------------");
retVal = cmd.ExecuteScalar();
}
}
return retVal;
}
catch (Exception ee)
{
throw new SqlCeProviderException("Error running Scalar: \nSQL Statement:\n" + commandText + "\n\nException:\n" + ee.ToString());
}
}
/// <summary>
///
/// </summary>
/// <param name="connectionString"></param>
/// <param name="commandType"></param>
/// <param name="commandText"></param>
/// <param name="commandParameters"></param>
public static int ExecuteNonQuery(
string connectionString,
CommandType commandType,
string commandText,
params SqlCeParameter[] commandParameters
)
{
try
{
int rowsAffected;
using (SqlCeConnection conn = SqlCeContextGuardian.Open(connectionString))
{
// this is for multiple queries in the installer
if (commandText.Trim().StartsWith("!!!"))
{
commandText = commandText.Trim().Trim('!');
string[] commands = commandText.Split('|');
string currentCmd = String.Empty;
foreach (string cmd in commands)
{
try
{
currentCmd = cmd;
if (!String.IsNullOrWhiteSpace(cmd))
{
SqlCeCommand c = new SqlCeCommand(cmd, conn);
c.ExecuteNonQuery();
}
}
catch (Exception e)
{
Debug.WriteLine("*******************************************************************");
Debug.WriteLine(currentCmd);
Debug.WriteLine(e);
Debug.WriteLine("*******************************************************************");
}
}
return 1;
}
else
{
Debug.WriteLine("----------------------------------------------------------------------------");
Debug.WriteLine(commandText);
Debug.WriteLine("----------------------------------------------------------------------------");
SqlCeCommand cmd = new SqlCeCommand(commandText, conn);
AttachParameters(cmd, commandParameters);
rowsAffected = cmd.ExecuteNonQuery();
}
}
return rowsAffected;
}
catch (Exception ee)
{
throw new SqlCeProviderException("Error running NonQuery: \nSQL Statement:\n" + commandText + "\n\nException:\n" + ee.ToString());
}
}
/// <summary>
///
/// </summary>
/// <param name="connectionString"></param>
/// <param name="commandType"></param>
/// <param name="commandText"></param>
/// <param name="commandParameters"></param>
/// <returns></returns>
public static SqlCeDataReader ExecuteReader(
string connectionString,
CommandType commandType,
string commandText,
params SqlCeParameter[] commandParameters
)
{
try
{
Debug.WriteLine("---------------------------------READER-------------------------------------");
Debug.WriteLine(commandText);
Debug.WriteLine("----------------------------------------------------------------------------");
SqlCeDataReader reader;
SqlCeConnection conn = SqlCeContextGuardian.Open(connectionString);
try
{
SqlCeCommand cmd = new SqlCeCommand(commandText, conn);
AttachParameters(cmd, commandParameters);
reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch
{
conn.Close();
throw;
}
return reader;
}
catch (Exception ee)
{
throw new SqlCeProviderException("Error running Reader: \nSQL Statement:\n" + commandText + "\n\nException:\n" + ee.ToString());
}
}
public static bool VerifyConnection(string connectionString)
{
bool isConnected = false;
using (SqlCeConnection conn = SqlCeContextGuardian.Open(connectionString))
{
isConnected = conn.State == ConnectionState.Open;
}
return isConnected;
}
private static void AttachParameters(SqlCeCommand command, SqlCeParameter[] commandParameters)
{
foreach (SqlCeParameter parameter in commandParameters)
{
if ((parameter.Direction == ParameterDirection.InputOutput) && (parameter.Value == null))
{
parameter.Value = DBNull.Value;
}
command.Parameters.Add(parameter);
}
}
}
}
+64
View File
@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlServerCe;
using System.Linq;
using System.Text;
namespace SQLCE4Umbraco
{
public static class SqlCeContextGuardian
{
private static SqlCeConnection _constantOpenConnection;
private static readonly object Lock = new object();
// Awesome SQL CE 4 speed improvement by Erik Ejskov Jensen - SQL CE 4 MVP
// It's not an issue with SQL CE 4 that we never close the connection
public static SqlCeConnection Open(string connectionString)
{
var connectionStringBuilder = new DbConnectionStringBuilder();
try
{
connectionStringBuilder.ConnectionString = connectionString;
}
catch (Exception ex)
{
throw new ArgumentException("Bad connection string.", "connectionString", ex);
}
connectionStringBuilder.Remove("datalayer");
// SQL CE 4 performs better when there's always a connection open in the background
EnsureOpenBackgroundConnection(connectionStringBuilder.ConnectionString);
SqlCeConnection conn = new SqlCeConnection(connectionStringBuilder.ConnectionString);
conn.Open();
return conn;
}
/// <summary>
/// Sometimes we need to ensure this is closed especially in unit tests
/// </summary>
internal static void CloseBackgroundConnection()
{
if (_constantOpenConnection != null)
_constantOpenConnection.Close();
}
private static void EnsureOpenBackgroundConnection(string connectionString)
{
lock (Lock)
{
if (_constantOpenConnection == null)
{
_constantOpenConnection = new SqlCeConnection(connectionString);
_constantOpenConnection.Open();
}
else if (_constantOpenConnection.State != ConnectionState.Open)
_constantOpenConnection.Open();
}
}
}
}
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SqlCE4Umbraco
{
public class SqlCeProviderException : Exception
{
public SqlCeProviderException() : base()
{
}
public SqlCeProviderException(string message) : base(message)
{
}
}
}
+35
View File
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
</packages>
+5 -12
View File
@@ -2,21 +2,14 @@
using System.Resources;
[assembly: AssemblyCompany("Umbraco")]
[assembly: AssemblyCopyright("Copyright © Umbraco 2017")]
[assembly: AssemblyCopyright("Copyright © Umbraco 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]
// versions
// read https://stackoverflow.com/questions/64602/what-are-differences-between-assemblyversion-assemblyfileversion-and-assemblyin
// note: do NOT change anything here manually, use the build scripts
// this is the ONLY ONE the CLR cares about for compatibility
// should change ONLY when "hard" breaking compatibility (manual change)
[assembly: AssemblyVersion("8.0.0")]
[assembly: AssemblyVersion("1.0.*")]
// these are FYI and changed automatically
[assembly: AssemblyFileVersion("8.0.0")]
[assembly: AssemblyInformationalVersion("8.0.0-alpha.37")]
[assembly: AssemblyFileVersion("7.4.1")]
[assembly: AssemblyInformationalVersion("7.4.1")]
+73
View File
@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
using umbraco.interfaces;
namespace Umbraco.Core
{
/// <summary>
/// A resolver to return all IAction objects
/// </summary>
public sealed class ActionsResolver : LazyManyObjectsResolverBase<ActionsResolver, IAction>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="serviceProvider"></param>
/// <param name="logger"></param>
/// <param name="packageActions"></param>
internal ActionsResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> packageActions)
: base(serviceProvider, logger, packageActions)
{
}
/// <summary>
/// Gets the <see cref="IPackageAction"/> implementations.
/// </summary>
public IEnumerable<IAction> Actions
{
get
{
return Values;
}
}
/// <summary>
/// Gets an Action if it exists.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
internal IAction GetAction<T>()
where T : IAction
{
return Actions.SingleOrDefault(x => x.GetType() == typeof (T));
}
protected override IEnumerable<IAction> CreateInstances()
{
var actions = new List<IAction>();
var foundIActions = InstanceTypes;
foreach (var type in foundIActions)
{
IAction typeInstance;
var instance = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
//if the singletone initializer is not found, try simply creating an instance of the IAction if it supports public constructors
if (instance == null)
typeInstance = ServiceProvider.GetService(type) as IAction;
else
typeInstance = instance.GetValue(null, null) as IAction;
if (typeInstance != null)
{
actions.Add(typeInstance);
}
}
return actions;
}
}
}
+20
View File
@@ -0,0 +1,20 @@
namespace Umbraco.Core
{
/// <summary>
/// Helper methods for Activation
/// </summary>
internal static class ActivatorHelper
{
/// <summary>
/// Creates an instance of a type using that type's default constructor.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T CreateInstance<T>() where T : class, new()
{
return new ActivatorServiceProvider().GetService(typeof (T)) as T;
}
}
}
@@ -0,0 +1,12 @@
using System;
namespace Umbraco.Core
{
internal class ActivatorServiceProvider : IServiceProvider
{
public object GetService(Type serviceType)
{
return Activator.CreateInstance(serviceType);
}
}
}
+435
View File
@@ -0,0 +1,435 @@
using System;
using System.Configuration;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Profiling;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
namespace Umbraco.Core
{
/// <summary>
/// the Umbraco Application context
/// </summary>
/// <remarks>
/// one per AppDomain, represents the global Umbraco application
/// </remarks>
public class ApplicationContext : IDisposable
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <param name="cache"></param>
/// <param name="logger"></param>
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger)
{
if (dbContext == null) throw new ArgumentNullException("dbContext");
if (serviceContext == null) throw new ArgumentNullException("serviceContext");
if (cache == null) throw new ArgumentNullException("cache");
if (logger == null) throw new ArgumentNullException("logger");
_databaseContext = dbContext;
_services = serviceContext;
ApplicationCache = cache;
ProfilingLogger = logger;
Init();
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <param name="cache"></param>
[Obsolete("Use the other constructor specifying a ProfilingLogger instead")]
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache)
: this(dbContext, serviceContext, cache,
new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler))
{
}
/// <summary>
/// Creates a basic app context
/// </summary>
/// <param name="cache"></param>
[Obsolete("Use the other constructor specifying a ProfilingLogger instead")]
public ApplicationContext(CacheHelper cache)
{
if (cache == null) throw new ArgumentNullException("cache");
ApplicationCache = cache;
ProfilingLogger = new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler);
Init();
}
/// <summary>
/// Creates a basic app context
/// </summary>
/// <param name="cache"></param>
/// <param name="logger"></param>
public ApplicationContext(CacheHelper cache, ProfilingLogger logger)
{
if (cache == null) throw new ArgumentNullException("cache");
if (logger == null) throw new ArgumentNullException("logger");
ApplicationCache = cache;
ProfilingLogger = logger;
Init();
}
/// <summary>
/// A method used to set and/or ensure that a global ApplicationContext singleton is created.
/// </summary>
/// <param name="appContext">
/// The instance to set on the global application singleton
/// </param>
/// <param name="replaceContext">If set to true and the singleton is already set, it will be replaced</param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(ApplicationContext appContext, bool replaceContext)
{
if (Current != null)
{
if (!replaceContext)
return Current;
}
Current = appContext;
return Current;
}
/// <summary>
/// A method used to create and ensure that a global ApplicationContext singleton is created.
/// </summary>
/// <param name="cache"></param>
/// <param name="replaceContext">
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// startup if for some reason the boot manager is not the umbraco boot manager.
/// </param>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// </remarks>
[Obsolete("Use the other method specifying an ProfilingLogger instead")]
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, bool replaceContext)
{
if (Current != null)
{
if (!replaceContext)
return Current;
}
var ctx = new ApplicationContext(dbContext, serviceContext, cache);
Current = ctx;
return Current;
}
/// <summary>
/// A method used to create and ensure that a global ApplicationContext singleton is created.
/// </summary>
/// <param name="cache"></param>
/// <param name="logger"></param>
/// <param name="replaceContext">
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// startup if for some reason the boot manager is not the umbraco boot manager.
/// </param>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger, bool replaceContext)
{
if (Current != null)
{
if (!replaceContext)
return Current;
}
var ctx = new ApplicationContext(dbContext, serviceContext, cache, logger);
Current = ctx;
return Current;
}
/// <summary>
/// Singleton accessor
/// </summary>
public static ApplicationContext Current { get; internal set; }
/// <summary>
/// Returns the application wide cache accessor
/// </summary>
/// <remarks>
/// Any caching that is done in the application (app wide) should be done through this property
/// </remarks>
public CacheHelper ApplicationCache { get; private set; }
/// <summary>
/// Exposes the global ProfilingLogger - this should generally not be accessed via the UmbracoContext and should normally just be exposed
/// on most base classes or injected with IoC
/// </summary>
public ProfilingLogger ProfilingLogger { get; private set; }
// IsReady is set to true by the boot manager once it has successfully booted
// note - the original umbraco module checks on content.Instance in umbraco.dll
// now, the boot task that setup the content store ensures that it is ready
bool _isReady = false;
readonly ManualResetEventSlim _isReadyEvent = new ManualResetEventSlim(false);
private DatabaseContext _databaseContext;
private ServiceContext _services;
public bool IsReady
{
get
{
return _isReady;
}
internal set
{
AssertIsNotReady();
_isReady = value;
_isReadyEvent.Set();
}
}
public bool WaitForReady(int timeout)
{
return _isReadyEvent.WaitHandle.WaitOne(timeout);
}
// notes
// GlobalSettings.ConfigurationStatus returns the value that's in the web.config, so it's the "configured version"
// GlobalSettings.CurrentVersion returns the hard-coded "current version"
// the system is configured if they match
// if they don't, install runs, updates web.config (presumably) and updates GlobalSettings.ConfiguredStatus
public bool IsConfigured
{
get { return _configured.Value; }
}
/// <summary>
/// If the db is configured, there is a database context and there is an umbraco schema, but we are not 'configured' , then it means we are upgrading
/// </summary>
public bool IsUpgrading
{
get
{
if (IsConfigured == false
&& DatabaseContext != null
&& DatabaseContext.IsDatabaseConfigured)
{
var schemaresult = DatabaseContext.ValidateDatabaseSchema();
if (schemaresult.ValidTables.Count > 0) return true;
}
return false;
}
}
/// <summary>
/// The application url.
/// </summary>
/// <remarks>
/// The application url is the url that should be used by services to talk to the application,
/// eg keep alive or scheduled publishing services. It must exist on a global context because
/// some of these services may not run within a web context.
/// The format of the application url is:
/// - has a scheme (http or https)
/// - has the SystemDirectories.Umbraco path
/// - does not end with a slash
/// It is initialized on the first request made to the server, by UmbracoModule.EnsureApplicationUrl:
/// - if umbracoSettings:settings/web.routing/@umbracoApplicationUrl is set, use the value (new setting)
/// - if umbracoSettings:settings/scheduledTasks/@baseUrl is set, use the value (backward compatibility)
/// - otherwise, use the url of the (first) request.
/// Not locking, does not matter if several threads write to this.
/// See also issues:
/// - http://issues.umbraco.org/issue/U4-2059
/// - http://issues.umbraco.org/issue/U4-6788
/// - http://issues.umbraco.org/issue/U4-5728
/// - http://issues.umbraco.org/issue/U4-5391
/// </remarks>
internal string UmbracoApplicationUrl
{
get
{
ApplicationUrlHelper.EnsureApplicationUrl(this);
return _umbracoApplicationUrl;
}
}
// ReSharper disable once InconsistentNaming
internal string _umbracoApplicationUrl;
private Lazy<bool> _configured;
internal MainDom MainDom { get; private set; }
private void Init()
{
MainDom = new MainDom(ProfilingLogger.Logger);
MainDom.Acquire();
//Create the lazy value to resolve whether or not the application is 'configured'
_configured = new Lazy<bool>(() =>
{
try
{
var configStatus = ConfigurationStatus;
var currentVersion = UmbracoVersion.GetSemanticVersion();
var ok =
//we are not configured if this is null
string.IsNullOrWhiteSpace(configStatus) == false
//they must match
&& configStatus == currentVersion;
if (ok)
{
//The versions are the same in config, but are they the same in the database. We can only check this
// if we have a db context available, if we don't then we are not installed anyways
if (DatabaseContext.IsDatabaseConfigured && DatabaseContext.CanConnect)
{
var found = Services.MigrationEntryService.FindEntry(GlobalSettings.UmbracoMigrationName, UmbracoVersion.GetSemanticVersion());
if (found == null)
{
//we haven't executed this migration in this environment, so even though the config versions match,
// this db has not been updated.
ProfilingLogger.Logger.Debug<ApplicationContext>(string.Format("The migration for version: '{0} has not been executed, there is no record in the database", currentVersion.ToSemanticString()));
ok = false;
}
}
}
else
{
ProfilingLogger.Logger.Debug<ApplicationContext>(string.Format("CurrentVersion different from configStatus: '{0}','{1}'", currentVersion.ToSemanticString(), configStatus));
}
return ok;
}
catch (Exception ex)
{
LogHelper.Error<ApplicationContext>("Error determining if application is configured, returning false", ex);
return false;
}
});
}
private string ConfigurationStatus
{
get
{
try
{
return ConfigurationManager.AppSettings["umbracoConfigurationStatus"];
}
catch
{
return String.Empty;
}
}
}
private void AssertIsNotReady()
{
if (this.IsReady)
throw new Exception("ApplicationContext has already been initialized.");
}
/// <summary>
/// Gets the current DatabaseContext
/// </summary>
/// <remarks>
/// Internal set is generally only used for unit tests
/// </remarks>
public DatabaseContext DatabaseContext
{
get
{
if (_databaseContext == null)
throw new InvalidOperationException("The DatabaseContext has not been set on the ApplicationContext");
return _databaseContext;
}
internal set { _databaseContext = value; }
}
/// <summary>
/// Gets the current ServiceContext
/// </summary>
/// <remarks>
/// Internal set is generally only used for unit tests
/// </remarks>
public ServiceContext Services
{
get
{
if (_services == null)
throw new InvalidOperationException("The ServiceContext has not been set on the ApplicationContext");
return _services;
}
internal set { _services = value; }
}
internal ServerRole GetCurrentServerRole()
{
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
return registrar == null ? ServerRole.Unknown : registrar.GetCurrentServerRole();
}
private volatile bool _disposed;
private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim();
/// <summary>
/// This will dispose and reset all resources used to run the application
/// </summary>
/// <remarks>
/// IMPORTANT: Never dispose this object if you require the Umbraco application to run, disposing this object
/// is generally used for unit testing and when your application is shutting down after you have booted Umbraco.
/// </remarks>
void IDisposable.Dispose()
{
// Only operate if we haven't already disposed
if (_disposed) return;
using (new WriteLock(_disposalLocker))
{
// Check again now we're inside the lock
if (_disposed) return;
//clear the cache
if (ApplicationCache != null)
{
ApplicationCache.RuntimeCache.ClearAllCache();
ApplicationCache.IsolatedRuntimeCache.ClearAllCaches();
}
//reset all resolvers
ResolverCollection.ResetAll();
//reset resolution itself (though this should be taken care of by resetting any of the resolvers above)
Resolution.Reset();
//reset the instance objects
this.ApplicationCache = null;
if (_databaseContext != null) //need to check the internal field here
{
if (DatabaseContext.IsDatabaseConfigured && DatabaseContext.Database != null)
{
DatabaseContext.Database.Dispose();
}
}
this.DatabaseContext = null;
this.Services = null;
this._isReady = false; //set the internal field
// Indicate that the instance has been disposed.
_disposed = true;
}
}
}
}
+119
View File
@@ -0,0 +1,119 @@
namespace Umbraco.Core
{
/// <summary>
/// A plugin type that allows developers to execute code during the Umbraco bootup process
/// </summary>
/// <remarks>
/// Allows you to override the methods that you would like to execute code for: ApplicationInitialized, ApplicationStarting, ApplicationStarted.
///
/// By default none of these methods will execute if the Umbraco application is not configured or if the Umbraco database is not configured, however
/// if you need these methods to execute even if either of these are not configured you can override the properties:
/// ExecuteWhenApplicationNotConfigured and ExecuteWhenDatabaseNotConfigured
/// </remarks>
public abstract class ApplicationEventHandler : IApplicationEventHandler
{
public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
if (ShouldExecute(applicationContext))
{
ApplicationInitialized(umbracoApplication, applicationContext);
}
}
public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
if (ShouldExecute(applicationContext))
{
ApplicationStarting(umbracoApplication, applicationContext);
}
}
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
if (ShouldExecute(applicationContext))
{
ApplicationStarted(umbracoApplication, applicationContext);
}
}
/// <summary>
/// Overridable method to execute when the ApplicationContext is created and other static objects that require initialization have been setup
/// </summary>
/// <param name="umbracoApplication"></param>
/// <param name="applicationContext"></param>
protected virtual void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
/// <summary>
/// Overridable method to execute when All resolvers have been initialized but resolution is not frozen so they can be modified in this method
/// </summary>
/// <param name="umbracoApplication"></param>
/// <param name="applicationContext"></param>
protected virtual void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
/// <summary>
/// Overridable method to execute when Bootup is completed, this allows you to perform any other bootup logic required for the application.
/// Resolution is frozen so now they can be used to resolve instances.
/// </summary>
/// <param name="umbracoApplication"></param>
/// <param name="applicationContext"></param>
protected virtual void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
/// <summary>
/// Determine if the methods should execute based on the configuration status of the application.
/// </summary>
/// <param name="applicationContext"></param>
/// <returns></returns>
private bool ShouldExecute(ApplicationContext applicationContext)
{
if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured)
{
return true;
}
if (!applicationContext.IsConfigured && ExecuteWhenApplicationNotConfigured)
{
return true;
}
if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured)
{
return true;
}
return false;
}
/// <summary>
/// A flag to determine if the overridable methods for this class will execute even if the
/// Umbraco application is not configured
/// </summary>
/// <remarks>
/// An Umbraco Application is not configured when it requires a new install or upgrade. When the latest version in the
/// assembly does not match the version in the config.
/// </remarks>
protected virtual bool ExecuteWhenApplicationNotConfigured
{
get { return false; }
}
/// <summary>
/// A flag to determine if the overridable methods for this class will execute even if the
/// Umbraco database is not configured
/// </summary>
/// <remarks>
/// The Umbraco database is not configured when we cannot connect to the database or when the database tables are not installed.
/// </remarks>
protected virtual bool ExecuteWhenDatabaseNotConfigured
{
get { return false; }
}
}
}
+32 -32
View File
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -6,20 +6,20 @@ using System.Reflection;
namespace Umbraco.Core
{
internal static class AssemblyExtensions
{
/// <summary>
/// Returns the file used to load the assembly
/// </summary>
/// <param name="assembly"></param>
/// <returns></returns>
public static FileInfo GetAssemblyFile(this Assembly assembly)
{
var codeBase = assembly.CodeBase;
var uri = new Uri(codeBase);
var path = uri.LocalPath;
return new FileInfo(path);
}
internal static class AssemblyExtensions
{
/// <summary>
/// Returns the file used to load the assembly
/// </summary>
/// <param name="assembly"></param>
/// <returns></returns>
public static FileInfo GetAssemblyFile(this Assembly assembly)
{
var codeBase = assembly.CodeBase;
var uri = new Uri(codeBase);
var path = uri.LocalPath;
return new FileInfo(path);
}
/// <summary>
/// Returns true if the assembly is the App_Code assembly
@@ -49,24 +49,24 @@ namespace Umbraco.Core
/// </summary>
/// <param name="assembly"></param>
/// <returns></returns>
public static bool IsGlobalAsaxAssembly(this Assembly assembly)
{
public static bool IsGlobalAsaxAssembly(this Assembly assembly)
{
//only way I can figure out how to test is by the name
return assembly.FullName.StartsWith("App_global.asax");
}
}
/// <summary>
/// Returns the file used to load the assembly
/// </summary>
/// <param name="assemblyName"></param>
/// <returns></returns>
public static FileInfo GetAssemblyFile(this AssemblyName assemblyName)
{
var codeBase = assemblyName.CodeBase;
var uri = new Uri(codeBase);
var path = uri.LocalPath;
return new FileInfo(path);
}
/// <summary>
/// Returns the file used to load the assembly
/// </summary>
/// <param name="assemblyName"></param>
/// <returns></returns>
public static FileInfo GetAssemblyFile(this AssemblyName assemblyName)
{
var codeBase = assemblyName.CodeBase;
var uri = new Uri(codeBase);
var path = uri.LocalPath;
return new FileInfo(path);
}
}
}
}
}
+6 -6
View File
@@ -69,11 +69,11 @@ namespace Umbraco.Core
public Task<IDisposable> LockAsync()
{
var wait = _semaphore != null
var wait = _semaphore != null
? _semaphore.WaitAsync()
: _semaphore2.WaitOneAsync();
return wait.IsCompleted
return wait.IsCompleted
? _releaserTask ?? Task.FromResult(CreateReleaser()) // anonymous vs named
: wait.ContinueWith((_, state) => (((AsyncLock) state).CreateReleaser()),
this, CancellationToken.None,
@@ -112,7 +112,7 @@ namespace Umbraco.Core
return _releaser ?? CreateReleaser(); // anonymous vs named
}
// note - before making those classes some structs, read
// note - before making those classes some structs, read
// about "impure methods" and mutating readonly structs...
private class NamedSemaphoreReleaser : CriticalFinalizerObject, IDisposable
@@ -140,9 +140,9 @@ namespace Umbraco.Core
_semaphore.Dispose();
}
// we WANT to release the semaphore because it's a system object, ie a critical
// we WANT to release the semaphore because it's a system object, ie a critical
// non-managed resource - and if it is not released then noone else can acquire
// the lock - so we inherit from CriticalFinalizerObject which means that the
// the lock - so we inherit from CriticalFinalizerObject which means that the
// finalizer "should" run in all situations - there is always a chance that it
// does not run and the semaphore remains "acquired" but then chances are the
// whole process (w3wp.exe...) is going down, at which point the semaphore will
@@ -200,4 +200,4 @@ namespace Umbraco.Core
}
}
}
}
}
+120 -80
View File
@@ -1,4 +1,4 @@
using System;
using System;
namespace Umbraco.Core
{
@@ -7,120 +7,160 @@ namespace Umbraco.Core
/// </summary>
public static class Attempt
{
// note:
// cannot rely on overloads only to differenciate between with/without status
// in some cases it will always be ambiguous, so be explicit w/ 'WithStatus' methods
/// <summary>
/// Creates a successful attempt with a result.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <typeparam name="T">The type of the attempted operation result.</typeparam>
/// <param name="result">The result of the attempt.</param>
/// <returns>The successful attempt.</returns>
public static Attempt<TResult> Succeed<TResult>(TResult result)
public static Attempt<T> Succeed<T>(T result)
{
return Attempt<TResult>.Succeed(result);
}
/// <summary>
/// Creates a successful attempt with a result and a status.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
/// <param name="status">The status of the attempt.</param>
/// <param name="result">The result of the attempt.</param>
/// <returns>The successful attempt.</returns>
public static Attempt<TResult, TStatus> SucceedWithStatus<TResult, TStatus>(TStatus status, TResult result)
{
return Attempt<TResult, TStatus>.Succeed(status, result);
}
/// <summary>
/// Creates a failed attempt.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult> Fail<TResult>()
{
return Attempt<TResult>.Fail();
return Attempt<T>.Succeed(result);
}
/// <summary>
/// Creates a failed attempt with a result.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <typeparam name="T">The type of the attempted operation result.</typeparam>
/// <param name="result">The result of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult> Fail<TResult>(TResult result)
public static Attempt<T> Fail<T>(T result)
{
return Attempt<TResult>.Fail(result);
}
/// <summary>
/// Creates a failed attempt with a result and a status.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
/// <param name="status">The status of the attempt.</param>
/// <param name="result">The result of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult, TStatus> FailWithStatus<TResult, TStatus>(TStatus status, TResult result)
{
return Attempt<TResult, TStatus>.Fail(status, result);
return Attempt<T>.Fail(result);
}
/// <summary>
/// Creates a failed attempt with a result and an exception.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <typeparam name="T">The type of the attempted operation result.</typeparam>
/// <param name="result">The result of the attempt.</param>
/// <param name="exception">The exception causing the failure of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult> Fail<TResult>(TResult result, Exception exception)
public static Attempt<T> Fail<T>(T result, Exception exception)
{
return Attempt<TResult>.Fail(result, exception);
}
/// <summary>
/// Creates a failed attempt with a result, an exception and a status.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
/// <param name="status">The status of the attempt.</param>
/// <param name="result">The result of the attempt.</param>
/// <param name="exception">The exception causing the failure of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult, TStatus> FailWithStatus<TResult, TStatus>(TStatus status, TResult result, Exception exception)
{
return Attempt<TResult, TStatus>.Fail(status, result, exception);
return Attempt<T>.Fail(result, exception);
}
/// <summary>
/// Creates a successful or a failed attempt, with a result.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <param name="condition">A value indicating whether the attempt is successful.</param>
/// <typeparam name="T">The type of the attempted operation result.</typeparam>
/// <param name="success">A value indicating whether the attempt is successful.</param>
/// <param name="result">The result of the attempt.</param>
/// <returns>The attempt.</returns>
public static Attempt<TResult> If<TResult>(bool condition, TResult result)
public static Attempt<T> If<T>(bool success, T result)
{
return Attempt<TResult>.If(condition, result);
return Attempt<T>.SucceedIf(success, result);
}
/// <summary>
/// Executes an attempt function, with callbacks.
/// </summary>
/// <typeparam name="T">The type of the attempted operation result.</typeparam>
/// <param name="attempt">The attempt returned by the attempt function.</param>
/// <param name="onSuccess">An action to execute in case the attempt succeeds.</param>
/// <param name="onFail">An action to execute in case the attempt fails.</param>
/// <returns>The outcome of the attempt.</returns>
/// <remarks>Runs <paramref name="onSuccess"/> or <paramref name="onFail"/> depending on the
/// whether the attempt function reports a success or a failure.</remarks>
public static Outcome Try<T>(Attempt<T> attempt, Action<T> onSuccess, Action<Exception> onFail = null)
{
if (attempt.Success)
{
onSuccess(attempt.Result);
return Outcome.Success;
}
if (onFail != null)
{
onFail(attempt.Exception);
}
return Outcome.Failure;
}
/// <summary>
/// Creates a successful or a failed attempt, with a result.
/// Represents the outcome of an attempt.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
/// <param name="condition">A value indicating whether the attempt is successful.</param>
/// <param name="succStatus">The status of the successful attempt.</param>
/// <param name="failStatus">The status of the failed attempt.</param>
/// <param name="result">The result of the attempt.</param>
/// <returns>The attempt.</returns>
public static Attempt<TResult, TStatus> IfWithStatus<TResult, TStatus>(bool condition, TStatus succStatus, TStatus failStatus, TResult result)
/// <remarks>Can be a success or a failure, and allows for attempts chaining.</remarks>
public struct Outcome
{
return Attempt<TResult, TStatus>.If(condition, succStatus, failStatus, result);
private readonly bool _success;
/// <summary>
/// Gets an outcome representing a success.
/// </summary>
public static readonly Outcome Success = new Outcome(true);
/// <summary>
/// Gets an outcome representing a failure.
/// </summary>
public static readonly Outcome Failure = new Outcome(false);
private Outcome(bool success)
{
_success = success;
}
/// <summary>
/// Executes another attempt function, if the previous one failed, with callbacks.
/// </summary>
/// <typeparam name="T">The type of the attempted operation result.</typeparam>
/// <param name="nextFunction">The attempt function to execute, returning an attempt.</param>
/// <param name="onSuccess">An action to execute in case the attempt succeeds.</param>
/// <param name="onFail">An action to execute in case the attempt fails.</param>
/// <returns>If it executes, returns the outcome of the attempt, else returns a success outcome.</returns>
/// <remarks>
/// <para>Executes only if the previous attempt failed, else does not execute and return a success outcome.</para>
/// <para>If it executes, then runs <paramref name="onSuccess"/> or <paramref name="onFail"/> depending on the
/// whether the attempt function reports a success or a failure.</para>
/// </remarks>
public Outcome OnFailure<T>(Func<Attempt<T>> nextFunction, Action<T> onSuccess, Action<Exception> onFail = null)
{
return _success
? Success
: ExecuteNextFunction(nextFunction, onSuccess, onFail);
}
/// <summary>
/// Executes another attempt function, if the previous one succeeded, with callbacks.
/// </summary>
/// <typeparam name="T">The type of the attempted operation result.</typeparam>
/// <param name="nextFunction">The attempt function to execute, returning an attempt.</param>
/// <param name="onSuccess">An action to execute in case the attempt succeeds.</param>
/// <param name="onFail">An action to execute in case the attempt fails.</param>
/// <returns>If it executes, returns the outcome of the attempt, else returns a failed outcome.</returns>
/// <remarks>
/// <para>Executes only if the previous attempt succeeded, else does not execute and return a success outcome.</para>
/// <para>If it executes, then runs <paramref name="onSuccess"/> or <paramref name="onFail"/> depending on the
/// whether the attempt function reports a success or a failure.</para>
/// </remarks>
public Outcome OnSuccess<T>(Func<Attempt<T>> nextFunction, Action<T> onSuccess, Action<Exception> onFail = null)
{
return _success
? ExecuteNextFunction(nextFunction, onSuccess, onFail)
: Failure;
}
private static Outcome ExecuteNextFunction<T>(Func<Attempt<T>> nextFunction, Action<T> onSuccess, Action<Exception> onFail = null)
{
var attempt = nextFunction();
if (attempt.Success)
{
onSuccess(attempt.Result);
return Success;
}
if (onFail != null)
{
onFail(attempt.Exception);
}
return Failure;
}
}
}
}
}
-133
View File
@@ -1,133 +0,0 @@
using System;
namespace Umbraco.Core
{
/// <summary>
/// Represents the result of an operation attempt.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
[Serializable]
public struct Attempt<TResult>
{
// private - use Succeed() or Fail() methods to create attempts
private Attempt(bool success, TResult result, Exception exception)
{
Success = success;
Result = result;
Exception = exception;
}
/// <summary>
/// Gets a value indicating whether this <see cref="Attempt{TResult}"/> was successful.
/// </summary>
public bool Success { get; }
/// <summary>
/// Gets the exception associated with an unsuccessful attempt.
/// </summary>
public Exception Exception { get; }
/// <summary>
/// Gets the attempt result.
/// </summary>
public TResult Result { get; }
/// <summary>
/// Gets the attempt result, if successful, else a default value.
/// </summary>
public TResult ResultOr(TResult value) => Success ? Result : value;
// optimize, use a singleton failed attempt
private static readonly Attempt<TResult> Failed = new Attempt<TResult>(false, default(TResult), null);
/// <summary>
/// Creates a successful attempt.
/// </summary>
/// <returns>The successful attempt.</returns>
public static Attempt<TResult> Succeed()
{
return new Attempt<TResult>(true, default(TResult), null);
}
/// <summary>
/// Creates a successful attempt with a result.
/// </summary>
/// <param name="result">The result of the attempt.</param>
/// <returns>The successful attempt.</returns>
public static Attempt<TResult> Succeed(TResult result)
{
return new Attempt<TResult>(true, result, null);
}
/// <summary>
/// Creates a failed attempt.
/// </summary>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult> Fail()
{
return Failed;
}
/// <summary>
/// Creates a failed attempt with an exception.
/// </summary>
/// <param name="exception">The exception causing the failure of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult> Fail(Exception exception)
{
return new Attempt<TResult>(false, default(TResult), exception);
}
/// <summary>
/// Creates a failed attempt with a result.
/// </summary>
/// <param name="result">The result of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult> Fail(TResult result)
{
return new Attempt<TResult>(false, result, null);
}
/// <summary>
/// Creates a failed attempt with a result and an exception.
/// </summary>
/// <param name="result">The result of the attempt.</param>
/// <param name="exception">The exception causing the failure of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult> Fail(TResult result, Exception exception)
{
return new Attempt<TResult>(false, result, exception);
}
/// <summary>
/// Creates a successful or a failed attempt.
/// </summary>
/// <param name="condition">A value indicating whether the attempt is successful.</param>
/// <returns>The attempt.</returns>
public static Attempt<TResult> If(bool condition)
{
return condition ? new Attempt<TResult>(true, default(TResult), null) : Failed;
}
/// <summary>
/// Creates a successful or a failed attempt, with a result.
/// </summary>
/// <param name="condition">A value indicating whether the attempt is successful.</param>
/// <param name="result">The result of the attempt.</param>
/// <returns>The attempt.</returns>
public static Attempt<TResult> If(bool condition, TResult result)
{
return new Attempt<TResult>(condition, result, null);
}
/// <summary>
/// Implicity operator to check if the attempt was successful without having to access the 'success' property
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
public static implicit operator bool(Attempt<TResult> a)
{
return a.Success;
}
}
}
-142
View File
@@ -1,142 +0,0 @@
using System;
namespace Umbraco.Core
{
/// <summary>
/// Represents the result of an operation attempt.
/// </summary>
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
[Serializable]
public struct Attempt<TResult, TStatus>
{
/// <summary>
/// Gets a value indicating whether this <see cref="Attempt{TResult,TStatus}"/> was successful.
/// </summary>
public bool Success { get; }
/// <summary>
/// Gets the exception associated with an unsuccessful attempt.
/// </summary>
public Exception Exception { get; }
/// <summary>
/// Gets the attempt result.
/// </summary>
public TResult Result { get; }
/// <summary>
/// Gets the attempt status.
/// </summary>
public TStatus Status { get; }
// private - use Succeed() or Fail() methods to create attempts
private Attempt(bool success, TResult result, TStatus status, Exception exception)
{
Success = success;
Result = result;
Status = status;
Exception = exception;
}
/// <summary>
/// Creates a successful attempt.
/// </summary>
/// <param name="status">The status of the attempt.</param>
/// <returns>The successful attempt.</returns>
public static Attempt<TResult, TStatus> Succeed(TStatus status)
{
return new Attempt<TResult, TStatus>(true, default(TResult), status, null);
}
/// <summary>
/// Creates a successful attempt with a result.
/// </summary>
/// <param name="status">The status of the attempt.</param>
/// <param name="result">The result of the attempt.</param>
/// <returns>The successful attempt.</returns>
public static Attempt<TResult, TStatus> Succeed(TStatus status, TResult result)
{
return new Attempt<TResult, TStatus>(true, result, status, null);
}
/// <summary>
/// Creates a failed attempt.
/// </summary>
/// <param name="status">The status of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult, TStatus> Fail(TStatus status)
{
return new Attempt<TResult, TStatus>(false, default(TResult), status, null);
}
/// <summary>
/// Creates a failed attempt with an exception.
/// </summary>
/// <param name="status">The status of the attempt.</param>
/// <param name="exception">The exception causing the failure of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult, TStatus> Fail(TStatus status, Exception exception)
{
return new Attempt<TResult, TStatus>(false, default(TResult), status, exception);
}
/// <summary>
/// Creates a failed attempt with a result.
/// </summary>
/// <param name="status">The status of the attempt.</param>
/// <param name="result">The result of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult, TStatus> Fail(TStatus status, TResult result)
{
return new Attempt<TResult, TStatus>(false, result, status, null);
}
/// <summary>
/// Creates a failed attempt with a result and an exception.
/// </summary>
/// <param name="status">The status of the attempt.</param>
/// <param name="result">The result of the attempt.</param>
/// <param name="exception">The exception causing the failure of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<TResult, TStatus> Fail(TStatus status, TResult result, Exception exception)
{
return new Attempt<TResult, TStatus>(false, result, status, exception);
}
/// <summary>
/// Creates a successful or a failed attempt.
/// </summary>
/// <param name="condition">A value indicating whether the attempt is successful.</param>
/// <param name="succStatus">The status of the successful attempt.</param>
/// <param name="failStatus">The status of the failed attempt.</param>
/// <returns>The attempt.</returns>
public static Attempt<TResult, TStatus> If(bool condition, TStatus succStatus, TStatus failStatus)
{
return new Attempt<TResult, TStatus>(condition, default(TResult), condition ? succStatus : failStatus, null);
}
/// <summary>
/// Creates a successful or a failed attempt, with a result.
/// </summary>
/// <param name="condition">A value indicating whether the attempt is successful.</param>
/// <param name="succStatus">The status of the successful attempt.</param>
/// <param name="failStatus">The status of the failed attempt.</param>
/// <param name="result">The result of the attempt.</param>
/// <returns>The attempt.</returns>
public static Attempt<TResult, TStatus> If(bool condition, TStatus succStatus, TStatus failStatus, TResult result)
{
return new Attempt<TResult, TStatus>(condition, result, condition ? succStatus : failStatus, null);
}
/// <summary>
/// Implicity operator to check if the attempt was successful without having to access the 'success' property
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
public static implicit operator bool(Attempt<TResult, TStatus> a)
{
return a.Success;
}
}
}
+174
View File
@@ -0,0 +1,174 @@
using System;
using Umbraco.Core.Dynamics;
namespace Umbraco.Core
{
/// <summary>
/// Represents the result of an operation attempt.
/// </summary>
/// <typeparam name="T">The type of the attempted operation result.</typeparam>
[Serializable]
public struct Attempt<T>
{
private readonly bool _success;
private readonly T _result;
private readonly Exception _exception;
/// <summary>
/// Gets a value indicating whether this <see cref="Attempt{T}"/> was successful.
/// </summary>
public bool Success
{
get { return _success; }
}
/// <summary>
/// Gets the exception associated with an unsuccessful attempt.
/// </summary>
public Exception Exception { get { return _exception; } }
/// <summary>
/// Gets the exception associated with an unsuccessful attempt.
/// </summary>
/// <remarks>Keep it for backward compatibility sake.</remarks>
[Obsolete(".Error is obsolete, you should use .Exception instead.", false)]
public Exception Error { get { return _exception; } }
/// <summary>
/// Gets the attempt result.
/// </summary>
public T Result
{
get { return _result; }
}
// optimize, use a singleton failed attempt
private static readonly Attempt<T> Failed = new Attempt<T>(false, default(T), null);
/// <summary>
/// Represents an unsuccessful attempt.
/// </summary>
/// <remarks>Keep it for backward compatibility sake.</remarks>
[Obsolete(".Failed is obsolete, you should use Attempt<T>.Fail() instead.", false)]
public static readonly Attempt<T> False = Failed;
// private - use Succeed() or Fail() methods to create attempts
private Attempt(bool success, T result, Exception exception)
{
_success = success;
_result = result;
_exception = exception;
}
/// <summary>
/// Initialize a new instance of the <see cref="Attempt{T}"/> struct with a result.
/// </summary>
/// <param name="success">A value indicating whether the attempt is successful.</param>
/// <param name="result">The result of the attempt.</param>
/// <remarks>Keep it for backward compatibility sake.</remarks>
[Obsolete("Attempt ctors are obsolete, you should use Attempt<T>.Succeed(), Attempt<T>.Fail() or Attempt<T>.If() instead.", false)]
public Attempt(bool success, T result)
: this(success, result, null)
{ }
/// <summary>
/// Initialize a new instance of the <see cref="Attempt{T}"/> struct representing a failed attempt, with an exception.
/// </summary>
/// <param name="exception">The exception causing the failure of the attempt.</param>
/// <remarks>Keep it for backward compatibility sake.</remarks>
[Obsolete("Attempt ctors are obsolete, you should use Attempt<T>.Succeed(), Attempt<T>.Fail() or Attempt<T>.If() instead.", false)]
public Attempt(Exception exception)
: this(false, default(T), exception)
{ }
/// <summary>
/// Creates a successful attempt.
/// </summary>
/// <returns>The successful attempt.</returns>
public static Attempt<T> Succeed()
{
return new Attempt<T>(true, default(T), null);
}
/// <summary>
/// Creates a successful attempt with a result.
/// </summary>
/// <param name="result">The result of the attempt.</param>
/// <returns>The successful attempt.</returns>
public static Attempt<T> Succeed(T result)
{
return new Attempt<T>(true, result, null);
}
/// <summary>
/// Creates a failed attempt.
/// </summary>
/// <returns>The failed attempt.</returns>
public static Attempt<T> Fail()
{
return Failed;
}
/// <summary>
/// Creates a failed attempt with an exception.
/// </summary>
/// <param name="exception">The exception causing the failure of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<T> Fail(Exception exception)
{
return new Attempt<T>(false, default(T), exception);
}
/// <summary>
/// Creates a failed attempt with a result.
/// </summary>
/// <param name="result">The result of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<T> Fail(T result)
{
return new Attempt<T>(false, result, null);
}
/// <summary>
/// Creates a failed attempt with a result and an exception.
/// </summary>
/// <param name="result">The result of the attempt.</param>
/// <param name="exception">The exception causing the failure of the attempt.</param>
/// <returns>The failed attempt.</returns>
public static Attempt<T> Fail(T result, Exception exception)
{
return new Attempt<T>(false, result, exception);
}
/// <summary>
/// Creates a successful or a failed attempt.
/// </summary>
/// <param name="condition">A value indicating whether the attempt is successful.</param>
/// <returns>The attempt.</returns>
public static Attempt<T> SucceedIf(bool condition)
{
return condition ? new Attempt<T>(true, default(T), null) : Failed;
}
/// <summary>
/// Creates a successful or a failed attempt, with a result.
/// </summary>
/// <param name="condition">A value indicating whether the attempt is successful.</param>
/// <param name="result">The result of the attempt.</param>
/// <returns>The attempt.</returns>
public static Attempt<T> SucceedIf(bool condition, T result)
{
return new Attempt<T>(condition, result, null);
}
/// <summary>
/// Implicity operator to check if the attempt was successful without having to access the 'success' property
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
public static implicit operator bool(Attempt<T> a)
{
return a.Success;
}
}
}
+17
View File
@@ -0,0 +1,17 @@
using System;
using System.ComponentModel;
namespace Umbraco.Core.Auditing
{
[Obsolete("Use Umbraco.Core.Services.IAuditService instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static class Audit
{
public static void Add(Umbraco.Core.Auditing.AuditTypes type, string comment, int userId, int objectId)
{
ApplicationContext.Current.Services.AuditService.Add(
Enum<Umbraco.Core.Models.AuditType>.Parse(type.ToString()),
comment, userId, objectId);
}
}
}
@@ -1,353 +0,0 @@
using System;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using Umbraco.Core.Components;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
namespace Umbraco.Core.Auditing
{
public sealed class AuditEventsComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
private IAuditService _auditService;
private IUserService _userService;
private IEntityService _entityService;
private IUser CurrentPerformingUser
{
get
{
var identity = Thread.CurrentPrincipal?.GetUmbracoIdentity();
return identity == null
? new User { Id = 0, Name = "SYSTEM", Email = "" }
: _userService.GetUserById(Convert.ToInt32(identity.Id));
}
}
private IUser GetPerformingUser(int userId)
{
var found = userId >= 0 ? _userService.GetUserById(userId) : null;
return found ?? new User {Id = 0, Name = "SYSTEM", Email = ""};
}
private string PerformingIp
{
get
{
var httpContext = HttpContext.Current == null ? (HttpContextBase) null : new HttpContextWrapper(HttpContext.Current);
var ip = httpContext.GetCurrentRequestIpAddress();
if (ip.ToLowerInvariant().StartsWith("unknown")) ip = "";
return ip;
}
}
public void Initialize(IAuditService auditService, IUserService userService, IEntityService entityService)
{
_auditService = auditService;
_userService = userService;
_entityService = entityService;
//BackOfficeUserManager.AccountLocked += ;
//BackOfficeUserManager.AccountUnlocked += ;
BackOfficeUserManager.ForgotPasswordRequested += OnForgotPasswordRequest;
BackOfficeUserManager.ForgotPasswordChangedSuccess += OnForgotPasswordChange;
BackOfficeUserManager.LoginFailed += OnLoginFailed;
//BackOfficeUserManager.LoginRequiresVerification += ;
BackOfficeUserManager.LoginSuccess += OnLoginSuccess;
BackOfficeUserManager.LogoutSuccess += OnLogoutSuccess;
BackOfficeUserManager.PasswordChanged += OnPasswordChanged;
BackOfficeUserManager.PasswordReset += OnPasswordReset;
//BackOfficeUserManager.ResetAccessFailedCount += ;
UserService.SavedUserGroup += OnSavedUserGroupWithUsers;
UserService.SavedUser += OnSavedUser;
UserService.DeletedUser += OnDeletedUser;
UserService.UserGroupPermissionsAssigned += UserGroupPermissionAssigned;
MemberService.Saved += OnSavedMember;
MemberService.Deleted += OnDeletedMember;
MemberService.AssignedRoles += OnAssignedRoles;
MemberService.RemovedRoles += OnRemovedRoles;
MemberService.Exported += OnMemberExported;
}
private string FormatEmail(IMember member)
{
return member == null ? string.Empty : member.Email.IsNullOrWhiteSpace() ? "" : $"<{member.Email}>";
}
private string FormatEmail(IUser user)
{
return user == null ? string.Empty : user.Email.IsNullOrWhiteSpace() ? "" : $"<{user.Email}>";
}
private void OnRemovedRoles(IMemberService sender, RolesEventArgs args)
{
var performingUser = CurrentPerformingUser;
var roles = string.Join(", ", args.Roles);
var members = sender.GetAllMembers(args.MemberIds).ToDictionary(x => x.Id, x => x);
foreach (var id in args.MemberIds)
{
members.TryGetValue(id, out var member);
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {id} \"{member?.Name ?? "(unknown)"}\" {FormatEmail(member)}",
"umbraco/member/roles/removed", $"roles modified, removed {roles}");
}
}
private void OnAssignedRoles(IMemberService sender, RolesEventArgs args)
{
var performingUser = CurrentPerformingUser;
var roles = string.Join(", ", args.Roles);
var members = sender.GetAllMembers(args.MemberIds).ToDictionary(x => x.Id, x => x);
foreach (var id in args.MemberIds)
{
members.TryGetValue(id, out var member);
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {id} \"{member?.Name ?? "(unknown)"}\" {FormatEmail(member)}",
"umbraco/member/roles/assigned", $"roles modified, assigned {roles}");
}
}
private void OnMemberExported(IMemberService sender, ExportedMemberEventArgs exportedMemberEventArgs)
{
var performingUser = CurrentPerformingUser;
var member = exportedMemberEventArgs.Member;
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {member.Id} \"{member.Name}\" {FormatEmail(member)}",
"umbraco/member/exported", "exported member data");
}
private void OnSavedUserGroupWithUsers(IUserService sender, SaveEventArgs<UserGroupWithUsers> saveEventArgs)
{
var performingUser = CurrentPerformingUser;
foreach (var groupWithUser in saveEventArgs.SavedEntities)
{
var group = groupWithUser.UserGroup;
var dp = string.Join(", ", ((UserGroup)group).GetWereDirtyProperties());
var sections = ((UserGroup)group).WasPropertyDirty("AllowedSections")
? string.Join(", ", group.AllowedSections)
: null;
var perms = ((UserGroup)group).WasPropertyDirty("Permissions")
? string.Join(", ", group.Permissions)
: null;
var sb = new StringBuilder();
sb.Append($"updating {(string.IsNullOrWhiteSpace(dp) ? "(nothing)" : dp)};");
if (sections != null)
sb.Append($", assigned sections: {sections}");
if (perms != null)
{
if (sections != null)
sb.Append(", ");
sb.Append($"default perms: {perms}");
}
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"User Group {group.Id} \"{group.Name}\" ({group.Alias})",
"umbraco/user-group/save", $"{sb}");
// now audit the users that have changed
foreach (var user in groupWithUser.RemovedUsers)
{
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
user.Id, $"User \"{user.Name}\" {FormatEmail(user)}",
"umbraco/user-group/save", $"Removed user \"{user.Name}\" {FormatEmail(user)} from group {group.Id} \"{group.Name}\" ({group.Alias})");
}
foreach (var user in groupWithUser.AddedUsers)
{
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
user.Id, $"User \"{user.Name}\" {FormatEmail(user)}",
"umbraco/user-group/save", $"Added user \"{user.Name}\" {FormatEmail(user)} to group {group.Id} \"{group.Name}\" ({group.Alias})");
}
}
}
private void UserGroupPermissionAssigned(IUserService sender, SaveEventArgs<EntityPermission> saveEventArgs)
{
var performingUser = CurrentPerformingUser;
var perms = saveEventArgs.SavedEntities;
foreach (var perm in perms)
{
var group = sender.GetUserGroupById(perm.UserGroupId);
var assigned = string.Join(", ", perm.AssignedPermissions);
var entity = _entityService.Get(perm.EntityId);
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"User Group {group.Id} \"{group.Name}\" ({group.Alias})",
"umbraco/user-group/permissions-change", $"assigning {(string.IsNullOrWhiteSpace(assigned) ? "(nothing)" : assigned)} on id:{perm.EntityId} \"{entity.Name}\"");
}
}
private void OnSavedMember(IMemberService sender, SaveEventArgs<IMember> saveEventArgs)
{
var performingUser = CurrentPerformingUser;
var members = saveEventArgs.SavedEntities;
foreach (var member in members)
{
var dp = string.Join(", ", ((Member) member).GetWereDirtyProperties());
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {member.Id} \"{member.Name}\" {FormatEmail(member)}",
"umbraco/member/save", $"updating {(string.IsNullOrWhiteSpace(dp) ? "(nothing)" : dp)}");
}
}
private void OnDeletedMember(IMemberService sender, DeleteEventArgs<IMember> deleteEventArgs)
{
var performingUser = CurrentPerformingUser;
var members = deleteEventArgs.DeletedEntities;
foreach (var member in members)
{
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {member.Id} \"{member.Name}\" {FormatEmail(member)}",
"umbraco/member/delete", $"delete member id:{member.Id} \"{member.Name}\" {FormatEmail(member)}");
}
}
private void OnSavedUser(IUserService sender, SaveEventArgs<IUser> saveEventArgs)
{
var performingUser = CurrentPerformingUser;
var affectedUsers = saveEventArgs.SavedEntities;
foreach (var affectedUser in affectedUsers)
{
var groups = affectedUser.WasPropertyDirty("Groups")
? string.Join(", ", affectedUser.Groups.Select(x => x.Alias))
: null;
var dp = string.Join(", ", ((User)affectedUser).GetWereDirtyProperties());
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
affectedUser.Id, $"User \"{affectedUser.Name}\" {FormatEmail(affectedUser)}",
"umbraco/user/save", $"updating {(string.IsNullOrWhiteSpace(dp) ? "(nothing)" : dp)}{(groups == null ? "" : "; groups assigned: " + groups)}");
}
}
private void OnDeletedUser(IUserService sender, DeleteEventArgs<IUser> deleteEventArgs)
{
var performingUser = CurrentPerformingUser;
var affectedUsers = deleteEventArgs.DeletedEntities;
foreach (var affectedUser in affectedUsers)
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
affectedUser.Id, $"User \"{affectedUser.Name}\" {FormatEmail(affectedUser)}",
"umbraco/user/delete", "delete user");
}
private void OnLoginSuccess(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs)
{
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/login", "login success");
}
}
private void OnLogoutSuccess(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs)
{
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/logout", "logout success");
}
}
private void OnPasswordReset(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/reset", "password reset");
}
}
private void OnPasswordChanged(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/change", "password change");
}
}
private void OnLoginFailed(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, 0, identityArgs.IpAddress, "umbraco/user/sign-in/failed", "login failed", affectedDetails: "");
}
}
private void OnForgotPasswordChange(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/change", "password forgot/change");
}
}
private void OnForgotPasswordRequest(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/request", "password forgot/request");
}
}
private void WriteAudit(int performingId, int affectedId, string ipAddress, string eventType, string eventDetails, string affectedDetails = null)
{
var performingUser = _userService.GetUserById(performingId);
var performingDetails = performingUser == null
? $"User UNKNOWN:{performingId}"
: $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}";
WriteAudit(performingId, performingDetails, affectedId, ipAddress, eventType, eventDetails, affectedDetails);
}
private void WriteAudit(IUser performingUser, int affectedId, string ipAddress, string eventType, string eventDetails)
{
var performingDetails = performingUser == null
? $"User UNKNOWN"
: $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}";
WriteAudit(performingUser?.Id ?? 0, performingDetails, affectedId, ipAddress, eventType, eventDetails);
}
private void WriteAudit(int performingId, string performingDetails, int affectedId, string ipAddress, string eventType, string eventDetails, string affectedDetails = null)
{
if (affectedDetails == null)
{
var affectedUser = _userService.GetUserById(affectedId);
affectedDetails = affectedUser == null
? $"User UNKNOWN:{affectedId}"
: $"User \"{affectedUser.Name}\" {FormatEmail(affectedUser)}";
}
_auditService.Write(performingId, performingDetails,
ipAddress,
DateTime.UtcNow,
affectedId, affectedDetails,
eventType, eventDetails);
}
}
}
+87
View File
@@ -0,0 +1,87 @@
using System;
using System.ComponentModel;
namespace Umbraco.Core.Auditing
{
[Obsolete("Use Umbraco.Core.Models.AuditType instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public enum AuditTypes
{
/// <summary>
/// Used when new nodes are added
/// </summary>
New,
/// <summary>
/// Used when nodes are saved
/// </summary>
Save,
/// <summary>
/// Used when nodes are opened
/// </summary>
Open,
/// <summary>
/// Used when nodes are deleted
/// </summary>
Delete,
/// <summary>
/// Used when nodes are published
/// </summary>
Publish,
/// <summary>
/// Used when nodes are send to publishing
/// </summary>
SendToPublish,
/// <summary>
/// Used when nodes are unpublished
/// </summary>
UnPublish,
/// <summary>
/// Used when nodes are moved
/// </summary>
Move,
/// <summary>
/// Used when nodes are copied
/// </summary>
Copy,
/// <summary>
/// Used when nodes are assígned a domain
/// </summary>
AssignDomain,
/// <summary>
/// Used when public access are changed for a node
/// </summary>
PublicAccess,
/// <summary>
/// Used when nodes are sorted
/// </summary>
Sort,
/// <summary>
/// Used when a notification are send to a user
/// </summary>
Notify,
/// <summary>
/// General system notification
/// </summary>
System,
/// <summary>
/// Used when a node's content is rolled back to a previous version
/// </summary>
RollBack,
/// <summary>
/// Used when a package is installed
/// </summary>
PackagerInstall,
/// <summary>
/// Used when a package is uninstalled
/// </summary>
PackagerUninstall,
/// <summary>
/// Used when a node is send to translation
/// </summary>
SendToTranslate,
/// <summary>
/// Use this log action for custom log messages that should be shown in the audit trail
/// </summary>
Custom
}
}
@@ -1,146 +0,0 @@
using System;
using System.ComponentModel;
using System.Threading;
using System.Web;
using Umbraco.Core.Security;
namespace Umbraco.Core.Auditing
{
/// <summary>
/// This class is used by events raised from hthe BackofficeUserManager
/// </summary>
public class IdentityAuditEventArgs : EventArgs
{
/// <summary>
/// The action that got triggered from the audit event
/// </summary>
public AuditEvent Action { get; private set; }
/// <summary>
/// Current date/time in UTC format
/// </summary>
public DateTime DateTimeUtc { get; private set; }
/// <summary>
/// The source IP address of the user performing the action
/// </summary>
public string IpAddress { get; private set; }
/// <summary>
/// The user affected by the event raised
/// </summary>
public int AffectedUser { get; private set; }
/// <summary>
/// If a user is perfoming an action on a different user, then this will be set. Otherwise it will be -1
/// </summary>
public int PerformingUser { get; private set; }
/// <summary>
/// An optional comment about the action being logged
/// </summary>
public string Comment { get; private set; }
/// <summary>
/// This property is always empty except in the LoginFailed event for an unknown user trying to login
/// </summary>
public string Username { get; private set; }
[Obsolete("Use the method that has the affectedUser parameter instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, int performingUser = -1)
{
DateTimeUtc = DateTime.UtcNow;
Action = action;
IpAddress = ipAddress;
PerformingUser = performingUser == -1
? GetCurrentRequestBackofficeUserId()
: performingUser;
}
/// <summary>
/// Default constructor
/// </summary>
/// <param name="action"></param>
/// <param name="ipAddress"></param>
/// <param name="comment"></param>
/// <param name="performingUser"></param>
/// <param name="affectedUser"></param>
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string comment = null, int performingUser = -1, int affectedUser = -1)
{
DateTimeUtc = DateTime.UtcNow;
Action = action;
IpAddress = ipAddress;
Comment = comment;
AffectedUser = affectedUser;
PerformingUser = performingUser == -1
? GetCurrentRequestBackofficeUserId()
: performingUser;
}
/// <summary>
/// Creates an instance without a performing or affected user (the id will be set to -1)
/// </summary>
/// <param name="action"></param>
/// <param name="ipAddress"></param>
/// <param name="username"></param>
/// <param name="comment"></param>
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string username, string comment)
{
DateTimeUtc = DateTime.UtcNow;
Action = action;
IpAddress = ipAddress;
Username = username;
Comment = comment;
PerformingUser = -1;
}
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string username, string comment, int performingUser)
{
DateTimeUtc = DateTime.UtcNow;
Action = action;
IpAddress = ipAddress;
Username = username;
Comment = comment;
PerformingUser = performingUser == -1
? GetCurrentRequestBackofficeUserId()
: performingUser;
}
/// <summary>
/// Returns the current logged in backoffice user's Id logging if there is one
/// </summary>
/// <returns></returns>
protected int GetCurrentRequestBackofficeUserId()
{
var userId = -1;
var backOfficeIdentity = Thread.CurrentPrincipal.GetUmbracoIdentity();
if (backOfficeIdentity != null)
int.TryParse(backOfficeIdentity.Id.ToString(), out userId);
return userId;
}
}
public enum AuditEvent
{
AccountLocked,
AccountUnlocked,
ForgotPasswordRequested,
ForgotPasswordChangedSuccess,
LoginFailed,
LoginRequiresVerification,
LoginSucces,
LogoutSuccess,
PasswordChanged,
PasswordReset,
ResetAccessFailedCount
}
}
-49
View File
@@ -1,49 +0,0 @@
using System;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web;
using Umbraco.Core;
[assembly: PreApplicationStartMethod(typeof(BindingRedirects), "Initialize")]
namespace Umbraco.Core
{
/// <summary>
/// Manages any assembly binding redirects that cannot be done via config (i.e. unsigned --> signed assemblies)
/// </summary>
public sealed class BindingRedirects
{
public static void Initialize()
{
// this only gets called when an assembly can't be resolved
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=\\w+$", RegexOptions.Compiled);
private const string Log4NetReplacement = "log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
/// <summary>
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
//log4net:
if (Log4NetAssemblyPattern.IsMatch(args.Name) && args.Name != Log4NetReplacement)
{
return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
}
//AutoMapper:
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
if (args.Name.StartsWith("AutoMapper") && args.Name.EndsWith("PublicKeyToken=null"))
return Assembly.Load(args.Name.Replace(", PublicKeyToken=null", ", PublicKeyToken=be96cd2c38ef1005"));
return null;
}
}
}
-39
View File
@@ -1,39 +0,0 @@
namespace Umbraco.Core
{
public static class ByteArrayExtensions
{
private static readonly char[] BytesToHexStringLookup = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public static string ToHexString(this byte[] bytes)
{
int i = 0, p = 0, bytesLength = bytes.Length;
var chars = new char[bytesLength * 2];
while (i < bytesLength)
{
var b = bytes[i++];
chars[p++] = BytesToHexStringLookup[b / 0x10];
chars[p++] = BytesToHexStringLookup[b % 0x10];
}
return new string(chars, 0, chars.Length);
}
public static string ToHexString(this byte[] bytes, char separator, int blockSize, int blockCount)
{
int p = 0, bytesLength = bytes.Length, count = 0, size = 0;
var chars = new char[bytesLength * 2 + blockCount];
for (var i = 0; i < bytesLength; i++)
{
var b = bytes[i++];
chars[p++] = BytesToHexStringLookup[b / 0x10];
chars[p++] = BytesToHexStringLookup[b % 0x10];
if (count == blockCount) continue;
if (++size < blockSize) continue;
chars[p++] = '/';
size = 0;
count++;
}
return new string(chars, 0, chars.Length);
}
}
}
-422
View File
@@ -1,422 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web;
using System.Web.Caching;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Class that is exposed by the ApplicationContext for application wide caching purposes
/// </summary>
public class CacheHelper
{
public static CacheHelper NoCache { get; } = new CacheHelper(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance));
/// <summary>
/// Creates a cache helper with disabled caches
/// </summary>
/// <returns></returns>
/// <remarks>
/// Good for unit testing
/// </remarks>
public static CacheHelper CreateDisabledCacheHelper()
{
// do *not* return NoCache
// NoCache is a special instance that is detected by RepositoryBase and disables all cache policies
// CreateDisabledCacheHelper is used in tests to use no cache, *but* keep all cache policies
return new CacheHelper(NullCacheProvider.Instance, NullCacheProvider.Instance, NullCacheProvider.Instance, new IsolatedRuntimeCache(_ => NullCacheProvider.Instance));
}
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
public CacheHelper()
: this(
new HttpRuntimeCacheProvider(HttpRuntime.Cache),
new StaticCacheProvider(),
new HttpRequestCacheProvider(),
new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
{
}
/// <summary>
/// Initializes a new instance for use in the web
/// </summary>
/// <param name="cache"></param>
public CacheHelper(System.Web.Caching.Cache cache)
: this(
new HttpRuntimeCacheProvider(cache),
new StaticCacheProvider(),
new HttpRequestCacheProvider(),
new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
{
}
[Obsolete("Use the constructor the specifies all dependencies")]
[EditorBrowsable(EditorBrowsableState.Never)]
public CacheHelper(
IRuntimeCacheProvider httpCacheProvider,
ICacheProvider staticCacheProvider,
ICacheProvider requestCacheProvider)
: this(httpCacheProvider, staticCacheProvider, requestCacheProvider, new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
{
}
/// <summary>
/// Initializes a new instance based on the provided providers
/// </summary>
/// <param name="httpCacheProvider"></param>
/// <param name="staticCacheProvider"></param>
/// <param name="requestCacheProvider"></param>
/// <param name="isolatedCacheManager"></param>
public CacheHelper(
IRuntimeCacheProvider httpCacheProvider,
ICacheProvider staticCacheProvider,
ICacheProvider requestCacheProvider,
IsolatedRuntimeCache isolatedCacheManager)
{
if (httpCacheProvider == null) throw new ArgumentNullException("httpCacheProvider");
if (staticCacheProvider == null) throw new ArgumentNullException("staticCacheProvider");
if (requestCacheProvider == null) throw new ArgumentNullException("requestCacheProvider");
if (isolatedCacheManager == null) throw new ArgumentNullException("isolatedCacheManager");
RuntimeCache = httpCacheProvider;
StaticCache = staticCacheProvider;
RequestCache = requestCacheProvider;
IsolatedRuntimeCache = isolatedCacheManager;
}
/// <summary>
/// Returns the current Request cache
/// </summary>
public ICacheProvider RequestCache { get; internal set; }
/// <summary>
/// Returns the current Runtime cache
/// </summary>
public ICacheProvider StaticCache { get; internal set; }
/// <summary>
/// Returns the current Runtime cache
/// </summary>
public IRuntimeCacheProvider RuntimeCache { get; internal set; }
/// <summary>
/// Returns the current Isolated Runtime cache manager
/// </summary>
public IsolatedRuntimeCache IsolatedRuntimeCache { get; internal set; }
#region Legacy Runtime/Http Cache accessors
/// <summary>
/// Clears the item in umbraco's runtime cache
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearAllCache()
{
RuntimeCache.ClearAllCache();
IsolatedRuntimeCache.ClearAllCaches();
}
/// <summary>
/// Clears the item in umbraco's runtime cache with the given key
/// </summary>
/// <param name="key">Key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheItem(string key)
{
RuntimeCache.ClearCacheItem(key);
}
/// <summary>
/// Clears all objects in the System.Web.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>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheObjectTypes(string typeName)
{
RuntimeCache.ClearCacheObjectTypes(typeName);
}
/// <summary>
/// Clears all objects in the System.Web.Cache with the System.Type specified
/// </summary>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheObjectTypes<T>()
{
RuntimeCache.ClearCacheObjectTypes<T>();
}
/// <summary>
/// Clears all cache items that starts with the key passed.
/// </summary>
/// <param name="keyStartsWith">The start of the key</param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeySearch(string keyStartsWith)
{
RuntimeCache.ClearCacheByKeySearch(keyStartsWith);
}
/// <summary>
/// Clears all cache items that have a key that matches the regular expression
/// </summary>
/// <param name="regexString"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeyExpression(string regexString)
{
RuntimeCache.ClearCacheByKeyExpression(regexString);
}
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
{
return RuntimeCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
/// <summary>
/// Returns a 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>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with all of the default parameters
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey,
TimeSpan timeout, Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, removedCallback: refreshAction);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, false, priority, refreshAction);
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<TT> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
/// <summary>
/// Gets (and adds if necessary) an item from the cache
/// </summary>
/// <typeparam name="TT"></typeparam>
/// <param name="cacheKey"></param>
/// <param name="priority"></param>
/// <param name="cacheDependency"></param>
/// <param name="getCacheItem"></param>
/// <returns></returns>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public TT GetCacheItem<TT>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
Func<TT> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), null, false, priority, null, cacheDependency);
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
/// <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="getCacheItem"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
Func<T> getCacheItem)
{
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, priority: priority);
}
/// <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="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
TimeSpan timeout,
Func<T> getCacheItem)
{
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, priority: priority);
}
/// <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>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheDependency cacheDependency,
TimeSpan timeout,
Func<T> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, null, cacheDependency);
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
/// <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="refreshAction"></param>
/// <param name="cacheDependency"></param>
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
/// <param name="getCacheItem"></param>
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
public void InsertCacheItem<T>(string cacheKey,
CacheItemPriority priority,
CacheItemRemovedCallback refreshAction,
CacheDependency cacheDependency,
TimeSpan? timeout,
Func<T> getCacheItem)
{
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
}
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
}
#endregion
private HttpRuntimeCacheProvider GetHttpRuntimeCacheProvider(IRuntimeCacheProvider runtimeCache)
{
HttpRuntimeCacheProvider cache;
var wrapper = RuntimeCache as IRuntimeCacheProviderWrapper;
if (wrapper != null)
{
cache = wrapper.InnerProvider as HttpRuntimeCacheProvider;
}
else
{
cache = RuntimeCache as HttpRuntimeCacheProvider;
}
return cache;
}
}
}
+49 -6
View File
@@ -1,4 +1,4 @@
using System;
using System;
using System.ComponentModel;
using Umbraco.Core.CodeAnnotations;
@@ -22,11 +22,16 @@ namespace Umbraco.Core.Cache
[UmbracoWillObsolete("This cache key is only used for the legacy 'library' caching, remove in v8")]
public const string MediaCacheKey = "UL_GetMedia";
public const string MacroXsltCacheKey = "macroXslt_";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string MacroCacheKey = "UmbracoMacroCache";
public const string MacroContentCacheKey = "macroContent_"; // for macro contents
public const string MacroHtmlCacheKey = "macroHtml_";
public const string MacroControlCacheKey = "macroControl_";
public const string MacroHtmlDateAddedCacheKey = "macroHtml_DateAdded_";
public const string MacroControlDateAddedCacheKey = "macroControl_DateAdded_";
[UmbracoWillObsolete("This cache key is only used for legacy 'library' member caching, remove in v8")]
public const string MemberLibraryCacheKey = "UL_GetMember";
@@ -37,15 +42,53 @@ namespace Umbraco.Core.Cache
[UmbracoWillObsolete("This cache key is only used for legacy template business logic caching, remove in v8")]
public const string TemplateFrontEndCacheKey = "template";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string TemplateBusinessLogicCacheKey = "UmbracoTemplateCache";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string UserContextCacheKey = "UmbracoUserContext";
public const string UserContextTimeoutCacheKey = "UmbracoUserContextTimeout";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string UserCacheKey = "UmbracoUser";
public const string UserPermissionsCacheKey = "UmbracoUserPermissions";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string ContentTypeCacheKey = "UmbracoContentType";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string ContentTypePropertiesCacheKey = "ContentType_PropertyTypes_Content:";
public const string IdToKeyCacheKey = "UI2K__";
public const string KeyToIdCacheKey = "UK2I__";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string PropertyTypeCacheKey = "UmbracoPropertyTypeCache";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string LanguageCacheKey = "UmbracoLanguageCache";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string DomainCacheKey = "UmbracoDomainList";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string StylesheetCacheKey = "UmbracoStylesheet";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string StylesheetPropertyCacheKey = "UmbracoStylesheetProperty";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
public const string IdToKeyCacheKey = "UI2K";
public const string KeyToIdCacheKey = "UK2I";
}
}
}
@@ -67,4 +67,4 @@ namespace Umbraco.Core.Cache
return result.TryConvertTo<T>().Result;
}
}
}
}
+55 -97
View File
@@ -1,120 +1,78 @@
using System;
using Umbraco.Core.Events;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Sync;
using umbraco.interfaces;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
/// <summary>
/// A base class for cache refreshers that handles events.
/// A base class for cache refreshers to inherit from that ensures the correct events are raised
/// when cache refreshing occurs.
/// </summary>
/// <typeparam name="TInstanceType">The actual cache refresher type.</typeparam>
/// <remarks>The actual cache refresher type is used for strongly typed events.</remarks>
/// <typeparam name="TInstanceType">The real cache refresher type, this is used for raising strongly typed events</typeparam>
public abstract class CacheRefresherBase<TInstanceType> : ICacheRefresher
where TInstanceType : class, ICacheRefresher
where TInstanceType : ICacheRefresher
{
/// <summary>
/// Initializes a new instance of the <see cref="CacheRefresherBase{TInstanceType}"/>.
/// </summary>
/// <param name="cacheHelper">A cache helper.</param>
protected CacheRefresherBase(CacheHelper cacheHelper)
{
CacheHelper = cacheHelper;
}
/// <summary>
/// Triggers when the cache is updated on the server.
/// An event that is raised when cache is updated on an individual server
/// </summary>
/// <remarks>
/// Triggers on each server configured for an Umbraco project whenever a cache refresher is updated.
/// This event will fire on each server configured for an Umbraco project whenever a cache refresher
/// is updated.
/// </remarks>
public static event TypedEventHandler<TInstanceType, CacheRefresherEventArgs> CacheUpdated;
#region Define
/// <summary>
/// Gets the typed 'this' for events.
/// Raises the event
/// </summary>
protected abstract TInstanceType This { get; }
/// <summary>
/// Gets the unique identifier of the refresher.
/// </summary>
public abstract Guid RefresherUniqueId { get; }
/// <summary>
/// Gets the name of the refresher.
/// </summary>
public abstract string Name { get; }
#endregion
#region Refresher
/// <summary>
/// Refreshes all entities.
/// </summary>
public virtual void RefreshAll()
{
OnCacheUpdated(This, new CacheRefresherEventArgs(null, MessageType.RefreshAll));
}
/// <summary>
/// Refreshes an entity.
/// </summary>
/// <param name="id">The entity's identifier.</param>
public virtual void Refresh(int id)
{
OnCacheUpdated(This, new CacheRefresherEventArgs(id, MessageType.RefreshById));
}
/// <summary>
/// Refreshes an entity.
/// </summary>
/// <param name="id">The entity's identifier.</param>
public virtual void Refresh(Guid id)
{
OnCacheUpdated(This, new CacheRefresherEventArgs(id, MessageType.RefreshById));
}
/// <summary>
/// Removes an entity.
/// </summary>
/// <param name="id">The entity's identifier.</param>
public virtual void Remove(int id)
{
OnCacheUpdated(This, new CacheRefresherEventArgs(id, MessageType.RemoveById));
}
#endregion
#region Protected
/// <summary>
/// Gets the cache helper.
/// </summary>
protected CacheHelper CacheHelper { get; }
/// <summary>
/// Clears the cache for all repository entities of a specified type.
/// </summary>
/// <typeparam name="TEntity">The type of the entities.</typeparam>
protected void ClearAllIsolatedCacheByEntityType<TEntity>()
where TEntity : class, IEntity
{
CacheHelper.IsolatedRuntimeCache.ClearCache<TEntity>();
}
/// <summary>
/// Raises the CacheUpdated event.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="args">The event arguments.</param>
/// <param name="sender"></param>
/// <param name="args"></param>
protected static void OnCacheUpdated(TInstanceType sender, CacheRefresherEventArgs args)
{
CacheUpdated?.Invoke(sender, args);
if (CacheUpdated != null)
{
CacheUpdated(sender, args);
}
}
#endregion
/// <summary>
/// Returns the real instance of the object ('this') for use in strongly typed events
/// </summary>
protected abstract TInstanceType Instance { get; }
public abstract Guid UniqueIdentifier { get; }
public abstract string Name { get; }
public virtual void RefreshAll()
{
OnCacheUpdated(Instance, new CacheRefresherEventArgs(null, MessageType.RefreshAll));
}
public virtual void Refresh(int id)
{
OnCacheUpdated(Instance, new CacheRefresherEventArgs(id, MessageType.RefreshById));
}
public virtual void Remove(int id)
{
OnCacheUpdated(Instance, new CacheRefresherEventArgs(id, MessageType.RemoveById));
}
public virtual void Refresh(Guid id)
{
OnCacheUpdated(Instance, new CacheRefresherEventArgs(id, MessageType.RefreshById));
}
/// <summary>
/// Clears the cache for all repository entities of this type
/// </summary>
/// <typeparam name="TEntity"></typeparam>
internal void ClearAllIsolatedCacheByEntityType<TEntity>()
where TEntity : class, IAggregateRoot
{
ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.ClearCache<TEntity>();
}
}
}
}
@@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Cache
{
public class CacheRefresherCollection : BuilderCollectionBase<ICacheRefresher>
{
public CacheRefresherCollection(IEnumerable<ICacheRefresher> items)
: base(items)
{ }
public ICacheRefresher this[Guid id]
=> this.FirstOrDefault(x => x.RefresherUniqueId == id);
}
}
@@ -1,15 +0,0 @@
using System.Collections.Generic;
using LightInject;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Cache
{
public class CacheRefresherCollectionBuilder : LazyCollectionBuilderBase<CacheRefresherCollectionBuilder, CacheRefresherCollection, ICacheRefresher>
{
public CacheRefresherCollectionBuilder(IServiceContainer container)
: base(container)
{ }
protected override CacheRefresherCollectionBuilder This => this;
}
}
@@ -16,4 +16,4 @@ namespace Umbraco.Core.Cache
public object MessageObject { get; private set; }
public MessageType MessageType { get; private set; }
}
}
}
@@ -1,9 +1,9 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Caching;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
@@ -16,26 +16,20 @@ namespace Umbraco.Core.Cache
}
/// <summary>
/// A wrapper for any IRuntimeCacheProvider that ensures that all inserts and returns
/// A wrapper for any IRuntimeCacheProvider that ensures that all inserts and returns
/// are a deep cloned copy of the item when the item is IDeepCloneable and that tracks changes are
/// reset if the object is TracksChangesEntityBase
/// </summary>
internal class DeepCloneRuntimeCacheProvider : IRuntimeCacheProvider, IRuntimeCacheProviderWrapper
{
public IRuntimeCacheProvider InnerProvider { get; }
public IRuntimeCacheProvider InnerProvider { get; private set; }
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
{
var type = typeof (DeepCloneRuntimeCacheProvider);
if (innerProvider.GetType() == type)
throw new InvalidOperationException($"A {type} cannot wrap another instance of {type}.");
InnerProvider = innerProvider;
}
#region Clear - doesn't require any changes
public void ClearAllCache()
{
InnerProvider.ClearAllCache();
@@ -69,8 +63,7 @@ namespace Umbraco.Core.Cache
public void ClearCacheByKeyExpression(string regexString)
{
InnerProvider.ClearCacheByKeyExpression(regexString);
}
}
#endregion
public IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
@@ -84,7 +77,7 @@ namespace Umbraco.Core.Cache
return InnerProvider.GetCacheItemsByKeyExpression(regexString)
.Select(CheckCloneableAndTracksChanges);
}
public object GetCacheItem(string cacheKey)
{
var item = InnerProvider.GetCacheItem(cacheKey);
@@ -112,11 +105,9 @@ namespace Umbraco.Core.Cache
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
if (value == null) return null; // do not store null values (backward compat)
// clone / reset to go into the cache
return CheckCloneableAndTracksChanges(value);
}, timeout, isSliding, priority, removedCallback, dependentFiles);
// clone / reset to go into the cache
return CheckCloneableAndTracksChanges(cached);
}
@@ -128,9 +119,8 @@ namespace Umbraco.Core.Cache
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
if (value == null) return null; // do not store null values (backward compat)
// clone / reset to go into the cache
return CheckCloneableAndTracksChanges(value);
}, timeout, isSliding, priority, removedCallback, dependentFiles);
}, timeout, isSliding, priority, removedCallback, dependentFiles);
}
private static object CheckCloneableAndTracksChanges(object input)
@@ -138,10 +128,11 @@ namespace Umbraco.Core.Cache
var cloneable = input as IDeepCloneable;
if (cloneable != null)
{
input = cloneable.DeepClone();
input = cloneable.DeepClone();
}
// reset dirty initial properties (U4-1946)
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
var tracksChanges = input as IRememberBeingDirty;
if (tracksChanges != null)
{
@@ -152,4 +143,4 @@ namespace Umbraco.Core.Cache
return input;
}
}
}
}
@@ -1,244 +1,268 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Scoping;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Represents the default cache policy.
/// The default cache policy for retrieving a single entity
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TId">The type of the identifier.</typeparam>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TId"></typeparam>
/// <remarks>
/// <para>The default cache policy caches entities with a 5 minutes sliding expiration.</para>
/// <para>Each entity is cached individually.</para>
/// <para>If options.GetAllCacheAllowZeroCount then a 'zero-count' array is cached when GetAll finds nothing.</para>
/// <para>If options.GetAllCacheValidateCount then we check against the db when getting many entities.</para>
/// This cache policy uses sliding expiration and caches instances for 5 minutes. However if allow zero count is true, then we use the
/// default policy with no expiry.
/// </remarks>
internal class DefaultRepositoryCachePolicy<TEntity, TId> : RepositoryCachePolicyBase<TEntity, TId>
where TEntity : class, IEntity
where TEntity : class, IAggregateRoot
{
private static readonly TEntity[] EmptyEntities = new TEntity[0]; // const
private readonly RepositoryCachePolicyOptions _options;
public DefaultRepositoryCachePolicy(IRuntimeCacheProvider cache, IScopeAccessor scopeAccessor, RepositoryCachePolicyOptions options)
: base(cache, scopeAccessor)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
public DefaultRepositoryCachePolicy(IRuntimeCacheProvider cache, RepositoryCachePolicyOptions options)
: base(cache)
{
if (options == null) throw new ArgumentNullException("options");
_options = options;
}
protected string GetEntityCacheKey(object id)
protected string GetCacheIdKey(object id)
{
if (id == null) throw new ArgumentNullException(nameof(id));
return GetEntityTypeCacheKey() + id;
if (id == null) throw new ArgumentNullException("id");
return string.Format("{0}{1}", GetCacheTypeKey(), id);
}
protected string GetEntityTypeCacheKey()
protected string GetCacheTypeKey()
{
return $"uRepo_{typeof (TEntity).Name}_";
return string.Format("uRepo_{0}_", typeof(TEntity).Name);
}
protected virtual void InsertEntity(string cacheKey, TEntity entity)
public override void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod)
{
Cache.InsertCacheItem(cacheKey, () => entity, TimeSpan.FromMinutes(5), true);
}
protected virtual void InsertEntities(TId[] ids, TEntity[] entities)
{
if (ids.Length == 0 && entities.Length == 0 && _options.GetAllCacheAllowZeroCount)
{
// getting all of them, and finding nothing.
// if we can cache a zero count, cache an empty array,
// for as long as the cache is not cleared (no expiration)
Cache.InsertCacheItem(GetEntityTypeCacheKey(), () => EmptyEntities);
}
else
{
// individually cache each item
foreach (var entity in entities)
{
var capture = entity;
Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => capture, TimeSpan.FromMinutes(5), true);
}
}
}
/// <inheritdoc />
public override void Create(TEntity entity, Action<TEntity> persistNew)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
if (entity == null) throw new ArgumentNullException("entity");
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
try
{
persistNew(entity);
persistMethod(entity);
// just to be safe, we cannot cache an item without an identity
if (entity.HasIdentity)
//set the disposal action
SetCacheAction(() =>
{
Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => entity, TimeSpan.FromMinutes(5), true);
}
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
//just to be safe, we cannot cache an item without an identity
if (entity.HasIdentity)
{
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => entity,
timeout: TimeSpan.FromMinutes(5),
isSliding: true);
}
//If there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetCacheTypeKey());
});
}
catch
{
// if an exception is thrown we need to remove the entry from cache,
// this is ONLY a work around because of the way
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
Cache.ClearCacheItem(GetEntityCacheKey(entity.Id));
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
//set the disposal action
SetCacheAction(() =>
{
//if an exception is thrown we need to remove the entry from cache, this is ONLY a work around because of the way
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
Cache.ClearCacheItem(GetCacheIdKey(entity.Id));
//If there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetCacheTypeKey());
});
throw;
}
}
/// <inheritdoc />
public override void Update(TEntity entity, Action<TEntity> persistUpdated)
public override void Remove(TEntity entity, Action<TEntity> persistMethod)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
if (entity == null) throw new ArgumentNullException("entity");
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
try
{
persistUpdated(entity);
// just to be safe, we cannot cache an item without an identity
if (entity.HasIdentity)
{
Cache.InsertCacheItem(GetEntityCacheKey(entity.Id), () => entity, TimeSpan.FromMinutes(5), true);
}
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
}
catch
{
// if an exception is thrown we need to remove the entry from cache,
// this is ONLY a work around because of the way
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
Cache.ClearCacheItem(GetEntityCacheKey(entity.Id));
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
throw;
}
}
/// <inheritdoc />
public override void Delete(TEntity entity, Action<TEntity> persistDeleted)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
try
{
persistDeleted(entity);
persistMethod(entity);
}
finally
{
// whatever happens, clear the cache
var cacheKey = GetEntityCacheKey(entity.Id);
Cache.ClearCacheItem(cacheKey);
// if there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetEntityTypeCacheKey());
//set the disposal action
var cacheKey = GetCacheIdKey(entity.Id);
SetCacheAction(() =>
{
Cache.ClearCacheItem(cacheKey);
//If there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetCacheTypeKey());
});
}
}
/// <inheritdoc />
public override TEntity Get(TId id, Func<TId, TEntity> performGet, Func<TId[], IEnumerable<TEntity>> performGetAll)
public override TEntity Get(TId id, Func<TId, TEntity> getFromRepo)
{
var cacheKey = GetEntityCacheKey(id);
var fromCache = Cache.GetCacheItem<TEntity>(cacheKey);
if (getFromRepo == null) throw new ArgumentNullException("getFromRepo");
// if found in cache then return else fetch and cache
var cacheKey = GetCacheIdKey(id);
var fromCache = Cache.GetCacheItem<TEntity>(cacheKey);
if (fromCache != null)
return fromCache;
var entity = performGet(id);
var entity = getFromRepo(id);
if (entity != null && entity.HasIdentity)
InsertEntity(cacheKey, entity);
//set the disposal action
SetCacheAction(cacheKey, entity);
return entity;
}
/// <inheritdoc />
public override TEntity GetCached(TId id)
public override TEntity Get(TId id)
{
var cacheKey = GetEntityCacheKey(id);
var cacheKey = GetCacheIdKey(id);
return Cache.GetCacheItem<TEntity>(cacheKey);
}
/// <inheritdoc />
public override bool Exists(TId id, Func<TId, bool> performExists, Func<TId[], IEnumerable<TEntity>> performGetAll)
public override bool Exists(TId id, Func<TId, bool> getFromRepo)
{
// if found in cache the return else check
var cacheKey = GetEntityCacheKey(id);
if (getFromRepo == null) throw new ArgumentNullException("getFromRepo");
var cacheKey = GetCacheIdKey(id);
var fromCache = Cache.GetCacheItem<TEntity>(cacheKey);
return fromCache != null || performExists(id);
return fromCache != null || getFromRepo(id);
}
/// <inheritdoc />
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> performGetAll)
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo)
{
if (ids.Length > 0)
if (getFromRepo == null) throw new ArgumentNullException("getFromRepo");
if (ids.Any())
{
// try to get each entity from the cache
// if we can find all of them, return
var entities = ids.Select(GetCached).WhereNotNull().ToArray();
if (ids.Length.Equals(entities.Length))
return entities; // no need for null checks, we are not caching nulls
var entities = ids.Select(Get).ToArray();
if (ids.Length.Equals(entities.Length) && entities.Any(x => x == null) == false)
return entities;
}
else
{
// get everything we have
var entities = Cache.GetCacheItemsByKeySearch<TEntity>(GetEntityTypeCacheKey())
.ToArray(); // no need for null checks, we are not caching nulls
if (entities.Length > 0)
var allEntities = GetAllFromCache();
if (allEntities.Any())
{
// if some of them were in the cache...
if (_options.GetAllCacheValidateCount)
{
// need to validate the count, get the actual count and return if ok
//Get count of all entities of current type (TEntity) to ensure cached result is correct
var totalCount = _options.PerformCount();
if (entities.Length == totalCount)
return entities;
if (allEntities.Length == totalCount)
return allEntities;
}
else
{
// no need to validate, just return what we have and assume it's all there is
return entities;
return allEntities;
}
}
else if (_options.GetAllCacheAllowZeroCount)
{
// if none of them were in the cache
// and we allow zero count - check for the special (empty) entry
var empty = Cache.GetCacheItem<TEntity[]>(GetEntityTypeCacheKey());
if (empty != null) return empty;
//if the repository allows caching a zero count, then check the zero count cache
if (HasZeroCountCache())
{
//there is a zero count cache so return an empty list
return new TEntity[] {};
}
}
}
// cache failed, get from repo and cache
var repoEntities = performGetAll(ids)
.WhereNotNull() // exclude nulls!
.Where(x => x.HasIdentity) // be safe, though would be weird...
//we need to do the lookup from the repo
var entityCollection = getFromRepo(ids)
//ensure we don't include any null refs in the returned collection!
.WhereNotNull()
.ToArray();
// note: if empty & allow zero count, will cache a special (empty) entry
InsertEntities(ids, repoEntities);
//set the disposal action
SetCacheAction(ids, entityCollection);
return repoEntities;
return entityCollection;
}
/// <inheritdoc />
public override void ClearAll()
/// <summary>
/// Looks up the zero count cache, must return null if it doesn't exist
/// </summary>
/// <returns></returns>
protected bool HasZeroCountCache()
{
Cache.ClearCacheByKeySearch(GetEntityTypeCacheKey());
var zeroCount = Cache.GetCacheItem<TEntity[]>(GetCacheTypeKey());
return (zeroCount != null && zeroCount.Any() == false);
}
/// <summary>
/// Performs the lookup for all entities of this type from the cache
/// </summary>
/// <returns></returns>
protected TEntity[] GetAllFromCache()
{
var allEntities = Cache.GetCacheItemsByKeySearch<TEntity>(GetCacheTypeKey())
.WhereNotNull()
.ToArray();
return allEntities.Any() ? allEntities : new TEntity[] {};
}
/// <summary>
/// Sets the action to execute on disposal for a single entity
/// </summary>
/// <param name="cacheKey"></param>
/// <param name="entity"></param>
protected virtual void SetCacheAction(string cacheKey, TEntity entity)
{
if (entity == null) return;
SetCacheAction(() =>
{
//just to be safe, we cannot cache an item without an identity
if (entity.HasIdentity)
{
Cache.InsertCacheItem(cacheKey, () => entity,
timeout: TimeSpan.FromMinutes(5),
isSliding: true);
}
});
}
/// <summary>
/// Sets the action to execute on disposal for an entity collection
/// </summary>
/// <param name="ids"></param>
/// <param name="entityCollection"></param>
protected virtual void SetCacheAction(TId[] ids, TEntity[] entityCollection)
{
SetCacheAction(() =>
{
//This option cannot execute if we are looking up specific Ids
if (ids.Any() == false && entityCollection.Length == 0 && _options.GetAllCacheAllowZeroCount)
{
//there was nothing returned but we want to cache a zero count result so add an TEntity[] to the cache
// to signify that there is a zero count cache
//NOTE: Don't set expiry/sliding for a zero count
Cache.InsertCacheItem(GetCacheTypeKey(), () => new TEntity[] {});
}
else
{
//This is the default behavior, we'll individually cache each item so that if/when these items are resolved
// by id, they are returned from the already existing cache.
foreach (var entity in entityCollection.WhereNotNull())
{
var localCopy = entity;
//just to be safe, we cannot cache an item without an identity
if (localCopy.HasIdentity)
{
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => localCopy,
timeout: TimeSpan.FromMinutes(5),
isSliding: true);
}
}
}
});
}
}
}
}
@@ -0,0 +1,27 @@
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Creates cache policies
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TId"></typeparam>
internal class DefaultRepositoryCachePolicyFactory<TEntity, TId> : IRepositoryCachePolicyFactory<TEntity, TId>
where TEntity : class, IAggregateRoot
{
private readonly IRuntimeCacheProvider _runtimeCache;
private readonly RepositoryCachePolicyOptions _options;
public DefaultRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, RepositoryCachePolicyOptions options)
{
_runtimeCache = runtimeCache;
_options = options;
}
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
{
return new DefaultRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _options);
}
}
}
@@ -1,147 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Cache
{
internal class DictionaryCacheProvider : ICacheProvider
{
private readonly ConcurrentDictionary<string, Lazy<object>> _items
= new ConcurrentDictionary<string, Lazy<object>>();
// for tests
internal ConcurrentDictionary<string, Lazy<object>> Items => _items;
public void ClearAllCache()
{
_items.Clear();
}
public void ClearCacheItem(string key)
{
_items.TryRemove(key, out _);
}
public void ClearCacheObjectTypes(string typeName)
{
var type = TypeFinder.GetTypeByName(typeName);
if (type == null) return;
var isInterface = type.IsInterface;
foreach (var kvp in _items
.Where(x =>
{
// entry.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// get non-created as NonCreatedValue & exceptions as null
var value = DictionaryCacheProviderBase.GetSafeLazyValue(x.Value, true);
// if T is an interface remove anything that implements that interface
// otherwise remove exact types (not inherited types)
return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type));
}))
_items.TryRemove(kvp.Key, out _);
}
public void ClearCacheObjectTypes<T>()
{
var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface;
foreach (var kvp in _items
.Where(x =>
{
// entry.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// compare on exact type, don't use "is"
// get non-created as NonCreatedValue & exceptions as null
var value = DictionaryCacheProviderBase.GetSafeLazyValue(x.Value, true);
// if T is an interface remove anything that implements that interface
// otherwise remove exact types (not inherited types)
return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT));
}))
_items.TryRemove(kvp.Key, out _);
}
public void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
{
var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface;
foreach (var kvp in _items
.Where(x =>
{
// entry.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// compare on exact type, don't use "is"
// get non-created as NonCreatedValue & exceptions as null
var value = DictionaryCacheProviderBase.GetSafeLazyValue(x.Value, true);
if (value == null) return true;
// if T is an interface remove anything that implements that interface
// otherwise remove exact types (not inherited types)
return (isInterface ? (value is T) : (value.GetType() == typeOfT))
// run predicate on the 'public key' part only, ie without prefix
&& predicate(x.Key, (T)value);
}))
_items.TryRemove(kvp.Key, out _);
}
public void ClearCacheByKeySearch(string keyStartsWith)
{
foreach (var ikvp in _items
.Where(kvp => kvp.Key.InvariantStartsWith(keyStartsWith)))
_items.TryRemove(ikvp.Key, out _);
}
public void ClearCacheByKeyExpression(string regexString)
{
foreach (var ikvp in _items
.Where(kvp => Regex.IsMatch(kvp.Key, regexString)))
_items.TryRemove(ikvp.Key, out _);
}
public IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
{
return _items
.Where(kvp => kvp.Key.InvariantStartsWith(keyStartsWith))
.Select(kvp => DictionaryCacheProviderBase.GetSafeLazyValue(kvp.Value))
.Where(x => x != null);
}
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
{
return _items
.Where(kvp => Regex.IsMatch(kvp.Key, regexString))
.Select(kvp => DictionaryCacheProviderBase.GetSafeLazyValue(kvp.Value))
.Where(x => x != null);
}
public object GetCacheItem(string cacheKey)
{
_items.TryGetValue(cacheKey, out var result); // else null
return result == null ? null : DictionaryCacheProviderBase.GetSafeLazyValue(result); // return exceptions as null
}
public object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
var result = _items.GetOrAdd(cacheKey, k => DictionaryCacheProviderBase.GetSafeLazy(getCacheItem));
var value = result.Value; // will not throw (safe lazy)
if (!(value is DictionaryCacheProviderBase.ExceptionHolder eh))
return value;
// and... it's in the cache anyway - so contrary to other cache providers,
// which would trick with GetSafeLazyValue, we need to remove by ourselves,
// in order NOT to cache exceptions
_items.TryRemove(cacheKey, out result);
eh.Exception.Throw(); // throw once!
return null; // never reached
}
}
}
@@ -2,9 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Text.RegularExpressions;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Cache
{
@@ -24,13 +22,8 @@ namespace Umbraco.Core.Cache
protected abstract object GetEntry(string key);
// read-write lock the underlying cache
//protected abstract IDisposable ReadLock { get; }
//protected abstract IDisposable WriteLock { get; }
protected abstract void EnterReadLock();
protected abstract void ExitReadLock();
protected abstract void EnterWriteLock();
protected abstract void ExitWriteLock();
protected abstract IDisposable ReadLock { get; }
protected abstract IDisposable WriteLock { get; }
protected string GetCacheKey(string key)
{
@@ -51,7 +44,7 @@ namespace Umbraco.Core.Cache
}
catch (Exception e)
{
return new ExceptionHolder(ExceptionDispatchInfo.Capture(e));
return new ExceptionHolder(e);
}
});
}
@@ -81,43 +74,33 @@ namespace Umbraco.Core.Cache
internal class ExceptionHolder
{
public ExceptionHolder(ExceptionDispatchInfo e)
public ExceptionHolder(Exception e)
{
Exception = e;
}
public ExceptionDispatchInfo Exception { get; }
public Exception Exception { get; private set; }
}
#region Clear
public virtual void ClearAllCache()
{
try
using (WriteLock)
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheItem(string key)
{
var cacheKey = GetCacheKey(key);
try
using (WriteLock)
{
EnterWriteLock();
RemoveEntry(cacheKey);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheObjectTypes(string typeName)
@@ -125,16 +108,15 @@ namespace Umbraco.Core.Cache
var type = TypeFinder.GetTypeByName(typeName);
if (type == null) return;
var isInterface = type.IsInterface;
try
using (WriteLock)
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x =>
{
// entry.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
// if T is an interface remove anything that implements that interface
// otherwise remove exact types (not inherited types)
@@ -143,19 +125,14 @@ namespace Umbraco.Core.Cache
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheObjectTypes<T>()
{
var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface;
try
using (WriteLock)
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x =>
{
@@ -163,7 +140,7 @@ namespace Umbraco.Core.Cache
// remove null values as well, does not hurt
// compare on exact type, don't use "is"
// get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
// if T is an interface remove anything that implements that interface
// otherwise remove exact types (not inherited types)
@@ -172,10 +149,6 @@ namespace Umbraco.Core.Cache
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
@@ -183,9 +156,8 @@ namespace Umbraco.Core.Cache
var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface;
var plen = CacheItemPrefix.Length + 1;
try
using (WriteLock)
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x =>
{
@@ -193,7 +165,7 @@ namespace Umbraco.Core.Cache
// remove null values as well, does not hurt
// compare on exact type, don't use "is"
// get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
if (value == null) return true;
// if T is an interface remove anything that implements that interface
@@ -204,44 +176,30 @@ namespace Umbraco.Core.Cache
}))
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheByKeySearch(string keyStartsWith)
{
var plen = CacheItemPrefix.Length + 1;
try
using (WriteLock)
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheByKeyExpression(string regexString)
{
var plen = CacheItemPrefix.Length + 1;
try
using (WriteLock)
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
#endregion
@@ -252,18 +210,12 @@ namespace Umbraco.Core.Cache
{
var plen = CacheItemPrefix.Length + 1;
IEnumerable<DictionaryEntry> entries;
try
using (ReadLock)
{
EnterReadLock();
entries = GetDictionaryEntries()
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
.ToArray(); // evaluate while locked
}
finally
{
ExitReadLock();
}
return entries
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null); // backward compat, don't store null values in the cache
@@ -274,17 +226,12 @@ namespace Umbraco.Core.Cache
const string prefix = CacheItemPrefix + "-";
var plen = prefix.Length;
IEnumerable<DictionaryEntry> entries;
try
using (ReadLock)
{
EnterReadLock();
entries = GetDictionaryEntries()
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
.ToArray(); // evaluate while locked
}
finally
{
ExitReadLock();
}
return entries
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null); // backward compat, don't store null values in the cache
@@ -294,15 +241,10 @@ namespace Umbraco.Core.Cache
{
cacheKey = GetCacheKey(cacheKey);
Lazy<object> result;
try
using (ReadLock)
{
EnterReadLock();
result = GetEntry(cacheKey) as Lazy<object>; // null if key not found
}
finally
{
ExitReadLock();
}
return result == null ? null : GetSafeLazyValue(result); // return exceptions as null
}
@@ -310,4 +252,4 @@ namespace Umbraco.Core.Cache
#endregion
}
}
}
@@ -1,177 +1,229 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Collections;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Scoping;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Represents a caching policy that caches the entire entities set as a single collection.
/// A caching policy that caches an entire dataset as a single collection
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TId">The type of the identifier.</typeparam>
/// <remarks>
/// <para>Caches the entire set of entities as a single collection.</para>
/// <para>Used by Content-, Media- and MemberTypeRepository, DataTypeRepository, DomainRepository,
/// LanguageRepository, PublicAccessRepository, TemplateRepository... things that make sense to
/// keep as a whole in memory.</para>
/// </remarks>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TId"></typeparam>
internal class FullDataSetRepositoryCachePolicy<TEntity, TId> : RepositoryCachePolicyBase<TEntity, TId>
where TEntity : class, IEntity
where TEntity : class, IAggregateRoot
{
private readonly Func<TEntity, TId> _entityGetId;
private readonly Func<TEntity, TId> _getEntityId;
private readonly Func<IEnumerable<TEntity>> _getAllFromRepo;
private readonly bool _expires;
public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache, IScopeAccessor scopeAccessor, Func<TEntity, TId> entityGetId, bool expires)
: base(cache, scopeAccessor)
public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache, Func<TEntity, TId> getEntityId, Func<IEnumerable<TEntity>> getAllFromRepo, bool expires)
: base(cache)
{
_entityGetId = entityGetId;
_getEntityId = getEntityId;
_getAllFromRepo = getAllFromRepo;
_expires = expires;
}
protected static readonly TId[] EmptyIds = new TId[0]; // const
private bool? _hasZeroCountCache;
protected string GetEntityTypeCacheKey()
protected string GetCacheTypeKey()
{
return $"uRepo_{typeof (TEntity).Name}_";
return string.Format("uRepo_{0}_", typeof(TEntity).Name);
}
protected void InsertEntities(TEntity[] entities)
public override void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod)
{
// cache is expected to be a deep-cloning cache ie it deep-clones whatever is
// IDeepCloneable when it goes in, and out. it also resets dirty properties,
// making sure that no 'dirty' entity is cached.
//
// this policy is caching the entire list of entities. to ensure that entities
// are properly deep-clones when cached, it uses a DeepCloneableList. however,
// we don't want to deep-clone *each* entity in the list when fetching it from
// cache as that would not be efficient for Get(id). so the DeepCloneableList is
// set to ListCloneBehavior.CloneOnce ie it will clone *once* when inserting,
// and then will *not* clone when retrieving.
var key = GetEntityTypeCacheKey();
if (_expires)
{
Cache.InsertCacheItem(key, () => new DeepCloneableList<TEntity>(entities), TimeSpan.FromMinutes(5), true);
}
else
{
Cache.InsertCacheItem(key, () => new DeepCloneableList<TEntity>(entities));
}
}
/// <inheritdoc />
public override void Create(TEntity entity, Action<TEntity> persistNew)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
if (entity == null) throw new ArgumentNullException("entity");
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
try
{
persistNew(entity);
persistMethod(entity);
//set the disposal action
SetCacheAction(() =>
{
//Clear all
Cache.ClearCacheItem(GetCacheTypeKey());
});
}
finally
catch
{
ClearAll();
//set the disposal action
SetCacheAction(() =>
{
//Clear all
Cache.ClearCacheItem(GetCacheTypeKey());
});
throw;
}
}
/// <inheritdoc />
public override void Update(TEntity entity, Action<TEntity> persistUpdated)
public override void Remove(TEntity entity, Action<TEntity> persistMethod)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
if (entity == null) throw new ArgumentNullException("entity");
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
try
{
persistUpdated(entity);
persistMethod(entity);
}
finally
{
ClearAll();
//set the disposal action
SetCacheAction(() =>
{
//Clear all
Cache.ClearCacheItem(GetCacheTypeKey());
});
}
}
/// <inheritdoc />
public override void Delete(TEntity entity, Action<TEntity> persistDeleted)
public override TEntity Get(TId id, Func<TId, TEntity> getFromRepo)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
//Force get all with cache
var found = GetAll(new TId[] { }, ids => _getAllFromRepo().WhereNotNull());
try
//we don't have anything in cache (this should never happen), just return from the repo
if (found == null) return getFromRepo(id);
var entity = found.FirstOrDefault(x => _getEntityId(x).Equals(id));
if (entity == null) return null;
//We must ensure to deep clone each one out manually since the deep clone list only clones one way
return (TEntity)entity.DeepClone();
}
public override TEntity Get(TId id)
{
//Force get all with cache
var found = GetAll(new TId[] { }, ids => _getAllFromRepo().WhereNotNull());
//we don't have anything in cache (this should never happen), just return null
if (found == null) return null;
var entity = found.FirstOrDefault(x => _getEntityId(x).Equals(id));
if (entity == null) return null;
//We must ensure to deep clone each one out manually since the deep clone list only clones one way
return (TEntity)entity.DeepClone();
}
public override bool Exists(TId id, Func<TId, bool> getFromRepo)
{
//Force get all with cache
var found = GetAll(new TId[] { }, ids => _getAllFromRepo().WhereNotNull());
//we don't have anything in cache (this should never happen), just return from the repo
return found == null
? getFromRepo(id)
: found.Any(x => _getEntityId(x).Equals(id));
}
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo)
{
//process getting all including setting the cache callback
var result = PerformGetAll(getFromRepo);
//now that the base result has been calculated, they will all be cached.
// Now we can just filter by ids if they have been supplied
return (ids.Any()
? result.Where(x => ids.Contains(_getEntityId(x))).ToArray()
: result)
//We must ensure to deep clone each one out manually since the deep clone list only clones one way
.Select(x => (TEntity)x.DeepClone())
.ToArray();
}
private TEntity[] PerformGetAll(Func<TId[], IEnumerable<TEntity>> getFromRepo)
{
var allEntities = GetAllFromCache();
if (allEntities.Any())
{
persistDeleted(entity);
return allEntities;
}
finally
//check the zero count cache
if (HasZeroCountCache())
{
ClearAll();
//there is a zero count cache so return an empty list
return new TEntity[] { };
}
//we need to do the lookup from the repo
var entityCollection = getFromRepo(new TId[] { })
//ensure we don't include any null refs in the returned collection!
.WhereNotNull()
.ToArray();
//set the disposal action
SetCacheAction(entityCollection);
return entityCollection;
}
/// <inheritdoc />
public override TEntity Get(TId id, Func<TId, TEntity> performGet, Func<TId[], IEnumerable<TEntity>> performGetAll)
/// <summary>
/// For this type of caching policy, we don't cache individual items
/// </summary>
/// <param name="cacheKey"></param>
/// <param name="entity"></param>
protected void SetCacheAction(string cacheKey, TEntity entity)
{
// get all from the cache, then look for the entity
var all = GetAllCached(performGetAll);
var entity = all.FirstOrDefault(x => _entityGetId(x).Equals(id));
// see note in InsertEntities - what we get here is the original
// cached entity, not a clone, so we need to manually ensure it is deep-cloned.
return (TEntity)entity?.DeepClone();
//No-op
}
/// <inheritdoc />
public override TEntity GetCached(TId id)
/// <summary>
/// Sets the action to execute on disposal for an entity collection
/// </summary>
/// <param name="entityCollection"></param>
protected void SetCacheAction(TEntity[] entityCollection)
{
// get all from the cache -- and only the cache, then look for the entity
var all = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetEntityTypeCacheKey());
var entity = all?.FirstOrDefault(x => _entityGetId(x).Equals(id));
//set the disposal action
SetCacheAction(() =>
{
//We want to cache the result as a single collection
// see note in InsertEntities - what we get here is the original
// cached entity, not a clone, so we need to manually ensure it is deep-cloned.
return (TEntity) entity?.DeepClone();
if (_expires)
{
Cache.InsertCacheItem(GetCacheTypeKey(), () => new DeepCloneableList<TEntity>(entityCollection),
timeout: TimeSpan.FromMinutes(5),
isSliding: true);
}
else
{
Cache.InsertCacheItem(GetCacheTypeKey(), () => new DeepCloneableList<TEntity>(entityCollection));
}
});
}
/// <inheritdoc />
public override bool Exists(TId id, Func<TId, bool> performExits, Func<TId[], IEnumerable<TEntity>> performGetAll)
/// <summary>
/// Looks up the zero count cache, must return null if it doesn't exist
/// </summary>
/// <returns></returns>
protected bool HasZeroCountCache()
{
// get all as one set, then look for the entity
var all = GetAllCached(performGetAll);
return all.Any(x => _entityGetId(x).Equals(id));
if (_hasZeroCountCache.HasValue)
return _hasZeroCountCache.Value;
_hasZeroCountCache = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetCacheTypeKey()) != null;
return _hasZeroCountCache.Value;
}
/// <inheritdoc />
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> performGetAll)
/// <summary>
/// This policy will cache the full data set as a single collection
/// </summary>
/// <returns></returns>
protected TEntity[] GetAllFromCache()
{
// get all as one set, from cache if possible, else repo
var all = GetAllCached(performGetAll);
var found = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetCacheTypeKey());
// if ids have been specified, filter
if (ids.Length > 0) all = all.Where(x => ids.Contains(_entityGetId(x)));
//This method will get called before checking for zero count cache, so we'll just set the flag here
_hasZeroCountCache = found != null;
// and return
// see note in SetCacheActionToInsertEntities - what we get here is the original
// cached entities, not clones, so we need to manually ensure they are deep-cloned.
return all.Select(x => (TEntity) x.DeepClone()).ToArray();
return found == null ? new TEntity[] { } : found.WhereNotNull().ToArray();
}
// does NOT clone anything, so be nice with the returned values
internal IEnumerable<TEntity> GetAllCached(Func<TId[], IEnumerable<TEntity>> performGetAll)
{
// try the cache first
var all = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetEntityTypeCacheKey());
if (all != null) return all.ToArray();
// else get from repo and cache
var entities = performGetAll(EmptyIds).WhereNotNull().ToArray();
InsertEntities(entities); // may be an empty array...
return entities;
}
/// <inheritdoc />
public override void ClearAll()
{
Cache.ClearCacheItem(GetEntityTypeCacheKey());
}
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Creates cache policies
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TId"></typeparam>
internal class FullDataSetRepositoryCachePolicyFactory<TEntity, TId> : IRepositoryCachePolicyFactory<TEntity, TId>
where TEntity : class, IAggregateRoot
{
private readonly IRuntimeCacheProvider _runtimeCache;
private readonly Func<TEntity, TId> _getEntityId;
private readonly Func<IEnumerable<TEntity>> _getAllFromRepo;
private readonly bool _expires;
public FullDataSetRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, Func<TEntity, TId> getEntityId, Func<IEnumerable<TEntity>> getAllFromRepo, bool expires)
{
_runtimeCache = runtimeCache;
_getEntityId = getEntityId;
_getAllFromRepo = getAllFromRepo;
_expires = expires;
}
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
{
return new FullDataSetRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _getEntityId, _getAllFromRepo, _expires);
}
}
}
@@ -9,9 +9,6 @@ namespace Umbraco.Core.Cache
/// <summary>
/// A cache provider that caches items in the HttpContext.Items
/// </summary>
/// <remarks>
/// If the Items collection is null, then this provider has no effect
/// </remarks>
internal class HttpRequestCacheProvider : DictionaryCacheProviderBase
{
// context provider
@@ -37,11 +34,6 @@ namespace Umbraco.Core.Cache
get { return _context != null ? _context.Items : HttpContext.Current.Items; }
}
private bool HasContextItems
{
get { return (_context != null && _context.Items != null) || HttpContext.Current != null; }
}
// for unit tests
public HttpRequestCacheProvider(HttpContextBase context)
{
@@ -58,47 +50,38 @@ namespace Umbraco.Core.Cache
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
{
const string prefix = CacheItemPrefix + "-";
if (HasContextItems == false) return Enumerable.Empty<DictionaryEntry>();
return ContextItems.Cast<DictionaryEntry>()
.Where(x => x.Key is string && ((string)x.Key).StartsWith(prefix));
}
protected override void RemoveEntry(string key)
{
if (HasContextItems == false) return;
ContextItems.Remove(key);
}
protected override object GetEntry(string key)
{
return HasContextItems ? ContextItems[key] : null;
return ContextItems[key];
}
#region Lock
private bool _entered;
protected override void EnterReadLock() => EnterWriteLock();
protected override void EnterWriteLock()
protected override IDisposable ReadLock
{
if (HasContextItems)
{
System.Threading.Monitor.Enter(ContextItems.SyncRoot, ref _entered);
}
// there's no difference between ReadLock and WriteLock here
get { return WriteLock; }
}
protected override void ExitReadLock() => ExitWriteLock();
protected override void ExitWriteLock()
protected override IDisposable WriteLock
{
if (_entered)
// NOTE
// could think about just overriding base.Locker to return a different
// object but then we'd create a ReaderWriterLockSlim per request,
// which is less efficient than just using a basic monitor lock.
get
{
_entered = false;
System.Threading.Monitor.Exit(ContextItems.SyncRoot);
return new MonitorLock(ContextItems.SyncRoot);
}
}
@@ -108,16 +91,12 @@ namespace Umbraco.Core.Cache
public override object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
//no place to cache so just return the callback result
if (HasContextItems == false) return getCacheItem();
cacheKey = GetCacheKey(cacheKey);
Lazy<object> result;
try
using (WriteLock)
{
EnterWriteLock();
result = ContextItems[cacheKey] as Lazy<object>; // null if key not found
// cannot create value within the lock, so if result.IsValueCreated is false, just
@@ -130,10 +109,6 @@ namespace Umbraco.Core.Cache
ContextItems[cacheKey] = result;
}
}
finally
{
ExitWriteLock();
}
// using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
// exceptions (but try again and again) and silently eat them - however at
@@ -143,7 +118,8 @@ namespace Umbraco.Core.Cache
//return result.Value;
var value = result.Value; // will not throw (safe lazy)
if (value is ExceptionHolder eh) eh.Exception.Throw(); // throw once!
var eh = value as ExceptionHolder;
if (eh != null) throw eh.Exception; // throw once!
return value;
}
@@ -152,10 +128,5 @@ namespace Umbraco.Core.Cache
#region Insert
#endregion
private class NoopLocker : DisposableObjectSlim
{
protected override void DisposeResources()
{ }
}
}
}
}
@@ -50,26 +50,14 @@ namespace Umbraco.Core.Cache
#region Lock
protected override void EnterReadLock()
protected override IDisposable ReadLock
{
_locker.EnterReadLock();
get { return new ReadLock(_locker); }
}
protected override void EnterWriteLock()
protected override IDisposable WriteLock
{
_locker.EnterWriteLock();;
}
protected override void ExitReadLock()
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
protected override void ExitWriteLock()
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
get { return new WriteLock(_locker); }
}
#endregion
@@ -110,7 +98,7 @@ namespace Umbraco.Core.Cache
// on the Lazy lock to ensure that getCacheItem runs once and everybody waits on it, while the global
// application lock has been released.
// NOTE
// NOTE
// The Lazy value creation may produce a null value.
// Must make sure (for backward compatibility) that we pretend they are not in the cache.
// So if we find an entry in the cache that already has its value created and is null,
@@ -130,16 +118,10 @@ namespace Umbraco.Core.Cache
// reads. We first try with a normal ReadLock for maximum concurrency and take the penalty of
// having to re-lock in case there's no value. Would need to benchmark to figure out whether
// it's worth it, though...
try
using (new ReadLock(_locker))
{
_locker.EnterReadLock();
result = _cache.Get(cacheKey) as Lazy<object>; // null if key not found
}
finally
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
var value = result == null ? null : GetSafeLazyValue(result);
if (value != null) return value;
@@ -171,7 +153,8 @@ namespace Umbraco.Core.Cache
//return result.Value;
value = result.Value; // will not throw (safe lazy)
if (value is ExceptionHolder eh) eh.Exception.Throw(); // throw once!
var eh = value as ExceptionHolder;
if (eh != null) throw eh.Exception; // throw once!
return value;
}
@@ -213,17 +196,11 @@ namespace Umbraco.Core.Cache
var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
try
using (new WriteLock(_locker))
{
_locker.EnterWriteLock();
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
@@ -238,4 +215,4 @@ namespace Umbraco.Core.Cache
#endregion
}
}
}
+3 -3
View File
@@ -4,7 +4,7 @@ using System.Collections.Generic;
namespace Umbraco.Core.Cache
{
/// <summary>
/// An interface for implementing a basic cache provider
/// An abstract class for implementing a basic cache provider
/// </summary>
public interface ICacheProvider
{
@@ -55,7 +55,7 @@ namespace Umbraco.Core.Cache
IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith);
IEnumerable<object> GetCacheItemsByKeyExpression(string regexString);
/// <summary>
/// Returns an item with a given key
/// </summary>
@@ -65,4 +65,4 @@ namespace Umbraco.Core.Cache
object GetCacheItem(string cacheKey, Func<object> getCacheItem);
}
}
}

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