Compare commits

..

252 Commits

Author SHA1 Message Date
Sebastiaan Janssen 31767a4152 Merge pull request #1857 from umbraco/temp-U4-9696
fixes: U4-9696 Update hover of Umbraco Forms install button
2017-04-04 13:42:15 +02:00
Mads Rasmussen d79134c710 fixes: U4-9696 Update hover of Umbraco Forms install button 2017-04-04 13:20:22 +02:00
Claus 2ed4948619 Merge pull request #1854 from umbraco/temp-U4-9720
U4-9720 No more _thumb thumbnail file generation - all thumbnails should be generated via Image Processor
2017-04-04 09:49:10 +02:00
Sebastiaan Janssen 0e67c787a8 Bump version to RC :) 2017-04-04 08:05:32 +02:00
Shannon ebfb2b536f bumps version to RC01 2017-04-04 13:12:03 +10:00
Shannon Deminick 81010444f3 Merge pull request #1852 from umbraco/temp-U4-9707
fixes: U4-9707 Umbraco 7.6.0 - add border-radius to listview create b…
2017-04-04 12:51:56 +10:00
Shannon Deminick bbbc1949bc Merge pull request #1853 from umbraco/temp-U4-9708
fixes: U4-9708 Make lightbox screenshots in packages section bigger
2017-04-04 12:48:30 +10:00
Shannon Deminick 7b34e59222 Merge pull request #1851 from umbraco/temp-U4-9706
fixes: U4-9706 Partial View Macro File is not created but Macro is
2017-04-04 12:46:29 +10:00
Shannon 3706405bff Obsoletes all methods that perform image manipulation and thumbnail generation, removes thumbnail generation from occurring, fixes the issue of getting the size for an image!! Argh, we were bypassing the Exif data reading and instead still loading the whole image in! 2017-04-04 12:14:06 +10:00
Mads Rasmussen 8a0efd7790 fixes: U4-9708 Make lightbox screenshots in packages section bigger 2017-04-03 15:24:37 +02:00
Mads Rasmussen bd2ac3d128 fixes: U4-9707 Umbraco 7.6.0 - add border-radius to listview create button 2017-04-03 15:15:39 +02:00
Emil Wangaa c25b710b80 Using the VirtualPath for creating the partial view macro + file instead of parent+filename 2017-04-03 14:31:21 +02:00
Shannon 09e060ff92 Merge branch 'dev-v7.6' of https://github.com/umbraco/Umbraco-CMS into dev-v7.6 2017-04-03 21:53:21 +10:00
Shannon 2248a85876 Merge remote-tracking branch 'origin/dev-v7' into dev-v7.6
# Conflicts:
#	build/NuSpecs/UmbracoCms.nuspec
#	src/Umbraco.Core/Services/ContentTypeService.cs
#	src/Umbraco.Web.UI.Client/src/views/dashboard/developer/examinemanagement.html
#	src/Umbraco.Web.UI/packages.config
2017-04-03 21:50:22 +10:00
Robot for Continuous Integration a3f4b2db5d Merge pull request #1771 from umbraco/temp-faster-startup-less-scanning
Temp faster startup less scanning
2017-04-03 13:45:30 +02:00
Stephan 5947f01590 RIP DirtyBackDoor 2017-04-03 13:45:03 +02:00
Mads Rasmussen 75a006ca87 move create macro logic from partial view macro file dialog to editor 2017-04-03 13:32:15 +02:00
Shannon cee5880501 Changes TypeHelper back to Ordinal since that is what it was before 2017-04-03 21:16:08 +10:00
Shannon f65002ea16 Ensures we only write the cache file if we are scanning 2017-04-03 21:15:50 +10:00
Shannon bd1bfa416c Ensures both IServiceConnector and BaseMapper are IDiscoverable because we scan for them 2017-04-03 21:15:34 +10:00
Shannon 317f96a1bd removes very old logic for rescanning IAction, this is totally unecessary 2017-04-03 21:15:14 +10:00
Shannon a42d6b954f ensure that we have cache = true for ITree and IApplication because otherwise we'll be scanning but they are implicitly cached because they are IDiscoverable 2017-04-03 21:14:45 +10:00
Stephan 71b8674664 U4-9576 - deal with broken cache file 2017-04-03 09:25:27 +02:00
Shannon 9e3ca51286 fixes build error... though that check will need to be put back in 2017-04-03 17:17:31 +10:00
Shannon 0e6f2b542e Merge branch 'dev-v7.6' into temp-faster-startup-less-scanning
# Conflicts:
#	src/Umbraco.Core/PluginManager.cs
2017-04-03 16:57:57 +10:00
Shannon Deminick 218f523022 Merge pull request #1843 from umbraco/temp-U4-9691
Fixes the Examine mgmt dashboard to look better and to detect if an i…
2017-04-03 16:28:36 +10:00
Shannon Deminick 50c6fb036a Merge pull request #1839 from umbraco/temp-uaasscrum-827
uaasscrum-827 - more robust umbraco.config
2017-04-03 16:19:27 +10:00
Shannon Deminick bc2115ff0a Merge pull request #1847 from umbraco/temp-u4-9683
Upgrade to ModelsBuilder 3.0.6
2017-04-03 16:03:13 +10:00
Shannon Deminick 9eee5c2bc0 Merge pull request #1840 from umbraco/temp-U4-9689
U4-9689 Content type description isn't always saved the same way
2017-04-03 15:53:30 +10:00
Claus 038163421b Merge pull request #1849 from umbraco/temp-u4-9702
U4-9702 - event error when deleting content type container
2017-03-30 15:28:09 +02:00
Mads Rasmussen 7ce58f6e5f installer image is a jpg 2017-03-30 12:07:43 +02:00
Sebastiaan Janssen c6470decb2 Merge branch 'temp-U4-9687' into dev-v7.6 2017-03-30 11:46:37 +02:00
Sebastiaan Janssen 8a28639331 Revert commit of test variable 2017-03-30 11:43:48 +02:00
Sebastiaan Janssen 65b2b7cb82 Merge pull request #1848 from umbraco/temp-U4-9687
Fixes: U4-9687 Update login screen UI
2017-03-30 11:21:42 +02:00
Sebastiaan Janssen 2daf71aee4 Move LoginBackgroundImage to the content section instead of the security section 2017-03-30 11:15:12 +02:00
Sebastiaan Janssen 339edb2295 Merge branch 'dev-v7.6' into temp-U4-9687 2017-03-30 10:49:03 +02:00
Stephan e117b764fb U4-9702 - event error when deleting content type container 2017-03-30 10:35:41 +02:00
Mads Rasmussen ed3096642d Merge pull request #1844 from ryanology/temp-U4-9697
U4-9697 - Listview create new node ordering
2017-03-30 10:31:51 +02:00
Emil Wangaa d51082f651 Bumps version 2017-03-30 10:27:54 +02:00
Stephan f2fb275b34 Fix post-merge issues 2017-03-30 09:58:27 +02:00
Stephan 95508c4fb7 Upgrade nuspec accordingly 2017-03-30 09:32:22 +02:00
Stephan 4677faff38 Upgrade to ModelsBuilder 3.0.6 2017-03-30 08:54:01 +02:00
Shannon c5f388f6bc Merge remote-tracking branch 'origin/dev-v7' into dev-v7.6
# Conflicts:
#	build/NuSpecs/UmbracoCms.Core.nuspec
#	src/Umbraco.Tests/packages.config
#	src/Umbraco.Web/Umbraco.Web.csproj
#	src/Umbraco.Web/packages.config
#	src/UmbracoExamine/UmbracoExamine.csproj
#	src/umbraco.MacroEngines/packages.config
#	src/umbraco.MacroEngines/umbraco.MacroEngines.csproj
2017-03-30 17:03:51 +11:00
Shannon 4419af427b Merge branch 'dev-v7.6' of https://github.com/umbraco/Umbraco-CMS into dev-v7.6 2017-03-30 17:02:04 +11:00
Shannon dbdee5fc2c U4-9655 Html Agility pack assembly binding needs to be updated via code, just in case 2017-03-30 17:01:30 +11:00
Shannon 725b3c5eca Merge branch 'dev-v7' into temp-U4-9691 2017-03-30 16:37:24 +11:00
Shannon 25f5179b29 updates nuspec 2017-03-30 16:36:54 +11:00
Shannon bf6d084f82 Merge branch 'dev-v7' into temp-U4-9691 2017-03-30 15:50:16 +11:00
Shannon 1a03bd9624 Logs an error if the index is rebuilding due to being corrupt 2017-03-30 15:49:45 +11:00
Shannon 6a1d60c5a7 U4-9692 Update to Examine 0.1.82 2017-03-30 15:43:06 +11:00
Shannon 4fef17190f adds notes 2017-03-30 11:03:07 +11:00
rrueckl 08ca75bb35 U4-9697 - Listview create new node ordering 2017-03-29 13:59:23 -04:00
Warren Buckley 143b9c605b Merge pull request #1841 from umbraco/temp-CON-1296
Adds support for loading uninitialized trees in the treepicker
2017-03-29 13:31:44 +01:00
Niels Hartvig d76a0271e9 Adds missing config element 2017-03-29 14:05:09 +02:00
Niels Hartvig 5deb483b94 U4-9694 Add support for specifying custom login background photo 2017-03-29 14:04:45 +02:00
Emil Wangaa db809f30fe Reverted hideHeader value to true in treepicker.controller.js - should not have been changed 2017-03-29 14:00:36 +02:00
Claus dcb50d10c4 Merge pull request #1842 from umbraco/temp-U4-9685
fixes: U4-9685 Disable picking folders in the partial view picker
2017-03-29 13:28:33 +02:00
Niels Hartvig a409b8b0f7 Adds server side support for configuring a background photo for login screen 2017-03-29 12:49:06 +02:00
Shannon 0512eaa7fd Fixes the Examine mgmt dashboard to look better and to detect if an index is unreadable in which case it allows you to rebuild it. 2017-03-29 21:43:00 +11:00
Mads Rasmussen a91a67ed8d fixes: U4-9685 Disable picking folders in the partial view picker 2017-03-29 11:37:30 +02:00
Claus e8df5f9eb4 U4-9689 Content type description isn't always saved the same way
also fixed for member types (and added test for media types also using the ContentTypeService)
2017-03-29 11:08:57 +02:00
Mads Rasmussen af1257d4ae update UI on login screen 2017-03-29 10:22:52 +02:00
Shannon 1f3e568a0d fixes merge issues 2017-03-29 19:11:55 +11:00
Stephan c46678c766 uaasscrum-827 - more robust umbraco.config 2017-03-29 10:03:02 +02:00
Shannon cb539e82d0 Merge remote-tracking branch 'origin/dev-v7' into dev-v7.6
# Conflicts:
#	build/UmbracoVersion.txt
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
#	src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs
#	src/UmbracoExamine/UmbracoMemberIndexer.cs
2017-03-29 18:11:51 +11:00
Shannon Deminick 1432d602ba Merge pull request #1838 from umbraco/temp-u4-9665
u4-9665
2017-03-29 18:06:28 +11:00
Shannon 841d2a7010 ensure change tracking is turned off on the dialog so the warning doesn't pop up 2017-03-29 17:51:31 +11:00
Shannon 7cdb48b6c9 bumps version 2017-03-29 16:35:37 +11:00
Shannon Deminick a667058422 Merge pull request #1828 from umbraco/temp-u4-9655
U4-9655 - update HtmlAgilityPack version in config
2017-03-29 16:33:37 +11:00
Shannon Deminick 4ffa6bb41b Merge pull request #1824 from umbraco/temp-u4-9617
U4-9617 - perf for published date
2017-03-29 16:29:31 +11:00
Shannon 77af16db55 Merge branch 'dev-v7' into temp-u4-9617
# Conflicts:
#	src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
2017-03-29 16:29:18 +11:00
Emil Wangaa 2a44b73056 Adds support for loading uninitialized trees in the treepicker - is needed for CON-1296 to work 2017-03-28 21:19:12 +02:00
Stephan 85d85fa587 Merge pull request #1819 from umbraco/temp-u4-9623
U4-9323 - fix DataTypeDefinitionRepository prevalues cache
2017-03-28 17:37:04 +02:00
Stephan bd27ed739d Merge pull request #1810 from umbraco/temp-U4-9633
Fixes: U4-9633 Update the offline dashboard to new content and styles
2017-03-28 17:28:47 +02:00
Stephan 3938868115 U4-9665 - create partial view macro with file 2017-03-28 17:22:18 +02:00
Claus 140792430f Merge pull request #1823 from umbraco/temp-U4-9647
fixes: U4-9647 7.6.0-beta: New template editor not set $dirty on code…
2017-03-28 15:15:43 +02:00
Claus c04cf1fe2e Merge pull request #1822 from umbraco/temp-U4-9654
fixes: U4-9654 7.6.0-beta: Legacy icons are not resolved in new listv…
2017-03-28 14:32:48 +02:00
Claus d1d83c84a0 fixes icons on listviews. 2017-03-28 14:27:05 +02:00
Claus 98acc50e13 Merge pull request #1830 from abryukhov/patch-7
Adding new UI keys for v7.6 features
2017-03-28 13:56:46 +02:00
Claus 1a0a02463e Merge pull request #1835 from umbraco/temp-U4-9680
fixes: U4-9680 The font change has made the tiny editor boxes a littl…
2017-03-28 13:53:23 +02:00
Claus 96c499a47e Merge pull request #1833 from umbraco/temp-U4-9679
fixes: U4-9679 Inserting partial views in the new template editor is …
2017-03-28 13:46:24 +02:00
Claus f7e8aefeab Merge pull request #1834 from umbraco/temp-u4-9666
U4-9666 - hide deprecated prop editors for macro params
2017-03-28 13:38:42 +02:00
Claus dfa803293f Merge pull request #1826 from umbraco/temp-U4-9671
Fixes: U4-9671 Fix failing client side unit tests for the content picker and template editor
2017-03-28 13:23:55 +02:00
Claus 7ade64f855 Merge pull request #1802 from umbraco/temp-U4-9637
U4-9637 addDashboardSection package action shouldn't add the dashboar…
2017-03-28 13:12:26 +02:00
Shannon Deminick 346e8dcaf0 Merge pull request #1820 from umbraco/temp-u4-9615
U4-9615 - implement way to find listviews in path fast
2017-03-28 16:05:25 +11:00
Shannon ddfd07bf4a Fixes count query 2017-03-28 16:04:06 +11:00
Shannon a9fe46da0c makes HasContainerInPath public 2017-03-28 15:55:45 +11:00
Shannon aca1f0d186 Adds comments 2017-03-28 15:46:33 +11:00
Shannon 9eb415d398 U4-9682 Repository's have a double nested DeepCloneRuntimeCacheProvider set which means all entities are double deep cloned in and out of the cache and ensures that PreValueCollections are not also manually deep cloned. 2017-03-28 15:41:55 +11:00
Shannon 8f6b728534 Moves paging value to a constant 2017-03-28 13:37:10 +11:00
Shannon Deminick 2e0c09ab39 Merge pull request #1827 from umbraco/temp-u4-9598
U4-9598 - fix paging in UmbracoContentIndexer
2017-03-28 13:31:37 +11:00
Shannon Deminick f211344786 Merge pull request #1825 from umbraco/temp-u4-9604
U4-9604 - fix current HttpContext in ManyObjectsResolverBase
2017-03-28 13:11:09 +11:00
Mads Rasmussen f8764cdd20 fixes: U4-9680 The font change has made the tiny editor boxes a little to small. 2017-03-27 13:05:46 +02:00
Stephan 1d17bfd59a U4-9666 - hide deprecated prop editors for macro params 2017-03-27 12:25:58 +02:00
Mads Rasmussen 98ad6ad366 fixes: U4-9679 Inserting partial views in the new template editor is broken 2017-03-27 11:27:58 +02:00
Stephan 68702b98f5 U4-9604 - add nullcheck 2017-03-27 08:52:10 +02:00
Stephan f93caf277b Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into temp-u4-9604 2017-03-27 08:47:40 +02:00
Shannon Deminick 32db674397 Merge pull request #1813 from umbraco/temp-U4-9645
Fixes: U4-9645 RTE link dialogs should use the new picker dialog
2017-03-27 14:25:07 +11:00
Shannon Deminick e0a7698780 Merge pull request #1821 from andyneil/dev-v7-lang-fixes
Dev v7 lang fixes
2017-03-27 14:20:41 +11:00
Shannon Deminick 783c74d3ba Merge pull request #1829 from abryukhov/patch-6
Adding missing keys before v7.6
2017-03-27 14:12:08 +11:00
Alexander Bryukhov 96d7bc3898 Adding new UI keys for v7.6 features 2017-03-24 22:10:09 +07:00
Alexander Bryukhov 21963c03a2 Adding missing keys before v7.6 2017-03-24 21:59:02 +07:00
Stephan a2a9794fdb U4-9655 - update HtmlAgilityPack version in config 2017-03-24 14:47:27 +01:00
Stephan 879a132077 U4-9598 - fix paging in UmbracoContentIndexer 2017-03-24 13:05:06 +01:00
Mads Rasmussen 9650d314c6 fix failing unit tests for template editor 2017-03-24 11:35:44 +01:00
Mads Rasmussen fcc0c452bb add mock for getEntitiesByIds POST request 2017-03-24 11:34:08 +01:00
Stephan 606ebcae92 U4-9604 - fix current HttpContext in ManyObjectsResolverBase 2017-03-24 11:07:15 +01:00
Stephan af10ae9e34 U4-9617 - fix 2017-03-23 18:00:58 +01:00
Stephan a23c150738 U4-9617 - fix 2017-03-23 17:51:30 +01:00
Stephan 085a678266 U4-9617 - perf for published date 2017-03-23 17:44:07 +01:00
Mads Rasmussen c73fb6144b fixes: U4-9647 7.6.0-beta: New template editor not set $dirty on code change 2017-03-23 16:31:50 +01:00
mikkelhm bfd201efcc Bump version to 7.6-Beta5 2017-03-23 15:46:18 +01:00
Mads Rasmussen 5a2b4f031b fixes: U4-9654 7.6.0-beta: Legacy icons are not resolved in new listview picker 2017-03-23 15:00:30 +01:00
andyneil cf7cafeb4c Update wording to be more grammatically correct 2017-03-23 13:41:48 +00:00
andyneil 870657affa Update wording to be more grammatically correct 2017-03-23 13:41:23 +00:00
Stephan fe11d4770d U4-9615 - implement way to find listviews in path fast 2017-03-23 14:07:45 +01:00
Mads Rasmussen ac75d8148d fix color on tree header checkmark 2017-03-23 11:46:51 +01:00
Mads Rasmussen 4a32cddf08 make tree search box full width 2017-03-23 11:37:13 +01:00
Mads Rasmussen 7461e7c55b align styling of error and success messages for content (move/copy) and media (move) 2017-03-23 11:36:51 +01:00
Stephan c8fe9030c7 U4-9323 - fix DataTypeDefinitionRepository prevalues cache 2017-03-23 10:39:28 +01:00
Shannon 2ae236e98d Adds xml transform for partial view tree types 2017-03-23 18:48:41 +11:00
Shannon 802fb95784 Fixes issue with renaming PartialViewMacro and PartialViewTree controller names - this also fixes an issue that we were looking up these types over and over again and now we just do it once. 2017-03-23 18:44:28 +11:00
Shannon 0297fdb32f Fixes a bunch of the JS unit tests 2017-03-23 13:19:37 +11:00
Shannon Deminick 5bede4bf9f Merge pull request #1816 from umbraco/temp-u4-9664
u4-9664 - Enables HasAccess on the MediaTreeController to use a udi for checkin…
2017-03-23 12:54:11 +11:00
Shannon d37106576d Adds null checks to the ContentTreeController too 2017-03-23 12:53:48 +11:00
Shannon ed0f0f7942 Merge remote-tracking branch 'origin/dev-v7' into dev-v7.6
# Conflicts:
#	src/Umbraco.Core/Configuration/CoreDebug.cs
#	src/Umbraco.Core/Publishing/PublishingStrategy.cs
#	src/Umbraco.Core/Umbraco.Core.csproj
2017-03-23 12:24:16 +11:00
Shannon Deminick 3d81c73495 Merge pull request #1814 from umbraco/temp-u4-9658
U4-9658 - detect umbraco.config rogue content types, and fix
2017-03-23 12:16:10 +11:00
Shannon e7a540e717 Proper Exception handling 2017-03-23 12:15:14 +11:00
Shannon Deminick bb886c237e Merge pull request #1815 from umbraco/temp-u4-9610
U4-9610 - fix nullref in BulkPublishController
2017-03-23 11:28:03 +11:00
Shannon 6c1e271fa8 Fixes styling and fixing error message quotes to make it more clear 2017-03-23 11:27:46 +11:00
Shannon Deminick 4c1b807e4f Merge pull request #1812 from umbraco/temp-u4-6811
U4-6811 - fix preview set deletion
2017-03-23 11:06:33 +11:00
Shannon 3b22c0cdd7 Catches correct expected exception type, we'll log for other non expected errors. 2017-03-23 11:06:06 +11:00
mikkelhm 31d8f49d3b Enables HasAccess on the MediaTreeController to use a udi for checking access 2017-03-22 20:25:15 +01:00
Stephan 631404743f U4-9610 - fix nullref in BulkPublishController 2017-03-22 14:44:39 +01:00
Emil Wangaa 1e154e8bc9 Internal Beta04 version bump - needed for Forms 2017-03-22 14:32:35 +01:00
Stephan d5c9639170 U4-9658 - detect umbraco.config rogue content types, and fix 2017-03-22 13:58:40 +01:00
Mads Rasmussen b90cccbfff implement mini list view for media copy 2017-03-22 13:45:09 +01:00
Stephan 94b7c36d62 U4-6811 - fix preview set deletion 2017-03-22 12:16:33 +01:00
Mads Rasmussen 22f0641c54 implement mini list view for url picker 2017-03-22 11:58:11 +01:00
Mads Rasmussen e465a937c5 Implement mini list view for generic move overlay 2017-03-22 11:26:53 +01:00
Mads Rasmussen d2164bc94d Implement mini list view for generic copy overlay 2017-03-22 11:26:08 +01:00
Mads Rasmussen df9d09725b add entity helper so we don't have to hard code these values all over the place 2017-03-22 11:25:00 +01:00
Stephan 1ffdd1abd1 Merge pull request #1811 from umbraco/temp-U4-9660
U4-9660 EntityService is not using readonly uow where it could be
2017-03-22 11:20:29 +01:00
Claus a06de1b165 U4-9660 EntityService is not using readonly uow where it could be 2017-03-22 11:14:16 +01:00
Mads Rasmussen 0a56f46b12 Implement mini list view for content copy dialog 2017-03-22 10:44:55 +01:00
Mads Rasmussen 972f9b3546 implement mini list view for content move dialog 2017-03-22 10:43:10 +01:00
Shannon 0fd3af6828 Fixes release version of tinymceconfig 2017-03-22 18:32:28 +11:00
Shannon fafb207799 U4-8658 RTE Editor: Edit an existing image by clicking 'media picker' in toolbar, show a blank picker 2017-03-22 18:27:18 +11:00
Shannon b1aea424e8 U4-9659 Javascript error when inserting an image into the rich text editor from the media picker 2017-03-22 18:26:11 +11:00
Shannon Deminick 3598acaddc Merge pull request #1805 from umbraco/temp-u4-9644
u4-9644 fix local link selection in the rich text editor
2017-03-22 18:25:04 +11:00
Shannon 8e03a1ffca Updates tha a and img tags in the rte to use a data-udi attribute when udi's are used 2017-03-22 18:17:59 +11:00
Shannon Deminick ded8afa8fc Merge pull request #1808 from umbraco/temp-u4-9582
U4-9582
2017-03-22 13:56:54 +11:00
Mads Rasmussen dcd2b1eb6b Merge pull request #1807 from crgrieve/U4-9648
U4-9648 Remove the relevant query rather than the first one in list.
2017-03-21 19:59:57 +01:00
Stephan c04ef47be3 Merge pull request #1806 from umbraco/temp-u4-9640
U4-9640
2017-03-21 17:48:07 +01:00
Stephan 62f3c87e8a Merge remote-tracking branch 'origin/dev-v7.6' into temp-u4-9640 2017-03-21 17:12:29 +01:00
Stephan 1b9776ecfb Merge pull request #1800 from umbraco/temp-U4-9591
U4-9591 All PetaPoco Relators for 1:M mappings need to be reviewed to…
2017-03-21 16:52:12 +01:00
Warren Buckley 7b1efa718e Internal Beta03 version bump - needed for Forms for access to [FileUploadCleanupFilter] 2017-03-21 15:50:13 +00:00
Warren Buckley f60ad15f70 Marks Forms access to internals in Umbraco.Web assembly - needed for [FileUploadCleanupFilter] in Forms 2017-03-21 15:42:30 +00:00
Mads Rasmussen 28ab176466 Fixes: U4-9633 Update the offline dashboard to new content and styles 2017-03-21 15:28:55 +01:00
mikkelhm 3f3db006e7 When selecting a local link, also update the data-id to be the udi 2017-03-21 14:43:54 +01:00
Stephan 7801cdf9ff Merge remote-tracking branch 'origin/dev-v7.6' into temp-u4-9640 2017-03-21 13:14:18 +01:00
mikkelhm 836e1bba54 Revert "moves binding redirects to app pre init"
This reverts commit 5a953761b0.
2017-03-21 13:14:07 +01:00
mikkelhm de9c5b88ab Updates the legacy linkpicker to show udi links properly, i.e. translate them to nice internal urls 2017-03-21 11:48:50 +01:00
Stephan 77981f889f U4-9582 - perfs, cache converter prevalues 2017-03-21 11:10:52 +01:00
Stephan 0a132ed5ed U4-9582 - perfs, remove Yield method 2017-03-21 11:10:37 +01:00
Shannon 5a953761b0 moves binding redirects to app pre init 2017-03-21 20:41:07 +11:00
Shannon 27ee192c8f Fixes all the logic in the CodeFileController, propery null checking, proper handling of persisting everything including renames, removes code duplication 2017-03-21 18:39:45 +11:00
Shannon dfa58183c6 Fixes deleting partial view and script files 2017-03-21 18:38:54 +11:00
Shannon e8668f3ed4 Don't pass in a value for snippets if it's not there, it will show up as a "undefined" string otherwise, adds the redirect method to the contentEditingHelper 2017-03-21 18:38:32 +11:00
Shannon c84e3dac38 Adds notes, return false if the file is not actually deleted, adds test assertions 2017-03-21 18:37:46 +11:00
Shannon 72ab51ea60 Fixes angular file controllers to not sync the tree if an item is being created, redirects to the correct path if the file is renamed 2017-03-21 18:36:14 +11:00
Shannon 1bfb63fe86 Adds validation for file names 2017-03-21 18:35:13 +11:00
Shannon 2cf68ab263 dont' render files that are invalid (no name) 2017-03-21 18:30:39 +11:00
Shannon 215bc64a83 Fixes val-server directive since it wasn't picking up on ngModel changes 2017-03-21 18:20:22 +11:00
Shannon Deminick 1b17f4e9df Merge pull request #1804 from umbraco/temp-u4-9543
U4-9543 - fix shadow filesystem filter
2017-03-21 12:59:43 +11:00
Shannon 73f0b1992d Fixes up sorting when using relators 2017-03-21 12:37:35 +11:00
carole_grieve_eqtr 21f54dd4ff Remove the relevant query rather than the first one! 2017-03-20 17:55:48 +00:00
Stephan a5903ec419 U4-9640 - fix CodeFileController for scripts 2017-03-20 16:53:08 +01:00
Warren Buckley ac496b0cf6 Updates version to beta02 - after Warren forgot to merge & push AccessToInternals for Forms before public beta 2017-03-20 15:40:15 +00:00
Warren Buckley 6036136938 Merge branch 'dev-v7.6' of https://github.com/umbraco/Umbraco-CMS into dev-v7.6
# Conflicts:
#	build/UmbracoVersion.txt
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
2017-03-20 14:55:29 +00:00
Stephan a9c7a7a405 U4-9640 - use IFileSystem 2017-03-20 15:53:34 +01:00
mikkelhm ce8286dadd Sets the udi as well as the id when selecting a local link in the rich text editor 2017-03-20 15:53:32 +01:00
Claus 532b177d2e Merge pull request #1793 from Phosworks/U4-8418
Fixes jquery selector bug, http://issues.umbraco.org/issue/U4-8418
2017-03-20 14:43:43 +01:00
mikkelhm 504aac0350 Fixes variable names when selecting a local link in the rich text editor 2017-03-20 14:32:43 +01:00
Stephan 454aad2170 U4-9543 - fix shadow filesystem filter 2017-03-20 13:01:03 +01:00
Shannon fd0cb7da23 Merge remote-tracking branch 'refs/remotes/origin/dev-v7.6' into temp-U4-9591 2017-03-20 18:28:38 +11:00
Shannon 4093fd9b79 U4-9637 addDashboardSection package action shouldn't add the dashboard if it already exists 2017-03-18 16:52:30 +11:00
Shannon 3d6f91cbef Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-03-18 15:47:56 +11:00
Shannon fffd508bb2 missing null check 2017-03-18 15:44:57 +11:00
Sebastiaan Janssen f4eb37d44d Missing null check (for unit test) 2017-03-17 12:11:28 +01:00
Sebastiaan Janssen c79aaa9c48 Bumps version 2017-03-17 11:49:42 +01:00
Sebastiaan Janssen e3bc6f148a New installer background image 2017-03-17 11:35:15 +01:00
Warren Buckley a43bd13e6a Merge pull request #1798 from umbraco/temp-U4-9621
Fixes: U4-9621 More UI color tweaks
2017-03-16 15:31:30 +00:00
Warren Buckley 6aa00c52dc Merge branch 'dev-v7.6' of https://github.com/umbraco/Umbraco-CMS into dev-v7.6 2017-03-16 15:08:33 +00:00
Stephan 333b35d8b9 U4-9606 - hard cap of 8 minidump files 2017-03-16 15:51:19 +01:00
Mads Rasmussen 30d5bfa7b4 move nonode css to less file, update grunt build + update no node colors + font 2017-03-16 15:49:59 +01:00
Claus 890673a197 Merge pull request #1797 from umbraco/temp-u4-9606
U4-9606 - New DumpOnTimeoutThreadAbort debug option
2017-03-16 15:38:01 +01:00
Claus 6344ad28aa adding sqlsyntax. 2017-03-16 14:52:50 +01:00
Claus eadc3c8c5a U4-9591 All PetaPoco Relators for 1:M mappings need to be reviewed to ensure there is a correct sort being used 2017-03-16 14:45:59 +01:00
Stephan 9b8db111dd Merge pull request #1790 from umbraco/temp-U4-9611
U4-9611 Create Property Value Converters for all new UDI Property Edi…
2017-03-16 14:36:17 +01:00
Stephan 7b506fadc6 U4-9611 - minor fix 2017-03-16 14:35:54 +01:00
Stephan 27539d4aad U4-9606 - always minidump on Monitor.ReliableEnter exceptions 2017-03-16 14:04:28 +01:00
Claus 1ce44565a3 Merge pull request #1764 from umbraco/temp-u4-9462
U4-9462 units of work cleanup
2017-03-16 13:12:32 +01:00
Stephan e70e651901 U4-9462 - minor fix 2017-03-16 13:10:53 +01:00
Mads Rasmussen 00b0515fc1 Revert "less bright and "dangerous" alerts, notifications and validation messages"
This reverts commit 691c13d1e1.
2017-03-16 10:31:48 +01:00
Morten Christensen d8c04b1f67 Merge pull request #1799 from umbraco/temp-U4-9632
U4-9632 Ensure GUID generation on updated entity types in v7.6 is unique
2017-03-16 10:09:31 +01:00
Shannon 172ef8c379 U4-7093 If allowManuallyChangingPassword=false on new install, installation doesn't work 2017-03-16 18:59:06 +11:00
Claus 7e1f045c09 U4-9632 Ensure GUID generation on updated entity types in v7.6 is unique
removing unused using statements from other migrations.
2017-03-16 08:19:03 +01:00
Sebastiaan Janssen d2fdf7b647 Check if MediaPicker is configured as single or multiple and give back appropriate result for each (IPublishedContent vs IEnumerable<IPublishedContent>) 2017-03-15 23:22:53 +01:00
Sebastiaan Janssen e1942d96d0 Incorporate Stephane's feedback: if we already know we're getting list of int or udi, we don't need to cast, or even test for the PropertyEditorAlias 2017-03-15 23:22:53 +01:00
Stephan 496e6c1711 U4-9462 - missed one safeXml.AcceptChanges 2017-03-15 14:50:42 +01:00
Mads Rasmussen c9fc0fbed1 Update installer gray buttons to purple buttons + align label with input 2017-03-15 14:35:11 +01:00
Stephan 3121ea6111 Merge branch 'dev-v7.6' into temp-u4-9462 2017-03-15 13:48:27 +01:00
Stephan 59ecc6e109 Merge branch 'dev-v7.6' into temp-U4-9611 2017-03-15 13:00:07 +01:00
Stephan eb42b9a4b6 Merge pull request #1796 from umbraco/temp-U4-6566
U4-6566 Membership provider `useLegacyEncoding` should default to `false`
2017-03-15 12:37:09 +01:00
Stephan 82660cf6af Merge branch 'dev-v7.6' into temp-U4-9611 2017-03-15 12:10:27 +01:00
Stephan 54afd3d954 Fix failing test 2017-03-15 12:08:52 +01:00
Mads Rasmussen 9ee3471153 add font smoothing to installer 2017-03-15 10:38:42 +01:00
Mads Rasmussen 691c13d1e1 less bright and "dangerous" alerts, notifications and validation messages 2017-03-15 10:26:05 +01:00
Stephan f7f23015d0 U4-9606 - missing file 2017-03-15 09:39:35 +01:00
Stephan e432b7061d U4-9606 - New DumpOnTimeoutThreadAbort debug option 2017-03-14 19:02:33 +01:00
Sebastiaan Janssen 241ccf00a5 U4-6566 Membership provider useLegacyEncoding should default to false 2017-03-14 17:05:24 +01:00
Sebastiaan Janssen 1a0046df95 Merge pull request #1795 from umbraco/temp-U4-9498
U4-9498 LocalLinks as UDI
2017-03-14 15:54:03 +01:00
Sebastiaan Janssen a2ca753dd9 Use RelatedLink class instead of weird extra inline class, convert UDI values 2017-03-14 10:26:13 +01:00
Sebastiaan Janssen 6f516a15aa Boyscout cleanup 2017-03-14 10:25:10 +01:00
Sebastiaan Janssen 223ed41c53 Use the extension method to get published content item - consistent with other PVCs 2017-03-14 10:24:31 +01:00
Sebastiaan Janssen d2a3932626 Merge branch 'dev-v7.6' into temp-U4-9611 2017-03-14 10:22:39 +01:00
Shannon 0a3220df85 Fixes null check, adds another test case 2017-03-14 16:26:17 +11:00
Shannon 9a57f463ce Updates LocalLinks to be UDI, this will support both INT and UDI as LocalLink but when a new LocalLink is picked, it will use the UDI so eventually the INT will be gone 2017-03-14 15:31:30 +11:00
Mads Rasmussen fdfae0f78a increase font size for template insert description 2017-03-13 22:43:24 +01:00
Mads Rasmussen 9ebe7f683a increase font size for validation label 2017-03-13 22:40:12 +01:00
Mads Rasmussen 185af08e75 increase header description font-size 2017-03-13 21:02:43 +01:00
Mads Rasmussen 874c679bfe update tree header 2017-03-13 20:53:55 +01:00
Mads Rasmussen 76a6449ffa increase font size on actions menu 2017-03-13 20:47:36 +01:00
Mads Rasmussen fd8e200bd7 make property editor placeholder lighter + increase font size 2017-03-13 20:38:02 +01:00
Mads Rasmussen aa7e739b0e increase sections label font size 2017-03-13 20:09:44 +01:00
Mads Rasmussen 97f379ff44 add more contrast to placeholder text 2017-03-13 20:06:57 +01:00
Sebastiaan Janssen 3904f9c503 Centralized getting an IPublishedContent item from a Udi in a single extension method so that we're not repeating that code all over the place all the time 2017-03-13 15:49:15 +01:00
Wincent fc92d40b3a Fixes jquery selector bug, http://issues.umbraco.org/issue/U4-8418 2017-03-13 11:25:02 +01:00
Sebastiaan Janssen 89c84676dd U4-9611 Create Property Value Converters for all new UDI Property Editors 2017-03-11 16:44:57 +01:00
Stephan 6439e2fdd0 Merge dev-v7.6 into temp-u4-9462 2017-03-09 15:29:26 +01:00
Stephan 5027757760 Merge branch dev-v7 into temp-faster-startup-less-scanning 2017-03-06 08:50:29 +01:00
Stephan d4d040d9ec More PluginManager TLC 2017-03-05 11:43:36 +01:00
Stephan 4f1b76f5ff More IDiscoverable 2017-03-05 11:28:37 +01:00
Stephan 3b3eda5bfc PluginManager TLC 2017-03-05 11:28:22 +01:00
Stephan becc07c2bd More PluginManager cleanup 2017-03-03 13:26:20 +01:00
Stephan 5841377431 Merge branch 'dev-v7' into temp-faster-startup-less-scanning 2017-03-02 16:04:03 +01:00
Shannon 5d69ec2391 missed one 2017-02-28 23:23:58 +01:00
Shannon 9f9b4d2e84 Changes all relevant scannable plugin types to implement a base marker interface so we only scan one time 2017-02-28 23:12:48 +01:00
Stephan 4d24e7bef8 U4-9462 - more units of work cleanup 2017-02-21 13:19:58 +01:00
Stephan 8d5f7af780 U4-9462 - cleanup file unit of work 2017-02-21 13:19:58 +01:00
Stephan 08c8b84a10 U4-9462 - cleanup units of work, code, fixmes 2017-02-21 13:19:58 +01:00
324 changed files with 6716 additions and 5043 deletions
+1 -1
View File
@@ -33,7 +33,7 @@
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
<dependency id="Examine" version="[0.1.81, 1.0.0)" />
<dependency id="Examine" version="[0.1.82, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.5.2, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.8.2, 5.0.0)" />
<dependency id="semver" version="[2.0.4, 3.0.0)" />
+1 -1
View File
@@ -17,7 +17,7 @@
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.5, 4.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.6, 4.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
</dependencies>
+2 -2
View File
@@ -58,7 +58,7 @@
<httpRuntime xdt:Transform="InsertIfMissing" />
<httpRuntime maxRequestLength="51200" fcnMode="Single" xdt:Transform="SetAttributes(fcnMode,maxRequestLength)" />
<httpRuntime targetFramework="4.5" xdt:Locator="Condition(count(@targetFramework) != 1)" xdt:Transform="SetAttributes(targetFramework)" />
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
<roleManager defaultProvider="DefaultRoleProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
@@ -337,7 +337,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.9.0" newVersion="1.4.9.0" />
<bindingRedirect oldVersion="0.0.0.0-1.4.9.5" newVersion="1.4.9.5" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
+17 -7
View File
@@ -34,10 +34,15 @@
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" 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()" />
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.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
@@ -84,9 +89,14 @@
<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="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="python"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
+1 -1
View File
@@ -1,3 +1,3 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.6.0
alpha075
RC
+1 -1
View File
@@ -12,4 +12,4 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.6.0")]
[assembly: AssemblyInformationalVersion("7.6.0-alpha075")]
[assembly: AssemblyInformationalVersion("7.6.0-RC")]
+3 -3
View File
@@ -1,8 +1,6 @@
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;
@@ -163,7 +161,9 @@ namespace Umbraco.Core
/// </summary>
public static ApplicationContext Current { get; internal set; }
// fixme
/// <summary>
/// Gets the scope provider.
/// </summary>
internal IScopeProvider ScopeProvider { get { return _databaseContext == null ? null : _databaseContext.ScopeProvider; } }
/// <summary>
+12 -4
View File
@@ -17,9 +17,12 @@ namespace Umbraco.Core
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=null", RegexOptions.Compiled);
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=null");
private const string Log4NetReplacement = "log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
private static readonly Regex HtmlAgilityAssemblyPattern = new Regex("HtmlAgilityPack, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=bd319b19eaf3b43a");
private const string HtmlAgilityReplacement = "HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a";
/// <summary>
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
/// </summary>
@@ -28,13 +31,18 @@ namespace Umbraco.Core
/// <returns></returns>
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
//log4net:
// Use regex to match and replace
//log4net:
if (Log4NetAssemblyPattern.IsMatch(args.Name) && args.Name != Log4NetReplacement)
{
return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
}
//HtmlAgility:
if (HtmlAgilityAssemblyPattern.IsMatch(args.Name) && args.Name != HtmlAgilityReplacement)
{
return Assembly.Load(HtmlAgilityAssemblyPattern.Replace(args.Name, HtmlAgilityReplacement));
}
//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
@@ -26,6 +26,9 @@ namespace Umbraco.Core.Cache
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
{
if (innerProvider.GetType() == typeof(DeepCloneRuntimeCacheProvider))
throw new InvalidOperationException("A " + typeof(DeepCloneRuntimeCacheProvider) + " cannot wrap another instance of " + typeof(DeepCloneRuntimeCacheProvider));
InnerProvider = innerProvider;
}
@@ -105,9 +108,11 @@ 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 out of the cache
return CheckCloneableAndTracksChanges(cached);
}
@@ -22,12 +22,12 @@ namespace Umbraco.Core.Cache
{
private static readonly TEntity[] EmptyEntities = new TEntity[0]; // const
private readonly RepositoryCachePolicyOptions _options;
public DefaultRepositoryCachePolicy(IRuntimeCacheProvider cache, RepositoryCachePolicyOptions options)
: base(cache)
{
{
if (options == null) throw new ArgumentNullException("options");
_options = options;
_options = options;
}
public override IRepositoryCachePolicy<TEntity, TId> Scoped(IRuntimeCacheProvider runtimeCache, IScope scope)
@@ -244,9 +244,7 @@ namespace Umbraco.Core.Cache
/// <inheritdoc />
public override void ClearAll()
{
// fixme the cache should NOT contain anything else so we can clean all, can't we?
Cache.ClearAllCache();
//Cache.ClearCacheByKeySearch(GetEntityTypeCacheKey());
}
}
}
@@ -18,10 +18,17 @@ namespace Umbraco.Core.Cache
// it is not *that* complicated but then RepositoryBase needs to have a TRepository generic
// type parameter and it all becomes convoluted - keeping it simple for the time being.
// fixme explain
/// <summary>
/// Creates a scoped version of this cache policy.
/// </summary>
/// <param name="runtimeCache">The global isolated runtime cache for this policy.</param>
/// <param name="scope">The scope.</param>
/// <remarks>When a policy is scoped, it means that it has been created with a scoped
/// isolated runtime cache, and now it needs to be wrapped into something that can apply
/// changes to the global isolated runtime cache.</remarks>
IRepositoryCachePolicy<TEntity, TId> Scoped(IRuntimeCacheProvider runtimeCache, IScope scope);
/// <summary>
/// <summary>
/// Gets an entity from the cache, else from the repository.
/// </summary>
/// <param name="id">The identifier.</param>
@@ -18,10 +18,14 @@ namespace Umbraco.Core.Configuration
{
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
LogUncompletedScopes = string.Equals("true", appSettings["Umbraco.CoreDebug.LogUncompletedScopes"], StringComparison.OrdinalIgnoreCase);
DumpOnTimeoutThreadAbort = string.Equals("true", appSettings["Umbraco.CoreDebug.DumpOnTimeoutThreadAbort"], StringComparison.OrdinalIgnoreCase);
}
// when true, Scope logs the stack trace for any scope that gets disposed without being completed.
// this helps troubleshooting rogue scopes that we forget to complete
public bool LogUncompletedScopes { get; private set; }
// when true, the Logger creates a minidump of w3wp in ~/App_Data/MiniDump whenever it logs
// an error due to a ThreadAbortException that is due to a timeout.
public bool DumpOnTimeoutThreadAbort { get; private set; }
}
}
@@ -183,6 +183,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return GetOptionalTextElement("EnablePropertyValueConverters", false); }
}
[ConfigurationProperty("loginBackgroundImage")]
internal InnerTextConfigurationElement<string> LoginBackgroundImage
{
get { return GetOptionalTextElement("loginBackgroundImage", string.Empty); }
}
string IContentSection.NotificationEmailAddress
{
get { return Notifications.NotificationEmailAddress; }
@@ -336,5 +342,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return EnablePropertyValueConverters; }
}
string IContentSection.LoginBackgroundImage
{
get { return LoginBackgroundImage; }
}
}
}
@@ -72,5 +72,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool EnablePropertyValueConverters { get; }
string LoginBackgroundImage { get; }
}
}
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
/// Gets the version comment (like beta or RC).
/// </summary>
/// <value>The version comment.</value>
public static string CurrentComment { get { return "alpha075"; } }
public static string CurrentComment { get { return "RC"; } }
// Get the version of the umbraco.dll by looking at a class in that dll
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
+10
View File
@@ -89,6 +89,11 @@ namespace Umbraco.Core
/// </summary>
public const string Media = "B796F64C-1F99-4FFB-B886-4BF4BC011A9C";
/// <summary>
/// Guid for a Document object.
/// </summary>
public static readonly Guid MediaGuid = new Guid(Media);
/// <summary>
/// Guid for the Media Recycle Bin.
/// </summary>
@@ -148,6 +153,11 @@ namespace Umbraco.Core
/// </summary>
public const string Template = "6FBDE604-4178-42CE-A10B-8A2600A2F07D";
/// <summary>
/// Guid for a Template object.
/// </summary>
public static readonly Guid TemplateTypeGuid = new Guid(Template);
/// <summary>
/// Guid for a Lock object.
/// </summary>
-1
View File
@@ -173,7 +173,6 @@ namespace Umbraco.Core
return new ServiceContext(
new RepositoryFactory(ApplicationCache, ProfilingLogger.Logger, dbContext.SqlSyntax, UmbracoConfig.For.UmbracoSettings()),
new PetaPocoUnitOfWorkProvider(scopeProvider),
new FileUnitOfWorkProvider(scopeProvider),
ApplicationCache,
ProfilingLogger.Logger,
msgFactory);
+5 -35
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlServerCe;
using System.IO;
@@ -34,7 +33,7 @@ namespace Umbraco.Core
private string _connectionString;
private string _providerName;
private DatabaseSchemaResult _result;
private DateTime? _connectionLastChecked = null;
private DateTime? _connectionLastChecked;
/// <summary>
/// The number of minutes to throttle the checks to CanConnect
@@ -99,10 +98,10 @@ namespace Umbraco.Core
SqlSyntaxContext.SqlSyntaxProvider = SqlSyntax;
var asDbFactory2 = factory as IDatabaseFactory2;
ScopeProvider = asDbFactory2 == null
? new ScopeProvider(new DatabaseFactoryWrapper(factory))
ScopeProvider = asDbFactory2 == null
? new ScopeProvider(new DatabaseFactoryWrapper(factory))
: new ScopeProvider(asDbFactory2);
_logger = logger;
_configured = true;
}
@@ -197,42 +196,13 @@ namespace Umbraco.Core
{
throw new InvalidOperationException("Cannot create a database instance, there is no available connection string");
}
return ScopeProvider.GetAmbientOrNoScope().Database;
//var scope = ScopeProvider.AmbientScope;
//return scope != null ? scope.Database : ScopeProvider.CreateNoScope().Database;
}
}
/// <summary>
/// Replaces the "ambient" database (if any) and by a new temp database.
/// </summary>
/// <remarks>
/// <para>The returned IDisposable *must* be diposed in order to properly dispose the temp database and
/// restore the original "ambient" database (if any).</para>
/// <para>This is to be used in background tasks to ensure that they have an "ambient" database which
/// will be properly removed from call context and does not interfere with anything else. In most case
/// it is not replacing anything, just temporarily installing a database in context.</para>
/// </remarks>
// fixme - this should just entirely be replaced by Scope?
/*
public virtual IDisposable UseSafeDatabase(bool force = false)
{
var factory = _factory as DefaultDatabaseFactory;
if (factory == null) throw new NotSupportedException();
if (DefaultDatabaseFactory.HasAmbientDatabase)
{
return force
? new UsingDatabase(DefaultDatabaseFactory.DetachAmbientDatabase(), factory.CreateDatabase())
: new UsingDatabase(null, null);
}
// create a new, temp, database (will be disposed with UsingDatabase)
return new UsingDatabase(null, factory.CreateDatabase());
}
*/
/// <summary>
/// Boolean indicating whether the database has been configured
/// </summary>
+2 -1
View File
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using umbraco.interfaces;
using Umbraco.Core;
namespace Umbraco.Core.Deploy
@@ -8,7 +9,7 @@ namespace Umbraco.Core.Deploy
/// <summary>
/// Connects to an Umbraco service.
/// </summary>
public interface IServiceConnector
public interface IServiceConnector : IDiscoverable
{
/// <summary>
/// Gets an artifact.
+135
View File
@@ -0,0 +1,135 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using Umbraco.Core.IO;
namespace Umbraco.Core.Diagnostics
{
// taken from https://blogs.msdn.microsoft.com/dondu/2010/10/24/writing-minidumps-in-c/
// and https://blogs.msdn.microsoft.com/dondu/2010/10/31/writing-minidumps-from-exceptions-in-c/
// which itself got it from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/
internal static class MiniDump
{
private static readonly object LockO = new object();
[Flags]
public enum Option : uint
{
// From dbghelp.h:
Normal = 0x00000000,
WithDataSegs = 0x00000001,
WithFullMemory = 0x00000002,
WithHandleData = 0x00000004,
FilterMemory = 0x00000008,
ScanMemory = 0x00000010,
WithUnloadedModules = 0x00000020,
WithIndirectlyReferencedMemory = 0x00000040,
FilterModulePaths = 0x00000080,
WithProcessThreadData = 0x00000100,
WithPrivateReadWriteMemory = 0x00000200,
WithoutOptionalData = 0x00000400,
WithFullMemoryInfo = 0x00000800,
WithThreadInfo = 0x00001000,
WithCodeSegs = 0x00002000,
WithoutAuxiliaryState = 0x00004000,
WithFullAuxiliaryState = 0x00008000,
WithPrivateWriteCopyMemory = 0x00010000,
IgnoreInaccessibleMemory = 0x00020000,
ValidTypeFlags = 0x0003ffff,
}
//typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
// DWORD ThreadId;
// PEXCEPTION_POINTERS ExceptionPointers;
// BOOL ClientPointers;
//} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;
[StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
public struct MiniDumpExceptionInformation
{
public uint ThreadId;
public IntPtr ExceptionPointers;
[MarshalAs(UnmanagedType.Bool)]
public bool ClientPointers;
}
//BOOL
//WINAPI
//MiniDumpWriteDump(
// __in HANDLE hProcess,
// __in DWORD ProcessId,
// __in HANDLE hFile,
// __in MINIDUMP_TYPE DumpType,
// __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
// __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
// __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam
// );
// Overload requiring MiniDumpExceptionInformation
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);
// Overload supporting MiniDumpExceptionInformation == NULL
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);
[DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
private static extern uint GetCurrentThreadId();
private static bool Write(SafeHandle fileHandle, Option options, bool withException = false)
{
var currentProcess = Process.GetCurrentProcess();
var currentProcessHandle = currentProcess.Handle;
var currentProcessId = (uint)currentProcess.Id;
MiniDumpExceptionInformation exp;
exp.ThreadId = GetCurrentThreadId();
exp.ClientPointers = false;
exp.ExceptionPointers = IntPtr.Zero;
if (withException)
exp.ExceptionPointers = Marshal.GetExceptionPointers();
var bRet = exp.ExceptionPointers == IntPtr.Zero
? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
: MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, ref exp, IntPtr.Zero, IntPtr.Zero);
return bRet;
}
public static bool Dump(Option options = Option.WithFullMemory, bool withException = false)
{
lock (LockO)
{
// work around "stack trace is not available while minidump debugging",
// by making sure a local var (that we can inspect) contains the stack trace.
// getting the call stack before it is unwound would require a special exception
// filter everywhere in our code = not!
var stacktrace = withException ? Environment.StackTrace : string.Empty;
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
if (Directory.Exists(filepath) == false)
Directory.CreateDirectory(filepath);
var filename = Path.Combine(filepath, string.Format("{0:yyyyMMddTHHmmss}.{1}.dmp", DateTime.UtcNow, Guid.NewGuid().ToString("N").Substring(0, 4)));
using (var stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Write))
{
return Write(stream.SafeFileHandle, options, withException);
}
}
}
public static bool OkToDump()
{
lock (LockO)
{
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
if (Directory.Exists(filepath) == false) return true;
var count = Directory.GetFiles(filepath, "*.dmp").Length;
return count < 8;
}
}
}
}
-17
View File
@@ -295,22 +295,5 @@ namespace Umbraco.Core
return list1Groups.Count == list2Groups.Count
&& list1Groups.All(g => g.Count() == list2Groups[g.Key].Count());
}
///<summary>
/// Returns the items of the given enumerable as a pure enumerable.
/// <remarks>
/// When quering lists using methods such as <see cref="M:List.Where"/>, the result, despite appearing to look like and quack like an
/// <see cref="T:Enumerable{T}"/> the type is actually an instance of <see cref="T:System.Linq.Enumerable.WhereEnumerableIterator"/>
/// </remarks>
/// </summary>
///<param name="source">The item to find.</param>
///<returns>The index of the first matching item, or -1 if the item was not found.</returns>
internal static IEnumerable<T> Yield<T>(this IEnumerable<T> source)
{
foreach (var element in source)
{
yield return element;
}
}
}
}
@@ -16,13 +16,17 @@ namespace Umbraco.Core.Events
protected override void ScopeExitCompleted()
{
// fixme - we'd need to de-duplicate events somehow, etc - and the deduplication should be last in wins
// processing only the last instance of each event...
// this is probably far from perfect, because if eg a content is saved in a list
// and then as a single content, the two events will probably not be de-duplicated,
// but it's better than nothing
foreach (var e in GetEvents(EventDefinitionFilter.All))
foreach (var e in GetEvents(EventDefinitionFilter.LastIn))
{
e.RaiseEvent();
// fixme - not sure I like doing it here - but then where? how?
// separating concerns means that this should probably not be here,
// but then where should it be (without making things too complicated)?
var delete = e.Args as IDeletingMediaFilesEventArgs;
if (delete != null && delete.MediaFilesToDelete.Count > 0)
MediaFileSystem.DeleteMediaFiles(delete.MediaFilesToDelete);
@@ -35,13 +39,7 @@ namespace Umbraco.Core.Events
{
get
{
if (_mediaFileSystem != null) return _mediaFileSystem;
// fixme - insane! reading config goes cross AppDomain and serializes context?
using (new SafeCallContext())
{
return _mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem;
}
return _mediaFileSystem ?? (_mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem);
}
}
}
@@ -45,7 +45,8 @@ namespace Umbraco.Core.IO
private IScopeProviderInternal ScopeProvider
{
// fixme - 'course this is bad, but enough for now
// this is bad, but enough for now, and we'll refactor
// in v8 when we'll get rid of this class' singleton
// beware: means that we capture the "current" scope provider - take care in tests!
get { return ApplicationContext.Current == null ? null : ApplicationContext.Current.ScopeProvider as IScopeProviderInternal; }
}
+28 -49
View File
@@ -31,6 +31,7 @@ namespace Umbraco.Core.IO
private long _folderCounter;
private bool _folderCounterInitialized;
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
private static readonly Dictionary<int, string> DefaultSizes = new Dictionary<int, string>
{
{ 100, "thumb" },
@@ -263,7 +264,7 @@ namespace Umbraco.Core.IO
var filename = Path.GetFileName(sourcepath);
var filepath = GetMediaPath(filename, content.Key, propertyType.Key);
this.CopyFile(sourcepath, filepath);
CopyThumbnails(sourcepath, filepath);
return filepath;
}
@@ -302,7 +303,7 @@ namespace Umbraco.Core.IO
{
var property = GetProperty(content, propertyTypeAlias);
var svalue = property.Value as string;
var oldpath = svalue == null ? null : GetRelativePath(svalue); // FIXME DELETE?
var oldpath = svalue == null ? null : GetRelativePath(svalue);
if (string.IsNullOrWhiteSpace(oldpath) == false && oldpath != filepath)
DeleteFile(oldpath, true);
property.Value = GetUrl(filepath);
@@ -312,29 +313,17 @@ namespace Umbraco.Core.IO
}
}
// sets a file for the FileUpload property editor
// ie generates thumbnails and populates autofill properties
/// <summary>
/// Sets a file for the FileUpload property editor and populates autofill properties
/// </summary>
/// <param name="content"></param>
/// <param name="property"></param>
/// <param name="filepath"></param>
/// <param name="filestream"></param>
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream)
{
// check if file is an image (and supports resizing and thumbnails etc)
var extension = Path.GetExtension(filepath);
var isImage = IsImageFile(extension);
// specific stuff for images (thumbnails etc)
if (isImage)
{
using (var image = Image.FromStream(filestream))
{
// use one image for all
GenerateThumbnails(image, filepath, property.PropertyType);
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, image);
}
}
else
{
// will use filepath for extension, and filestream for length
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
}
{
// will use filepath for extension, and filestream for length
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
}
#endregion
@@ -401,6 +390,7 @@ namespace Umbraco.Core.IO
// note: this does not find 'custom' thumbnails?
// will find _thumb and _big-thumb but NOT _custom?
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<string> GetThumbnails(string path)
{
var parentDirectory = Path.GetDirectoryName(path);
@@ -421,12 +411,14 @@ namespace Umbraco.Core.IO
DeleteThumbnails(path);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public void DeleteThumbnails(string path)
{
GetThumbnails(path)
.ForEach(x => base.DeleteFile(x));
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public void CopyThumbnails(string sourcePath, string targetPath)
{
var targetPathBase = Path.GetDirectoryName(targetPath) ?? "";
@@ -466,27 +458,6 @@ namespace Umbraco.Core.IO
var dir = Path.GetDirectoryName(file);
DeleteDirectory(dir, true);
}
// I don't even understand...
/*
var relativeFilePath = GetRelativePath(file); // fixme - should be relative already
if (FileExists(relativeFilePath) == false) return;
var parentDirectory = Path.GetDirectoryName(relativeFilePath);
// don't want to delete the media folder if not using directories.
if (_contentSection.UploadAllowDirectories && parentDirectory != GetRelativePath("/"))
{
//issue U4-771: if there is a parent directory the recursive parameter should be true
DeleteDirectory(parentDirectory, string.IsNullOrEmpty(parentDirectory) == false);
}
else
{
DeleteFile(file, true);
}
*/
}
catch (Exception e)
{
@@ -500,6 +471,7 @@ namespace Umbraco.Core.IO
#region GenerateThumbnails
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<ResizedImage> GenerateThumbnails(
Image image,
string filepath,
@@ -521,6 +493,7 @@ namespace Umbraco.Core.IO
return GenerateThumbnails(image, filepath, additionalSizes);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<ResizedImage> GenerateThumbnails(
Image image,
string filepath,
@@ -543,19 +516,21 @@ namespace Umbraco.Core.IO
.ToList(); // now
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<ResizedImage> GenerateThumbnails(
Stream filestream,
string filepath,
PropertyType propertyType)
{
// get the original image from the original stream
if (filestream.CanSeek) filestream.Seek(0, 0); // fixme - what if we cannot seek?
if (filestream.CanSeek) filestream.Seek(0, 0);
using (var image = Image.FromStream(filestream))
{
return GenerateThumbnails(image, filepath, propertyType);
}
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<ResizedImage> GenerateThumbnails(
Image image,
string filepath,
@@ -577,16 +552,19 @@ namespace Umbraco.Core.IO
#region GenerateResized - Generate at resized filepath derived from origin filepath
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight)
{
return GenerateResized(originImage, originFilepath, sizeName, maxWidthHeight, -1, -1);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int fixedWidth, int fixedHeight)
{
return GenerateResized(originImage, originFilepath, sizeName, -1, fixedWidth, fixedHeight);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight, int fixedWidth, int fixedHeight)
{
if (string.IsNullOrWhiteSpace(sizeName))
@@ -602,16 +580,19 @@ namespace Umbraco.Core.IO
#region GenerateResizedAt - Generate at specified resized filepath
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight)
{
return GenerateResizedAt(originImage, resizedFilepath, maxWidthHeight, -1, -1);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResizedAt(Image originImage, int fixedWidth, int fixedHeight, string resizedFilepath)
{
return GenerateResizedAt(originImage, resizedFilepath, -1, fixedWidth, fixedHeight);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight, int fixedWidth, int fixedHeight)
{
// target dimensions
@@ -658,9 +639,6 @@ namespace Umbraco.Core.IO
var rect = new Rectangle(0, 0, width, height);
graphics.DrawImage(originImage, rect, 0, 0, originImage.Width, originImage.Height, GraphicsUnit.Pixel);
// copy metadata
// fixme - er... no?
// get an encoder - based upon the file type
var extension = (Path.GetExtension(resizedFilepath) ?? "").TrimStart('.').ToLowerInvariant();
var encoders = ImageCodecInfo.GetImageEncoders();
@@ -723,6 +701,7 @@ namespace Umbraco.Core.IO
#region Inner classes
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public class ResizedImage
{
public ResizedImage()
+6 -2
View File
@@ -155,7 +155,9 @@ namespace Umbraco.Core.IO
if (directory == null) throw new InvalidOperationException("Could not get directory.");
Directory.CreateDirectory(directory); // ensure it exists
if (stream.CanSeek) // fixme - what else?
// if can seek, be safe and go back to start, else...
// hope that the stream hasn't been read already
if (stream.CanSeek)
stream.Seek(0, 0);
using (var destination = (Stream) File.Create(fullPath))
@@ -286,7 +288,9 @@ namespace Umbraco.Core.IO
var opath = path;
path = EnsureDirectorySeparatorChar(path);
// fixme - this part should go!
// TODO in v8 this should be cleaned up
// the first part should probably removed
// not sure what we are doing here - so if input starts with a (back) slash,
// we assume it's not a FS relative path and we try to convert it... but it
// really makes little sense?
+59 -26
View File
@@ -218,11 +218,11 @@ namespace Umbraco.Core.IO
var normPath = NormPath(path);
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
var files = filter != null ? _fs.GetFiles(path, filter) : _fs.GetFiles(path);
var regexFilter = FilterToRegex(filter);
var wildcard = filter == null ? null : new WildcardExpression(filter);
return files
.Except(shadows.Where(kvp => (kvp.Value.IsFile && kvp.Value.IsDelete) || kvp.Value.IsDir)
.Select(kvp => kvp.Key))
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist && FilterByRegex(kvp.Key, regexFilter)).Select(kvp => kvp.Key))
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist && (wildcard == null || wildcard.IsMatch(kvp.Key))).Select(kvp => kvp.Key))
.Distinct();
}
@@ -326,32 +326,65 @@ namespace Umbraco.Core.IO
_sfs.AddFile(path, physicalPath, overrideIfExists, copy);
Nodes[normPath] = new ShadowNode(false, false);
}
/// <summary>
/// Helper function for filtering keys by Regex if a filter is specified.
/// </summary>
/// <param name="input"></param>
/// <param name="regexFilter"></param>
/// <returns></returns>
internal static bool FilterByRegex(string input, string regexFilter)
{
if (regexFilter == null) return true;
return regexFilter != string.Empty && Regex.IsMatch(input, regexFilter);
}
/// <summary>
/// Transforms a filter pattern into a Regex pattern
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
/// <remarks>
/// Appending '$' only if not containing wildcard is stupid and broken.
/// It is however what seems to be what they're doing in .NET so we need to match the functionality.
/// </remarks>
internal static string FilterToRegex(string pattern)
// copied from System.Web.Util.Wildcard internal
internal class WildcardExpression
{
if (pattern == null) return null;
return "^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace("\\?", ".") + (pattern.Contains("*") ? string.Empty : "$");
private readonly string _pattern;
private readonly bool _caseInsensitive;
private Regex _regex;
private static Regex metaRegex = new Regex("[\\+\\{\\\\\\[\\|\\(\\)\\.\\^\\$]");
private static Regex questRegex = new Regex("\\?");
private static Regex starRegex = new Regex("\\*");
private static Regex commaRegex = new Regex(",");
private static Regex slashRegex = new Regex("(?=/)");
private static Regex backslashRegex = new Regex("(?=[\\\\:])");
public WildcardExpression(string pattern, bool caseInsensitive = true)
{
_pattern = pattern;
_caseInsensitive = caseInsensitive;
}
private void EnsureRegex(string pattern)
{
if (_regex != null) return;
var options = RegexOptions.None;
// match right-to-left (for speed) if the pattern starts with a *
if (pattern.Length > 0 && pattern[0] == '*')
options = RegexOptions.RightToLeft | RegexOptions.Singleline;
else
options = RegexOptions.Singleline;
// case insensitivity
if (_caseInsensitive)
options |= RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;
// Remove regex metacharacters
pattern = metaRegex.Replace(pattern, "\\$0");
// Replace wildcard metacharacters with regex codes
pattern = questRegex.Replace(pattern, ".");
pattern = starRegex.Replace(pattern, ".*");
pattern = commaRegex.Replace(pattern, "\\z|\\A");
// anchor the pattern at beginning and end, and return the regex
_regex = new Regex("\\A" + pattern + "\\z", options);
}
public bool IsMatch(string input)
{
EnsureRegex(_pattern);
return _regex.IsMatch(input);
}
}
}
}
+39 -5
View File
@@ -7,6 +7,8 @@ using System.Threading;
using System.Web;
using log4net;
using log4net.Config;
using Umbraco.Core.Configuration;
using Umbraco.Core.Diagnostics;
namespace Umbraco.Core.Logging
{
@@ -57,23 +59,55 @@ namespace Umbraco.Core.Logging
internal ILog LoggerFor(object getTypeFromInstance)
{
if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance");
return LogManager.GetLogger(getTypeFromInstance.GetType());
}
public void Error(Type callingType, string message, Exception exception)
{
var logger = LogManager.GetLogger(callingType);
if (logger == null) return;
var dump = false;
if (IsTimeoutThreadAbortException(exception))
{
message += "\r\nThe thread has been aborted, because the request has timed out.";
// dump if configured, or if stacktrace contains Monitor.ReliableEnter
dump = UmbracoConfig.For.CoreDebug().DumpOnTimeoutThreadAbort || IsMonitorEnterThreadAbortException(exception);
// dump if it is ok to dump (might have a cap on number of dump...)
dump &= MiniDump.OkToDump();
}
logger.Error(message, exception);
if (dump)
{
try
{
var dumped = MiniDump.Dump(withException: true);
message += dumped
? "\r\nA minidump was created in App_Data/MiniDump"
: "\r\nFailed to create a minidump";
}
catch (Exception e)
{
message += string.Format("\r\nFailed to create a minidump ({0}: {1})", e.GetType().FullName, e.Message);
}
}
logger.Error(message, exception);
}
private static bool IsMonitorEnterThreadAbortException(Exception exception)
{
var abort = exception as ThreadAbortException;
if (abort == null) return false;
var stacktrace = abort.StackTrace;
return stacktrace.Contains("System.Threading.Monitor.ReliableEnter");
}
private static bool IsTimeoutThreadAbortException(Exception exception)
{
var abort = exception as ThreadAbortException;
@@ -105,7 +139,7 @@ namespace Umbraco.Core.Logging
if (showHttpTrace && HttpContext.Current != null)
{
HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()));
}
}
var logger = LogManager.GetLogger(callingType);
if (logger == null || logger.IsWarnEnabled == false) return;
@@ -122,7 +156,7 @@ namespace Umbraco.Core.Logging
var logger = LogManager.GetLogger(callingType);
if (logger == null || logger.IsWarnEnabled == false) return;
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
}
/// <summary>
+8 -2
View File
@@ -1,8 +1,14 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Media
{
public interface IImageUrlProvider
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
// PluginManager is asked to find types implementing this interface it will fall back
// to a complete scan.
[Obsolete("IImageUrlProvider is no longer used and will be removed in future versions")]
public interface IImageUrlProvider // IDiscoverable
{
string Name { get; }
string GetImageUrlFromMedia(int mediaId, IDictionary<string, string> parameters);
+9 -2
View File
@@ -1,6 +1,13 @@
namespace Umbraco.Core.Media
using System;
namespace Umbraco.Core.Media
{
public interface IThumbnailProvider
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
// PluginManager is asked to find types implementing this interface it will fall back
// to a complete scan.
[Obsolete("Thumbnails are generated by ImageProcessor, use that instead")]
public interface IThumbnailProvider // : IDiscoverable
{
bool CanProvideThumbnail(string fileUrl);
string GetThumbnailUrl(string fileUrl);
@@ -96,8 +96,7 @@ namespace Umbraco.Core.Media
/// <param name="propertyTypeAlias">The property type alias.</param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
/// <param name="filestream">The stream containing the file data.</param>
/// <param name="image">The file data as an image object.</param>
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream, Image image = null)
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream)
{
if (content == null) throw new ArgumentNullException("content");
if (propertyTypeAlias == null) throw new ArgumentNullException("propertyTypeAlias");
@@ -110,7 +109,7 @@ namespace Umbraco.Core.Media
if (autoFillConfig == null) return; // nothing
// populate
Populate(content, autoFillConfig, filepath, filestream, image);
Populate(content, autoFillConfig, filepath, filestream);
}
/// <summary>
@@ -158,8 +157,7 @@ namespace Umbraco.Core.Media
/// <param name="autoFillConfig"></param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
/// <param name="filestream">The stream containing the file data.</param>
/// <param name="image">The file data as an image object.</param>
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream, Image image = null)
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream)
{
if (content == null) throw new ArgumentNullException("content");
if (autoFillConfig == null) throw new ArgumentNullException("autoFillConfig");
@@ -172,11 +170,7 @@ namespace Umbraco.Core.Media
else
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
Size? size;
if (image == null)
size = _mediaFileSystem.IsImageFile(extension) ? (Size?) _mediaFileSystem.GetDimensions(filestream) : null;
else
size = new Size(image.Width, image.Height);
var size = _mediaFileSystem.IsImageFile(extension) ? (Size?)_mediaFileSystem.GetDimensions(filestream) : null;
SetProperties(content, autoFillConfig, size, filestream.Length, extension);
}
}
+54 -4
View File
@@ -1,5 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Models
{
@@ -84,16 +86,64 @@ namespace Umbraco.Core.Models
public string Type { get; set; }
private Type _runtimeType;
/// <summary>
/// Returns the CLR type based on it's assembly name stored in the config
/// </summary>
/// <returns></returns>
public Type GetRuntimeType()
{
return _runtimeType ?? (_runtimeType = System.Type.GetType(Type));
}
if (_runtimeType != null)
return _runtimeType;
_runtimeType = TryGetType(Type);
return _runtimeType;
}
/// <summary>
/// Used to try to get and cache the tree type
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
internal static Type TryGetType(string type)
{
try
{
return ResolvedTypes.GetOrAdd(type, s =>
{
var result = System.Type.GetType(type);
if (result != null)
{
return result;
}
//we need to implement a bit of a hack here due to some trees being renamed and backwards compat
var parts = type.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 2)
{
if (parts[1].Trim() == "umbraco" && parts[0].StartsWith("Umbraco.Web.Trees") && parts[0].EndsWith("Controller") == false)
{
//if it's one of our controllers but it's not suffixed with "Controller" then add it and try again
var tempType = parts[0] + "Controller, umbraco";
result = System.Type.GetType(tempType);
if (result != null)
{
return result;
}
}
}
throw new InvalidOperationException("Could not resolve type");
});
}
catch (InvalidOperationException)
{
//swallow, this is our own exception, couldn't find the type
return null;
}
}
private static readonly ConcurrentDictionary<string, Type> ResolvedTypes = new ConcurrentDictionary<string, Type>();
}
}
+3
View File
@@ -274,6 +274,9 @@ namespace Umbraco.Core.Models
/// </summary>
public bool HasPublishedVersion { get { return PublishedVersionGuid != default(Guid); } }
[IgnoreDataMember]
internal DateTime PublishedDate { get; set; }
/// <summary>
/// Changes the Trashed state of the content object
/// </summary>
+12 -13
View File
@@ -7,7 +7,6 @@ using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.IO;
using Umbraco.Core.Media;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
@@ -42,7 +41,7 @@ namespace Umbraco.Core.Models
/// * The item exists and is published
/// * A call to ContentService.Save is made
/// * The item has not been modified whatsoever apart from changing it's published status from published to saved
///
///
/// In this case, there is no reason to make any database changes at all
/// </remarks>
internal static bool RequiresSaving(this IContent entity)
@@ -62,7 +61,7 @@ namespace Umbraco.Core.Models
/// * The item exists and is published
/// * A call to ContentService.Save is made
/// * The item has not been modified whatsoever apart from changing it's published status from published to saved
///
///
/// In this case, there is no reason to make any database changes at all
/// </remarks>
internal static bool RequiresSaving(this IContent entity, PublishedState publishedState)
@@ -70,7 +69,7 @@ namespace Umbraco.Core.Models
var publishedChanged = entity.IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished;
//check if any user prop has changed
var propertyValueChanged = entity.IsAnyUserPropertyDirty();
//We need to know if any other property apart from Published was changed here
//don't create a new version if the published state has changed to 'Save' but no data has actually been changed
if (publishedChanged && entity.Published == false && propertyValueChanged == false)
@@ -302,9 +301,9 @@ namespace Umbraco.Core.Models
return content.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Contains(recycleBinId.ToInvariantString());
}
/// <summary>
/// Removes characters that are not valide XML characters from all entity properties
/// Removes characters that are not valide XML characters from all entity properties
/// of type string. See: http://stackoverflow.com/a/961504/5018
/// </summary>
/// <returns></returns>
@@ -456,7 +455,7 @@ namespace Umbraco.Core.Models
/// <param name="value">The uploaded <see cref="HttpPostedFileBase"/>.</param>
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value)
{
// ensure we get the filename without the path in IE in intranet mode
// ensure we get the filename without the path in IE in intranet mode
// http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie
var filename = value.FileName;
var pos = filename.LastIndexOf(@"\", StringComparison.InvariantCulture);
@@ -468,10 +467,10 @@ namespace Umbraco.Core.Models
if (pos > 0)
filename = filename.Substring(pos + 1);
// get a safe filename - should this be done by MediaHelper?
// get a safe & clean filename
filename = IOHelper.SafeFileName(filename);
if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower(); // fixme - er... why?
filename = filename.ToLower();
FileSystemProviderManager.Current.MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, value.InputStream);
}
@@ -513,10 +512,10 @@ namespace Umbraco.Core.Models
{
if (filename == null || filestream == null) return;
// get a safe filename - should this be done by MediaHelper?
// get a safe & clean filename
filename = IOHelper.SafeFileName(filename);
if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower(); // fixme - er... why?
filename = filename.ToLower();
FileSystemProviderManager.Current.MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream);
}
@@ -548,7 +547,7 @@ namespace Umbraco.Core.Models
#endregion
#region User/Profile methods
/// <summary>
/// Gets the <see cref="IProfile"/> for the Creator of this media item.
/// </summary>
@@ -623,7 +622,7 @@ namespace Umbraco.Core.Models
///// <param name="tagGroup"></param>
///// <returns></returns>
///// <remarks>
///// The tags returned are only relavent for published content & saved media or members
///// The tags returned are only relavent for published content & saved media or members
///// </remarks>
//public static IEnumerable<ITag> GetTags(this IContentBase content, string propertyTypeAlias, string tagGroup = "default")
//{
@@ -1,85 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Services;
namespace Umbraco.Core.Models
{
//fixme: This whole thing needs to go, it's super hacky and doens't need to exist in the first place
internal static class ContentTypeExtensions
{
/// <summary>
/// Get all descendant content types
/// </summary>
/// <param name="contentType"></param>
/// <param name="contentTypeService"></param>
/// <returns></returns>
public static IEnumerable<IContentTypeBase> Descendants(this IContentTypeBase contentType, IContentTypeService contentTypeService)
{
if (contentType is IContentType)
{
var descendants = contentTypeService.GetContentTypeChildren(contentType.Id)
.SelectRecursive(type => contentTypeService.GetContentTypeChildren(type.Id));
return descendants;
}
if (contentType is IMediaType)
{
var descendants = contentTypeService.GetMediaTypeChildren(contentType.Id)
.SelectRecursive(type => contentTypeService.GetMediaTypeChildren(type.Id));
return descendants;
}
//No other content types have children (i.e. member types)
return Enumerable.Empty<IContentTypeBase>();
}
/// <summary>
/// Get all descendant content types
/// </summary>
/// <param name="contentType"></param>
/// <param name="contentTypeService"></param>
/// <returns></returns>
public static IEnumerable<IContentTypeBase> Descendants(this IContentTypeBase contentType, ContentTypeServiceBase contentTypeService)
{
var cService = contentTypeService as IContentTypeService;
return cService == null ? Enumerable.Empty<IContentTypeBase>() : contentType.Descendants(cService);
}
/// <summary>
/// Get all descendant and self content types
/// </summary>
/// <param name="contentType"></param>
/// <param name="contentTypeService"></param>
/// <returns></returns>
public static IEnumerable<IContentTypeBase> DescendantsAndSelf(this IContentTypeBase contentType, IContentTypeService contentTypeService)
{
var descendantsAndSelf = new[] { contentType }.Concat(contentType.Descendants(contentTypeService));
return descendantsAndSelf;
}
/// <summary>
/// Get all descendant and self content types
/// </summary>
/// <param name="contentType"></param>
/// <param name="contentTypeService"></param>
/// <returns></returns>
public static IEnumerable<IContentTypeBase> DescendantsAndSelf(this IContentTypeBase contentType, ContentTypeServiceBase contentTypeService)
{
var descendantsAndSelf = new[] { contentType }.Concat(contentType.Descendants(contentTypeService));
return descendantsAndSelf;
}
///// <summary>
///// Returns the descendant content type Ids for the given content type
///// </summary>
///// <param name="contentType"></param>
///// <returns></returns>
//public static IEnumerable<int> DescendantIds(this IContentTypeBase contentType)
//{
// return ((ContentTypeService) ApplicationContext.Current.Services.ContentTypeService)
// .GetDescendantContentTypeIds(contentType.Id);
//}
}
}
+4 -1
View File
@@ -49,7 +49,10 @@ namespace Umbraco.Core.Models
return path
.Replace('\\', System.IO.Path.DirectorySeparatorChar)
.Replace('/', System.IO.Path.DirectorySeparatorChar);
//.TrimStart(System.IO.Path.DirectorySeparatorChar);
//Don't strip the start - this was a bug fixed in 7.3, see ScriptRepositoryTests.PathTests
//.TrimStart(System.IO.Path.DirectorySeparatorChar)
//.TrimStart('/');
}
/// <summary>
@@ -179,7 +179,7 @@ namespace Umbraco.Core.Models.PublishedContent
}
if (contentType == null)
throw new Exception(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
throw new InvalidOperationException(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
itemType.ToString().ToLower(), alias));
return new PublishedContentType(contentType);
@@ -19,5 +19,8 @@ namespace Umbraco.Core.Models.Rdbms
[Column("newest")]
public bool Newest { get; set; }
[Column("updateDate")]
public DateTime VersionDate { get; set; }
}
}
@@ -22,6 +22,7 @@ namespace Umbraco.Core.ObjectResolution
private readonly string _httpContextKey;
private readonly List<Type> _instanceTypes = new List<Type>();
private IEnumerable<TResolved> _sortedValues;
private readonly Func<HttpContextBase> _httpContextGetter;
private int _defaultPluginWeight = 100;
@@ -42,12 +43,7 @@ namespace Umbraco.Core.ObjectResolution
if (logger == null) throw new ArgumentNullException("logger");
CanResolveBeforeFrozen = false;
if (scope == ObjectLifetimeScope.HttpRequest)
{
if (HttpContext.Current == null)
throw new InvalidOperationException("Use alternative constructor accepting a HttpContextBase object in order to set the lifetime scope to HttpRequest when HttpContext.Current is null");
CurrentHttpContext = new HttpContextWrapper(HttpContext.Current);
}
_httpContextGetter = () => new HttpContextWrapper(HttpContext.Current);
ServiceProvider = serviceProvider;
Logger = logger;
@@ -84,7 +80,7 @@ namespace Umbraco.Core.ObjectResolution
LifetimeScope = ObjectLifetimeScope.HttpRequest;
_httpContextKey = GetType().FullName;
ServiceProvider = serviceProvider;
CurrentHttpContext = httpContext;
_httpContextGetter = () => httpContext;
_instanceTypes = new List<Type>();
InitializeAppInstances();
@@ -160,7 +156,16 @@ namespace Umbraco.Core.ObjectResolution
/// Gets or sets the <see cref="HttpContextBase"/> used to initialize this object, if any.
/// </summary>
/// <remarks>If not null, then <c>LifetimeScope</c> will be <c>ObjectLifetimeScope.HttpRequest</c>.</remarks>
protected HttpContextBase CurrentHttpContext { get; private set; }
protected HttpContextBase CurrentHttpContext
{
get
{
var context = _httpContextGetter == null ? null : _httpContextGetter();
if (context == null)
throw new InvalidOperationException("Cannot use this resolver with lifetime 'HttpRequest' when there is no current HttpContext. Either use the ctor accepting an HttpContextBase, or use the resolver from within a request exclusively.");
return context;
}
}
/// <summary>
/// Returns the service provider used to instantiate objects
@@ -196,7 +201,7 @@ namespace Umbraco.Core.ObjectResolution
/// <summary>
/// Gets or sets the default type weight.
/// </summary>
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
/// them, when calling <c>GetSortedValues</c>.</remarks>
protected virtual int DefaultPluginWeight
{
@@ -276,7 +281,7 @@ namespace Umbraco.Core.ObjectResolution
/// Removes a type.
/// </summary>
/// <param name="value">The type to remove.</param>
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
/// the type is not a valid type for the resolver.</exception>
public virtual void RemoveType(Type value)
{
@@ -296,7 +301,7 @@ namespace Umbraco.Core.ObjectResolution
/// Removes a type.
/// </summary>
/// <typeparam name="T">The type to remove.</typeparam>
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
/// the type is not a valid type for the resolver.</exception>
public void RemoveType<T>()
where T : TResolved
@@ -309,7 +314,7 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <param name="types">The types to add.</param>
/// <remarks>The types are appended at the end of the list.</remarks>
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// a type is not a valid type for the resolver, or a type is already in the collection of types.</exception>
protected void AddTypes(IEnumerable<Type> types)
{
@@ -336,7 +341,7 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <param name="value">The type to add.</param>
/// <remarks>The type is appended at the end of the list.</remarks>
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
public virtual void AddType(Type value)
{
@@ -362,7 +367,7 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <typeparam name="T">The type to add.</typeparam>
/// <remarks>The type is appended at the end of the list.</remarks>
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
public void AddType<T>()
where T : TResolved
@@ -404,7 +409,7 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <param name="index">The zero-based index at which the type should be inserted.</param>
/// <param name="value">The type to insert.</param>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
public virtual void InsertType(int index, Type value)
@@ -430,7 +435,7 @@ namespace Umbraco.Core.ObjectResolution
/// Inserts a type at the beginning of the list.
/// </summary>
/// <param name="value">The type to insert.</param>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
public virtual void InsertType(Type value)
{
@@ -464,7 +469,7 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <param name="existingType">The existing type before which to insert.</param>
/// <param name="value">The type to insert.</param>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
/// or the new type is already in the collection of types.</exception>
public virtual void InsertTypeBefore(Type existingType, Type value)
@@ -498,7 +503,7 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <typeparam name="TExisting">The existing type before which to insert.</typeparam>
/// <typeparam name="T">The type to insert.</typeparam>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
/// or the new type is already in the collection of types.</exception>
public void InsertTypeBefore<TExisting, T>()
@@ -63,49 +63,6 @@ namespace Umbraco.Core.ObjectResolution
}
}
// NOTE - the ugly code below exists only because of umbraco.BusinessLogic.Actions.Action.ReRegisterActionsAndHandlers
// which wants to re-register actions and handlers instead of properly restarting the application. Don't even think
// about using it for anything else. Also, while the backdoor is open, the resolution system is locked so nothing
// can work properly => deadlocks. Therefore, open the backdoor, do resolution changes EXCLUSIVELY, and close the door!
/// <summary>
/// Returns a disposable object that reprents dirty access to temporarily unfrozen resolution configuration.
/// </summary>
/// <remarks>
/// <para>Should not be used.</para>
/// <para>Should be used in a <c>using(Resolution.DirtyBackdoorToConfiguration) { ... }</c> mode.</para>
/// <para>Because we just lift the frozen state, and we don't actually re-freeze, the <c>Frozen</c> event does not trigger.</para>
/// </remarks>
internal static IDisposable DirtyBackdoorToConfiguration
{
get { return new DirtyBackdoor(); }
}
// keep the class here because it needs write-access to Resolution.IsFrozen
private class DirtyBackdoor : IDisposable
{
private readonly IDisposable _lock;
private readonly bool _frozen;
public DirtyBackdoor()
{
LogHelper.Debug(typeof(DirtyBackdoor), "Creating back door for resolution");
_lock = new WriteLock(ConfigurationLock);
_frozen = _isFrozen;
_isFrozen = false;
}
public void Dispose()
{
LogHelper.Debug(typeof(DirtyBackdoor), "Disposing back door for resolution");
_isFrozen = _frozen;
_lock.Dispose();
}
}
/// <summary>
/// Freezes resolution.
/// </summary>
@@ -72,6 +72,9 @@ namespace Umbraco.Core.Persistence.Factories
content.PublishedVersionGuid = publishedDto == null
? (dto.DocumentPublishedReadOnlyDto == null ? default(Guid) : dto.DocumentPublishedReadOnlyDto.VersionId)
: publishedDto.VersionId;
content.PublishedDate = publishedDto == null
? (dto.DocumentPublishedReadOnlyDto == null ? default(DateTime) : dto.DocumentPublishedReadOnlyDto.VersionDate)
: publishedDto.VersionDate;
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
@@ -2,11 +2,12 @@
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
using umbraco.interfaces;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Mappers
{
public abstract class BaseMapper
public abstract class BaseMapper : IDiscoverable
{
private readonly ISqlSyntaxProvider _sqlSyntax;
@@ -1,9 +1,11 @@
namespace Umbraco.Core.Persistence.Migrations
using umbraco.interfaces;
namespace Umbraco.Core.Persistence.Migrations
{
/// <summary>
/// Marker interface for database migrations
/// </summary>
public interface IMigration
public interface IMigration : IDiscoverable
{
void Up();
void Down();
@@ -1,6 +1,5 @@
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
@@ -1,6 +1,5 @@
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
@@ -1,6 +1,5 @@
using System;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -44,7 +43,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
private static string UpdateMacroGuids(Database database)
{
var updates = database.Query<dynamic>("SELECT id, macroAlias FROM cmsMacro")
.Select(macro => Tuple.Create((int) macro.id, ((string) macro.macroAlias).ToGuid()))
.Select(macro => Tuple.Create((int) macro.id, ("macro____" + (string) macro.macroAlias).ToGuid()))
.ToList();
foreach (var update in updates)
@@ -58,7 +57,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
var updates = database.Query<dynamic>(@"SELECT cmsMacroProperty.id id, macroPropertyAlias propertyAlias, cmsMacro.macroAlias macroAlias
FROM cmsMacroProperty
JOIN cmsMacro ON cmsMacroProperty.macro=cmsMacro.id")
.Select(prop => Tuple.Create((int) prop.id, ((string) prop.macroAlias + "____" + (string) prop.propertyAlias).ToGuid()))
.Select(prop => Tuple.Create((int) prop.id, ("macro____" + (string) prop.macroAlias + "____" + (string) prop.propertyAlias).ToGuid()))
.ToList();
foreach (var update in updates)
@@ -1,6 +1,5 @@
using System;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -32,7 +31,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
private static string UpdateRelationTypeGuids(Database database)
{
var updates = database.Query<dynamic>("SELECT id, alias, name FROM umbracoRelationType")
.Select(relationType => Tuple.Create((int) relationType.id, ((string) relationType.alias + "____" + (string) relationType.name).ToGuid()))
.Select(relationType => Tuple.Create((int) relationType.id, ("relationType____" + (string) relationType.alias + "____" + (string) relationType.name).ToGuid()))
.ToList();
foreach (var update in updates)
@@ -1,5 +1,4 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -513,11 +513,13 @@ namespace Umbraco.Core.Persistence.Repositories
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
{
VersionId = dto.VersionId,
VersionDate = dto.UpdateDate,
Newest = true,
NodeId = dto.NodeId,
Published = true
Published = true
};
((Content)entity).PublishedVersionGuid = dto.VersionId;
((Content) entity).PublishedVersionGuid = dto.VersionId;
((Content) entity).PublishedDate = dto.UpdateDate;
}
entity.ResetDirtyProperties();
@@ -688,22 +690,26 @@ namespace Umbraco.Core.Persistence.Repositories
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
{
VersionId = dto.VersionId,
VersionDate = dto.UpdateDate,
Newest = true,
NodeId = dto.NodeId,
Published = true
};
((Content)entity).PublishedVersionGuid = dto.VersionId;
((Content) entity).PublishedVersionGuid = dto.VersionId;
((Content) entity).PublishedDate = dto.UpdateDate;
}
else if (publishedStateChanged)
{
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
{
VersionId = default(Guid),
VersionId = default (Guid),
VersionDate = default (DateTime),
Newest = false,
NodeId = dto.NodeId,
Published = false
};
((Content)entity).PublishedVersionGuid = default(Guid);
((Content) entity).PublishedVersionGuid = default(Guid);
((Content) entity).PublishedDate = default (DateTime);
}
entity.ResetDirtyProperties();
@@ -975,7 +981,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
}
//order by update date DESC, if there is corrupted published flags we only want the latest!
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.newest
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.updateDate, cmsDocument.newest
FROM cmsDocument INNER JOIN cmsContentVersion ON cmsContentVersion.VersionId = cmsDocument.versionId
WHERE cmsDocument.published = 1 AND cmsDocument.nodeId IN
(" + parsedOriginalSql + @")
@@ -101,7 +101,8 @@ namespace Umbraco.Core.Persistence.Repositories
var translator = new SqlTranslator<PropertyType>(sqlClause, query);
var sql = translator.Translate()
.OrderBy<PropertyTypeDto>(x => x.PropertyTypeGroupId, SqlSyntax);
//must be sorted this way for the relator to work
.OrderBy<PropertyTypeGroupDto>(x => x.Id, SqlSyntax);
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
@@ -468,7 +469,8 @@ AND umbracoNode.id <> @id",
.LeftJoin<DataTypeDto>()
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
.Where<PropertyTypeGroupDto>(x => x.ContentTypeNodeId == id)
.OrderBy<PropertyTypeGroupDto>(x => x.Id);
//must be sorted this way for the relator to work
.OrderBy<PropertyTypeGroupDto>(x => x.Id, SqlSyntax);
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
@@ -1250,5 +1252,19 @@ WHERE cmsContentType." + aliasColumn + @" LIKE @pattern",
while (aliases.Contains(test = alias + i)) i++;
return test;
}
/// <summary>
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
/// </summary>
/// <param name="contentPath"></param>
/// <returns></returns>
public bool HasContainerInPath(string contentPath)
{
var ids = contentPath.Split(',').Select(int.Parse);
var sql = new Sql(@"SELECT COUNT(*) FROM cmsContentType
INNER JOIN cmsContent ON cmsContentType.nodeId=cmsContent.contentType
WHERE cmsContent.nodeId IN (@ids) AND cmsContentType.isContainer=@isContainer", new { ids, isContainer = true });
return Database.ExecuteScalar<int>(sql) > 0;
}
}
}
@@ -276,47 +276,33 @@ AND umbracoNode.id <> @id",
public PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId)
{
var cached = IsolatedCache.GetCacheItemsByKeySearch<PreValueCollection>(GetPrefixedCacheKey(dataTypeId));
if (cached != null && cached.Any())
{
//return from the cache, ensure it's a cloned result
return (PreValueCollection)cached.First().DeepClone();
}
return GetAndCachePreValueCollection(dataTypeId);
}
internal static string GetCacheKeyRegex(int preValueId)
{
return CacheKeys.DataTypePreValuesCacheKey + @"[-\d]+-([\d]*,)*" + preValueId + @"(?!\d)[,\d$]*";
var collection = GetCachedPreValueCollection(dataTypeId);
return collection;
}
/// <summary>
/// Gets a specific PreValue by its Id
/// </summary>
/// <param name="preValueId">Id of the PreValue to retrieve the value from</param>
/// <returns>PreValue as a string</returns>
public string GetPreValueAsString(int preValueId)
{
//We need to see if we can find the cached PreValueCollection based on the cache key above
var collections = IsolatedCache.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_");
var cached = IsolatedCache.GetCacheItemsByKeyExpression<PreValueCollection>(GetCacheKeyRegex(preValueId));
if (cached != null && cached.Any())
{
//return from the cache
var collection = cached.First();
var preVal = collection.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
return preVal.Value.Value;
}
var preValue = collections.SelectMany(x => x.FormatAsDictionary().Values).FirstOrDefault(x => x.Id == preValueId);
if (preValue != null)
return preValue.Value;
//go and find the data type id for the pre val id passed in
var dto = Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @preValueId", new { preValueId = preValueId });
var dto = Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @preValueId", new { preValueId });
if (dto == null)
{
return string.Empty;
}
// go cache the collection
var preVals = GetAndCachePreValueCollection(dto.DataTypeNodeId);
//return the single value for this id
var pv = preVals.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
return pv.Value.Value;
var collection = GetCachedPreValueCollection(dto.DataTypeNodeId);
if (collection == null)
return string.Empty;
preValue = collection.FormatAsDictionary().Values.FirstOrDefault(x => x.Id == preValueId);
return preValue == null ? string.Empty : preValue.Value;
}
public void AddOrUpdatePreValues(int dataTypeId, IDictionary<string, PreValue> values)
@@ -441,40 +427,28 @@ AND umbracoNode.id <> @id",
sortOrder++;
}
}
private string GetPrefixedCacheKey(int dataTypeId)
private static string GetPrefixedCacheKey(int dataTypeId)
{
return CacheKeys.DataTypePreValuesCacheKey + dataTypeId + "-";
return CacheKeys.DataTypePreValuesCacheKey + "_" + dataTypeId;
}
private PreValueCollection GetAndCachePreValueCollection(int dataTypeId)
private PreValueCollection GetCachedPreValueCollection(int datetypeId)
{
//go get the data
var dtos = Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = dataTypeId });
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value, x.SortOrder), x.Alias, x.SortOrder)).ToList();
var collection = PreValueConverter.ConvertToPreValuesCollection(list);
//now create the cache key, this needs to include all pre-value ids so that we can use this cached item in the GetPreValuesAsString method
//the key will be: "UmbracoPreValDATATYPEID-CSVOFPREVALIDS
var key = GetPrefixedCacheKey(dataTypeId)
+ string.Join(",", collection.FormatAsDictionary().Select(x => x.Value.Id).ToArray());
//store into cache
IsolatedCache.InsertCacheItem(key, () => collection,
//30 mins
new TimeSpan(0, 0, 30),
//sliding is true
true);
return collection;
var key = GetPrefixedCacheKey(datetypeId);
return IsolatedCache.GetCacheItem<PreValueCollection>(key, () =>
{
var dtos = Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = datetypeId });
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value, x.SortOrder), x.Alias, x.SortOrder)).ToList();
var collection = PreValueConverter.ConvertToPreValuesCollection(list);
return collection;
}, TimeSpan.FromMinutes(20), isSliding: true);
}
private string EnsureUniqueNodeName(string nodeName, int id = 0)
{
var sql = new Sql();
sql.Select("*")
@@ -575,7 +549,7 @@ AND umbracoNode.id <> @id",
}
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
// in reality there is no need to check the uniqueness of this alias because the only way that this code executes is
// in reality there is no need to check the uniqueness of this alias because the only way that this code executes is
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
// must have unique aliases by definition, so there is no need for this additional check
@@ -595,10 +569,10 @@ AND umbracoNode.id <> @id",
{
throw new InvalidOperationException("Cannot update a pre value for a data type that has no identity");
}
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
// this causes issues when sorting the pre-values (http://issues.umbraco.org/issue/U4-5670) but in reality
// there is no need to check the uniqueness of this alias because the only way that this code executes is
// there is no need to check the uniqueness of this alias because the only way that this code executes is
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
// must have unique aliases by definition, so there is no need for this additional check
@@ -613,7 +587,7 @@ AND umbracoNode.id <> @id",
Database.Update(dto);
}
}
internal static class PreValueConverter
@@ -41,6 +41,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
var sql = GetBaseQuery(false)
.Where(GetBaseWhereClause(), new { Id = id })
//must be sorted this way for the relator to work
.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
var dto = Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql).FirstOrDefault();
@@ -64,6 +65,9 @@ namespace Umbraco.Core.Persistence.Repositories
sql.Where("cmsDictionary.pk in (@ids)", new { ids = ids });
}
//must be sorted this way for the relator to work
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
.Select(dto => ConvertFromDto(dto));
}
@@ -73,6 +77,7 @@ namespace Umbraco.Core.Persistence.Repositories
var sqlClause = GetBaseQuery(false);
var translator = new SqlTranslator<IDictionaryItem>(sqlClause, query);
var sql = translator.Translate();
//must be sorted this way for the relator to work
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
@@ -94,9 +99,9 @@ namespace Umbraco.Core.Persistence.Repositories
else
{
sql.Select("*")
.From<DictionaryDto>(SqlSyntax)
.LeftJoin<LanguageTextDto>(SqlSyntax)
.On<DictionaryDto, LanguageTextDto>(SqlSyntax, left => left.UniqueId, right => right.UniqueId);
.From<DictionaryDto>(SqlSyntax)
.LeftJoin<LanguageTextDto>(SqlSyntax)
.On<DictionaryDto, LanguageTextDto>(SqlSyntax, left => left.UniqueId, right => right.UniqueId);
}
return sql;
}
@@ -270,6 +275,8 @@ namespace Umbraco.Core.Persistence.Repositories
var translator = new SqlTranslator<IDictionaryItem>(sqlClause, Query<IDictionaryItem>.Builder);
var sql = translator.Translate();
//must be sorted this way for the relator to work
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
@@ -297,6 +304,9 @@ namespace Umbraco.Core.Persistence.Repositories
protected override IEnumerable<DictionaryDto> PerformFetch(Sql sql)
{
//must be sorted this way for the relator to work
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql);
}
@@ -349,6 +359,9 @@ namespace Umbraco.Core.Persistence.Repositories
protected override IEnumerable<DictionaryDto> PerformFetch(Sql sql)
{
//must be sorted this way for the relator to work
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql);
}
@@ -8,6 +8,13 @@ namespace Umbraco.Core.Persistence.Repositories
{
public interface IContentTypeRepository : IContentTypeCompositionRepository<IContentType>
{
/// <summary>
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
/// </summary>
/// <param name="contentPath"></param>
/// <returns></returns>
bool HasContainerInPath(string contentPath);
/// <summary>
/// Gets all entities of the specified <see cref="PropertyType"/> query
/// </summary>
@@ -37,6 +37,9 @@ namespace Umbraco.Core.Persistence.Repositories
private IMacro GetBySql(Sql sql)
{
//must be sorted this way for the relator to work
sql.OrderBy<MacroDto>(x => x.Id, SqlSyntax);
var macroDto = Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql).FirstOrDefault();
if (macroDto == null)
return null;
@@ -68,7 +71,10 @@ namespace Umbraco.Core.Persistence.Repositories
private IEnumerable<IMacro> GetAllNoIds()
{
var sql = GetBaseQuery(false);
var sql = GetBaseQuery(false)
//must be sorted this way for the relator to work
.OrderBy<MacroDto>(x => x.Id, SqlSyntax);
return ConvertFromDtos(Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql))
.ToArray();// we don't want to re-iterate again!
}
@@ -92,6 +98,9 @@ namespace Umbraco.Core.Persistence.Repositories
var translator = new SqlTranslator<IMacro>(sqlClause, query);
var sql = translator.Translate();
//must be sorted this way for the relator to work
sql.OrderBy<MacroDto>(x => x.Id, SqlSyntax);
var dtos = Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql);
foreach (var dto in dtos)
@@ -114,13 +123,13 @@ namespace Umbraco.Core.Persistence.Repositories
return sql;
}
private static Sql GetBaseQuery()
private Sql GetBaseQuery()
{
var sql = new Sql();
sql.Select("*")
.From<MacroDto>()
.LeftJoin<MacroPropertyDto>()
.On<MacroDto, MacroPropertyDto>(left => left.Id, right => right.Macro);
.From<MacroDto>()
.LeftJoin<MacroPropertyDto>()
.On<MacroDto, MacroPropertyDto>(left => left.Id, right => right.Macro);
return sql;
}
@@ -46,7 +46,9 @@ namespace Umbraco.Core.Persistence.Repositories
var statement = string.Join(" OR ", ids.Select(x => string.Format("umbracoNode.id='{0}'", x)));
sql.Where(statement);
}
sql.OrderByDescending<NodeDto>(x => x.NodeId, SqlSyntax);
//must be sorted this way for the relator to work
sql.OrderBy<MemberTypeReadOnlyDto>(x => x.UniqueId, SqlSyntax);
var dtos =
Database.Fetch<MemberTypeReadOnlyDto, PropertyTypeReadOnlyDto, PropertyTypeGroupReadOnlyDto, MemberTypeReadOnlyDto>(
@@ -62,7 +64,8 @@ namespace Umbraco.Core.Persistence.Repositories
var subquery = translator.Translate();
var sql = GetBaseQuery(false)
.Append(new Sql("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments))
.OrderBy<NodeDto>(x => x.SortOrder, SqlSyntax);
//must be sorted this way for the relator to work
.OrderBy<MemberTypeReadOnlyDto>(x => x.UniqueId, SqlSyntax);
var dtos =
Database.Fetch<MemberTypeReadOnlyDto, PropertyTypeReadOnlyDto, PropertyTypeGroupReadOnlyDto, MemberTypeReadOnlyDto>(
@@ -31,7 +31,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
protected internal new IScopeUnitOfWork UnitOfWork
{
get { return (IScopeUnitOfWork)base.UnitOfWork; }
get { return base.UnitOfWork; }
}
protected UmbracoDatabase Database
@@ -75,10 +75,5 @@ namespace Umbraco.Core.Persistence.Repositories
Database.Execute(delete, new { Id = GetEntityId(entity) });
}
}
protected virtual TId GetEntityId(TEntity entity)
{
return (TId)(object)entity.Id;
}
}
}
@@ -40,7 +40,10 @@ namespace Umbraco.Core.Persistence.Repositories
}
var factory = new PublicAccessEntryFactory();
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
sql.OrderBy<AccessDto>(dto => dto.Id, SqlSyntax);
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
return dtos.Select(factory.BuildEntity);
}
@@ -52,7 +55,10 @@ namespace Umbraco.Core.Persistence.Repositories
var sql = translator.Translate();
var factory = new PublicAccessEntryFactory();
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
sql.OrderBy<AccessDto>(dto => dto.Id, SqlSyntax);
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
return dtos.Select(factory.BuildEntity);
}
@@ -63,9 +69,8 @@ namespace Umbraco.Core.Persistence.Repositories
sql.Select("*")
.From<AccessDto>(SqlSyntax)
.LeftJoin<AccessRuleDto>(SqlSyntax)
.On<AccessDto, AccessRuleDto>(SqlSyntax, left => left.Id, right => right.AccessId)
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
.OrderBy<AccessDto>(dto => dto.Id, SqlSyntax);
.On<AccessDto, AccessRuleDto>(SqlSyntax, left => left.Id, right => right.AccessId);
return sql;
}
@@ -13,10 +13,10 @@ namespace Umbraco.Core.Persistence.Repositories
{
internal abstract class RepositoryBase : DisposableObject
{
private readonly IUnitOfWork _work;
private readonly IScopeUnitOfWork _work;
private readonly CacheHelper _globalCache;
protected RepositoryBase(IUnitOfWork work, CacheHelper cache, ILogger logger)
protected RepositoryBase(IScopeUnitOfWork work, CacheHelper cache, ILogger logger)
{
if (work == null) throw new ArgumentNullException("work");
if (cache == null) throw new ArgumentNullException("cache");
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <summary>
/// Returns the Unit of Work added to the repository
/// </summary>
protected internal IUnitOfWork UnitOfWork
protected internal IScopeUnitOfWork UnitOfWork
{
get { return _work; }
}
@@ -76,7 +76,7 @@ namespace Umbraco.Core.Persistence.Repositories
internal abstract class RepositoryBase<TId, TEntity> : RepositoryBase, IRepositoryQueryable<TId, TEntity>, IUnitOfWorkRepository
where TEntity : class, IAggregateRoot
{
protected RepositoryBase(IUnitOfWork work, CacheHelper cache, ILogger logger)
protected RepositoryBase(IScopeUnitOfWork work, CacheHelper cache, ILogger logger)
: base(work, cache, logger)
{
}
@@ -102,7 +102,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
if (_isolatedCache != null) return _isolatedCache;
var scope = ((ScopeUnitOfWork) UnitOfWork).Scope; // fixme cast!
var scope = UnitOfWork.Scope;
IsolatedRuntimeCache provider;
switch (scope.RepositoryCacheMode)
{
@@ -179,14 +179,17 @@ namespace Umbraco.Core.Persistence.Repositories
if (GlobalCache == CacheHelper.NoCache)
return _cachePolicy = NoRepositoryCachePolicy<TEntity, TId>.Instance;
// create the cache policy using IsolatedCache which is either global
// or scoped depending on the repository cache mode for the current scope
_cachePolicy = CreateCachePolicy(IsolatedCache);
var scope = ((ScopeUnitOfWork) UnitOfWork).Scope; // fixme cast!
var scope = UnitOfWork.Scope;
switch (scope.RepositoryCacheMode)
{
case RepositoryCacheMode.Default:
break;
case RepositoryCacheMode.Scoped:
_cachePolicy = _cachePolicy.Scoped(GetIsolatedCache(GlobalCache.IsolatedRuntimeCache), scope);
var globalIsolatedCache = GetIsolatedCache(GlobalCache.IsolatedRuntimeCache);
_cachePolicy = _cachePolicy.Scoped(globalIsolatedCache, scope);
break;
default:
throw new Exception("oops: cache mode.");
@@ -21,7 +21,9 @@ namespace Umbraco.Core.Persistence.Repositories
: base(work, CacheHelper.NoCache, logger, sqlSyntax)
{
// managing the cache our own way (no policy etc)
// fixme - ServerRegistrationRepository does *not* implement scoped cache at the moment!
// note: this means that the ServerRegistrationRepository does *not* implement scoped cache,
// and this is because the repository is special and should not participate in scopes
// (cleanup in v8)
_globalCache = globalCache;
}
@@ -39,6 +39,8 @@ namespace Umbraco.Core.Persistence.Repositories
{
var sql = GetBaseQuery(false);
sql.Where(GetBaseWhereClause(), new { Id = id });
//must be sorted this way for the relator to work
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
var dto = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql).FirstOrDefault();
@@ -60,7 +62,10 @@ namespace Umbraco.Core.Persistence.Repositories
{
sql.Where("umbracoUser.id in (@ids)", new {ids = ids});
}
//must be sorted this way for the relator to work
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql))
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
}
@@ -71,6 +76,9 @@ namespace Umbraco.Core.Persistence.Repositories
var translator = new SqlTranslator<IUser>(sqlClause, query);
var sql = translator.Translate();
//must be sorted this way for the relator to work
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
var dtos = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql)
.DistinctBy(x => x.Id);
@@ -96,13 +104,13 @@ namespace Umbraco.Core.Persistence.Repositories
return sql;
}
private static Sql GetBaseQuery(string columns)
private Sql GetBaseQuery(string columns)
{
var sql = new Sql();
sql.Select(columns)
.From<UserDto>()
.LeftJoin<User2AppDto>()
.On<UserDto, User2AppDto>(left => left.Id, right => right.UserId);
.From<UserDto>()
.LeftJoin<User2AppDto>()
.On<UserDto, User2AppDto>(left => left.Id, right => right.UserId);
return sql;
}
@@ -300,6 +308,8 @@ namespace Umbraco.Core.Persistence.Repositories
var innerSql = GetBaseQuery("umbracoUser.id");
innerSql.Where("umbracoUser2app.app = " + SqlSyntax.GetQuotedValue(sectionAlias));
sql.Where(string.Format("umbracoUser.id IN ({0})", innerSql.SQL));
//must be sorted this way for the relator to work
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql));
}
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Persistence
//if (sqlSyntax == null) throw new ArgumentNullException("sqlSyntax");
if (settings == null) throw new ArgumentNullException("settings");
_cacheHelper = cacheHelper;
_cacheHelper = cacheHelper;
//IMPORTANT: We will force the DeepCloneRuntimeCacheProvider to be used here which is a wrapper for the underlying
// runtime cache to ensure that anything that can be deep cloned in/out is done so, this also ensures that our tracks
@@ -49,7 +49,12 @@ namespace Umbraco.Core.Persistence
_cacheHelper.IsolatedRuntimeCache.CacheFactory = type =>
{
var cache = origFactory(type);
return new DeepCloneRuntimeCacheProvider(cache);
//if the result is already a DeepCloneRuntimeCacheProvider then return it, otherwise
//wrap the result with a DeepCloneRuntimeCacheProvider
return cache is DeepCloneRuntimeCacheProvider
? cache
: new DeepCloneRuntimeCacheProvider(cache);
};
}
@@ -71,7 +76,7 @@ namespace Umbraco.Core.Persistence
{
}
[Obsolete("Use the ctor specifying all dependencies instead, NOTE: disableAllCache has zero effect")]
[Obsolete("Use the ctor specifying all dependencies instead, NOTE: disableAllCache has zero effect")]
public RepositoryFactory(bool disableAllCache, CacheHelper cacheHelper)
: this(cacheHelper, LoggerResolver.Current.Logger, SqlSyntaxContext.SqlSyntaxProvider, UmbracoConfig.For.UmbracoSettings())
{
@@ -86,7 +91,7 @@ namespace Umbraco.Core.Persistence
{
}
#endregion
public virtual IExternalLoginRepository CreateExternalLoginRepository(IScopeUnitOfWork uow)
@@ -235,12 +240,13 @@ namespace Umbraco.Core.Persistence
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual IStylesheetRepository CreateStylesheetRepository(IUnitOfWork uow, IDatabaseUnitOfWork db)
{
// note: the second unit of work is ignored.
return new StylesheetRepository(uow, FileSystemProviderManager.Current.StylesheetsFileSystem);
}
public virtual ITemplateRepository CreateTemplateRepository(IScopeUnitOfWork uow)
{
return new TemplateRepository(uow,
return new TemplateRepository(uow,
_cacheHelper,
_logger, _sqlSyntax,
FileSystemProviderManager.Current.MasterPagesFileSystem,
@@ -279,7 +285,7 @@ namespace Umbraco.Core.Persistence
}
public virtual IUserRepository CreateUserRepository(IScopeUnitOfWork uow)
{
{
return new UserRepository(
uow,
//Need to cache users - we look up user information more than anything in the back office!
@@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Scoping;
namespace Umbraco.Core.Persistence.UnitOfWork
{
internal class FileUnitOfWork : ScopeUnitOfWork
{
// fixme
// soon as FileUnitOfWork inherits from ScopeUnitOfWork it does not make any sense anymore to keep this class around?!
public FileUnitOfWork(IScopeProvider scopeProvider, IsolationLevel isolationLevel = IsolationLevel.Unspecified)
: base(scopeProvider, isolationLevel)
{ }
}
}
@@ -4,10 +4,15 @@ using Umbraco.Core.Scoping;
namespace Umbraco.Core.Persistence.UnitOfWork
{
// note: the concept of "file unit of work" does not make sense anymore in v7.6
// and we should probably remove this class, which is not used anywhere, but for
// the time being we keep it here - just not to break too many things.
/// <summary>
/// Represents a Unit of Work Provider for creating a file unit of work
/// </summary>
public class FileUnitOfWorkProvider : ScopeUnitOfWorkProvider // fixme - what's the point?
[Obsolete("Use the ScopeUnitOfWorkProvider instead.", false)]
public class FileUnitOfWorkProvider : ScopeUnitOfWorkProvider
{
[Obsolete("Use the ctor specifying a IScopeProvider instead")]
public FileUnitOfWorkProvider()
@@ -18,11 +23,8 @@ namespace Umbraco.Core.Persistence.UnitOfWork
: base(scopeProvider)
{ }
// fixme - returning a IScopeUnitOfWork instead of a IUnitOfWork here is a breaking change!
// this is bad, we're going to end up creating // units of work which is ... really bad
public override IScopeUnitOfWork GetUnitOfWork()
{
// fixme - no point returning a FileUnitOfWork if its equivalent to ScopeUnitOfWork
return new ScopeUnitOfWork(ScopeProvider);
}
}
@@ -18,19 +18,9 @@ namespace Umbraco.Core.Persistence.UnitOfWork
// creates a unit of work
// support specifying an isolation level
// support auto-commit - beware!
// fixme - should we be able to specify ALL scope options?
// fixme - that isolation level thing is a pain because of the above existing method
IScopeUnitOfWork GetUnitOfWork(bool commit);
IScopeUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel, bool commit = false);
// creates a readonly unit of work
// the readonly unit of work will not accept operations, and will auto-complete
// of course it would be a bad idea to use it for anything else than reading
// fixme - implement that one FOR REAL not as an extension method
// the extension method was a ugly hack
// or maybe we want a autocommit flag in the ctor?
//IScopeUnitOfWork GetReadOnlyUnitOfWork();
//IScopeUnitOfWork GetReadOnlyUnitOfWork(bool autocommit = false);
// support auto-commit - but beware! it will be committed, whatever happens
// TODO in v8 this should all be merged as one single method with optional args
IScopeUnitOfWork GetUnitOfWork(bool readOnly);
IScopeUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel, bool readOnly = false);
}
}
@@ -16,6 +16,7 @@ namespace Umbraco.Core.Persistence.UnitOfWork
private readonly IsolationLevel _isolationLevel;
private readonly IScopeProvider _scopeProvider;
private bool _completeScope;
private readonly bool _readOnly;
private IScope _scope;
private Guid _key;
@@ -29,11 +30,11 @@ namespace Umbraco.Core.Persistence.UnitOfWork
/// </summary>
/// <param name="scopeProvider"></param>
/// <param name="isolationLevel"></param>
/// <param name="commit"></param>
/// <param name="readOnly"></param>
/// <remarks>
/// This should normally not be used directly and should be created with the UnitOfWorkProvider
/// </remarks>
internal ScopeUnitOfWork(IScopeProvider scopeProvider, IsolationLevel isolationLevel = IsolationLevel.Unspecified, bool commit = false)
internal ScopeUnitOfWork(IScopeProvider scopeProvider, IsolationLevel isolationLevel = IsolationLevel.Unspecified, bool readOnly = false)
{
_scopeProvider = scopeProvider;
_isolationLevel = isolationLevel;
@@ -43,7 +44,7 @@ namespace Umbraco.Core.Persistence.UnitOfWork
// be false by default
// if set to true... the UnitOfWork is "auto-commit" which means that even in the case of
// an exception, the scope would still be completed - ppl should use it with great care!
_completeScope = commit;
_completeScope = _readOnly = readOnly;
}
/// <summary>
@@ -53,6 +54,9 @@ namespace Umbraco.Core.Persistence.UnitOfWork
/// <param name="repository">The <see cref="IUnitOfWorkRepository" /> participating in the transaction</param>
public void RegisterAdded(IEntity entity, IUnitOfWorkRepository repository)
{
if (_readOnly)
throw new NotSupportedException("This unit of work is read-only.");
_operations.Enqueue(new Operation
{
Entity = entity,
@@ -68,7 +72,10 @@ namespace Umbraco.Core.Persistence.UnitOfWork
/// <param name="repository">The <see cref="IUnitOfWorkRepository" /> participating in the transaction</param>
public void RegisterChanged(IEntity entity, IUnitOfWorkRepository repository)
{
_operations.Enqueue(
if (_readOnly)
throw new NotSupportedException("This unit of work is read-only.");
_operations.Enqueue(
new Operation
{
Entity = entity,
@@ -84,7 +91,10 @@ namespace Umbraco.Core.Persistence.UnitOfWork
/// <param name="repository">The <see cref="IUnitOfWorkRepository" /> participating in the transaction</param>
public void RegisterRemoved(IEntity entity, IUnitOfWorkRepository repository)
{
_operations.Enqueue(
if (_readOnly)
throw new NotSupportedException("This unit of work is read-only.");
_operations.Enqueue(
new Operation
{
Entity = entity,
@@ -116,6 +126,9 @@ namespace Umbraco.Core.Persistence.UnitOfWork
{
// this happens in a scope-managed transaction
if (_readOnly)
throw new NotSupportedException("This unit of work is read-only.");
// in case anything goes wrong
_completeScope = false;
@@ -24,48 +24,28 @@ namespace Umbraco.Core.Persistence.UnitOfWork
return new ScopeUnitOfWork(ScopeProvider);
}
/// <summary>
/// Creates a Unit of work with a new UmbracoDatabase instance for the work item/transaction.
/// </summary>
/// <returns></returns>
/// <remarks>
/// Each PetaPoco UOW uses it's own Database object, not the shared Database object that comes from
/// the ApplicationContext.Current.DatabaseContext.Database. This is because each transaction should use it's own Database
/// and we Dispose of this Database object when the UOW is disposed.
/// fixme NO we dispose of it when the transaction completes
/// fixme just inheritdoc!
/// </remarks>
/// <inheritdoc />
public virtual IScopeUnitOfWork GetUnitOfWork()
{
return new ScopeUnitOfWork(ScopeProvider);
}
/// <summary>
/// Creates a Unit of work with a new UmbracoDatabase instance for the work item/transaction.
/// </summary>
/// <returns></returns>
/// <remarks>
/// Each PetaPoco UOW uses it's own Database object, not the shared Database object that comes from
/// the ApplicationContext.Current.DatabaseContext.Database. This is because each transaction should use it's own Database
/// and we Dispose of this Database object when the UOW is disposed.
/// fixme NO
/// fixme just inheritdoc!
/// </remarks>
/// <inheritdoc />
public IScopeUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel)
{
return new ScopeUnitOfWork(ScopeProvider, isolationLevel);
}
/// <inheritdoc />
public IScopeUnitOfWork GetUnitOfWork(bool commit)
public IScopeUnitOfWork GetUnitOfWork(bool readOnly)
{
return new ScopeUnitOfWork(ScopeProvider, commit: commit);
return new ScopeUnitOfWork(ScopeProvider, readOnly: readOnly);
}
/// <inheritdoc />
public IScopeUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel, bool commit)
public IScopeUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel, bool readOnly)
{
return new ScopeUnitOfWork(ScopeProvider, isolationLevel, commit: commit);
return new ScopeUnitOfWork(ScopeProvider, isolationLevel, readOnly: readOnly);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,8 +1,9 @@
using System.Collections.Generic;
using umbraco.interfaces;
namespace Umbraco.Core.PropertyEditors
{
public interface IParameterEditor
public interface IParameterEditor : IDiscoverable
{
/// <summary>
/// The id of the property editor
@@ -1,4 +1,5 @@
using System;
using umbraco.interfaces;
namespace Umbraco.Core.PropertyEditors
{
@@ -7,8 +8,8 @@ namespace Umbraco.Core.PropertyEditors
/// </summary>
// todo: drop IPropertyEditorValueConverter support (when?).
[Obsolete("Use IPropertyValueConverter.")]
public interface IPropertyEditorValueConverter
{
public interface IPropertyEditorValueConverter : IDiscoverable
{
/// <summary>
/// Returns a value indicating whether this provider applies to the specified property.
/// </summary>
@@ -1,11 +1,12 @@
using Umbraco.Core.Models.PublishedContent;
using umbraco.interfaces;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Provides published content properties conversion service.
/// </summary>
public interface IPropertyValueConverter
public interface IPropertyValueConverter : IDiscoverable
{
/// <summary>
/// Gets a value indicating whether the converter supports a property type.
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Core.ObjectResolution;
@@ -17,11 +19,13 @@ namespace Umbraco.Core.PropertyEditors
internal class ParameterEditorResolver : LazyManyObjectsResolverBase<ParameterEditorResolver, IParameterEditor>
{
private readonly ManifestBuilder _builder;
private readonly IContentSection _contentSection;
public ParameterEditorResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> typeListProducerList, ManifestBuilder builder)
: base(serviceProvider, logger, typeListProducerList, ObjectLifetimeScope.Application)
{
_builder = builder;
_contentSection = UmbracoConfig.For.UmbracoSettings().Content;
}
/// <summary>
@@ -31,20 +35,27 @@ namespace Umbraco.Core.PropertyEditors
{
get
{
//This will by default include all property editors and parameter editors but we need to filter this
//list to ensure that none of the property editors that do not have the IsParameterEditor flag set to true
//are filtered.
var filtered = Values.Select(x => x as PropertyEditor)
.WhereNotNull()
.Where(x => x.IsParameterEditor == false);
return Values
//exclude the non parameter editor c# property editors
.Except(filtered)
//include the manifest parameter editors
.Union(_builder.ParameterEditors)
//include the manifest prop editors that are parameter editors
// all property editors and parameter editors
// except property editors where !IsParameterEditor
var values = Values
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsParameterEditor);
// union all manifest parameter editors
values = values
.Union(_builder.ParameterEditors);
// union all manifest property editors where IsParameterEditor
values = values
.Union(_builder.PropertyEditors.Where(x => x.IsParameterEditor));
if (_contentSection.ShowDeprecatedPropertyEditors == false)
{
// except deprecated property editors
values = values
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsDeprecated == false);
}
return values;
}
}
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
@@ -88,13 +89,26 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
/// </returns>
private bool IsRangeDataType(int dataTypeId)
{
// ** This must be cached (U4-8862) **
var enableRange =
_dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId)
.PreValuesAsDictionary.FirstOrDefault(
x => string.Equals(x.Key, "enableRange", StringComparison.InvariantCultureIgnoreCase)).Value;
// GetPreValuesCollectionByDataTypeId is cached at repository level;
// still, the collection is deep-cloned so this is kinda expensive,
// better to cache here + trigger refresh in DataTypeCacheRefresher
return enableRange != null && enableRange.Value.TryConvertTo<bool>().Result;
return Storages.GetOrAdd(dataTypeId, id =>
{
var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id)
.PreValuesAsDictionary
.FirstOrDefault(x => string.Equals(x.Key, "enableRange", StringComparison.InvariantCultureIgnoreCase))
.Value;
return preValue != null && preValue.Value.TryConvertTo<bool>().Result;
});
}
private static readonly ConcurrentDictionary<int, bool> Storages = new ConcurrentDictionary<int, bool>();
internal static void ClearCaches()
{
Storages.Clear();
}
}
}
@@ -1,9 +1,12 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
@@ -74,18 +77,26 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
/// </returns>
private bool JsonStorageType(int dataTypeId)
{
// ** This must be cached (U4-8862) **
var storageType =
_dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId)
.PreValuesAsDictionary.FirstOrDefault(
x => string.Equals(x.Key, "storageType", StringComparison.InvariantCultureIgnoreCase)).Value;
// GetPreValuesCollectionByDataTypeId is cached at repository level;
// still, the collection is deep-cloned so this is kinda expensive,
// better to cache here + trigger refresh in DataTypeCacheRefresher
if (storageType.Value.InvariantEquals("Json"))
return Storages.GetOrAdd(dataTypeId, id =>
{
return true;
}
var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id)
.PreValuesAsDictionary
.FirstOrDefault(x => string.Equals(x.Key, "storageType", StringComparison.InvariantCultureIgnoreCase))
.Value;
return false;
return preValue != null && preValue.Value.InvariantEquals("json");
});
}
private static readonly ConcurrentDictionary<int, bool> Storages = new ConcurrentDictionary<int, bool>();
internal static void ClearCaches()
{
Storages.Clear();
}
}
}
+4 -3
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
@@ -12,7 +13,8 @@ namespace Umbraco.Core.Publishing
{
public PublishStatus(IContent content, PublishStatusType statusType, EventMessages eventMessages)
: base(content, statusType, eventMessages)
{
{
InvalidProperties = Enumerable.Empty<Property>();
}
/// <summary>
@@ -20,8 +22,7 @@ namespace Umbraco.Core.Publishing
/// </summary>
public PublishStatus(IContent content, EventMessages eventMessages)
: this(content, PublishStatusType.Success, eventMessages)
{
}
{ }
public IContent ContentItem
{
@@ -51,7 +51,7 @@ namespace Umbraco.Core.Publishing
/// </summary>
/// <param name="uow"></param>
/// <param name="content"><see cref="IContent"/> to publish</param>
/// <param name="userId">Id of the User issueing the publish operation</param>
/// <param name="userId">Id of the User issueing the publish operation</param>
Attempt<PublishStatus> IPublishingStrategy2.Publish(IScopeUnitOfWork uow, IContent content, int userId)
{
var evtMsgs = _eventMessagesFactory.Get();
@@ -124,26 +124,26 @@ namespace Umbraco.Core.Publishing
/// By default this is set to true which means that it will publish any content item in the list that is completely unpublished and
/// not visible on the front-end. If set to false, this will only publish content that is live on the front-end but has new versions
/// that have yet to be published.
/// </param>
/// </param>
/// <returns></returns>
/// <remarks>
///
///
/// This method becomes complex once we start to be able to cancel events or stop publishing a content item in any way because if a
/// content item is not published then it's children shouldn't be published either. This rule will apply for the following conditions:
/// * If a document fails to be published, do not proceed to publish it's children if:
/// ** The document does not have a publish version
/// ** The document does have a published version but the includeUnpublishedDocuments = false
///
///
/// In order to do this, we will order the content by level and begin by publishing each item at that level, then proceed to the next
/// level and so on. If we detect that the above rule applies when the document publishing is cancelled we'll add it to the list of
/// level and so on. If we detect that the above rule applies when the document publishing is cancelled we'll add it to the list of
/// parentsIdsCancelled so that it's children don't get published.
///
///
/// Its important to note that all 'root' documents included in the list *will* be published regardless of the rules mentioned
/// above (unless it is invalid)!! By 'root' documents we are referring to documents in the list with the minimum value for their 'level'.
/// In most cases the 'root' documents will only be one document since under normal circumstance we only publish one document and
/// above (unless it is invalid)!! By 'root' documents we are referring to documents in the list with the minimum value for their 'level'.
/// In most cases the 'root' documents will only be one document since under normal circumstance we only publish one document and
/// its children. The reason we have to do this is because if a user is publishing a document and it's children, it is implied that
/// the user definitely wants to publish it even if it has never been published before.
///
///
/// </remarks>
IEnumerable<Attempt<PublishStatus>> IPublishingStrategy2.PublishWithChildren(IScopeUnitOfWork uow,
IEnumerable<IContent> content, int userId, bool includeUnpublishedDocuments)
@@ -157,7 +157,7 @@ namespace Umbraco.Core.Publishing
//group by levels and iterate over the sorted ascending level.
//TODO: This will cause all queries to execute, they will not be lazy but I'm not really sure being lazy actually made
// much difference because we iterate over them all anyways?? Morten?
// much difference because we iterate over them all anyways?? Morten?
// Because we're grouping I think this will execute all the queries anyways so need to fetch it all first.
var fetchedContent = content.ToArray();
@@ -174,7 +174,7 @@ namespace Umbraco.Core.Publishing
var levelGroups = fetchedContent.GroupBy(x => x.Level);
foreach (var level in levelGroups.OrderBy(x => x.Key))
{
//set the first level flag, used to ensure that all documents at the first level will
//set the first level flag, used to ensure that all documents at the first level will
//be published regardless of the rules mentioned in the remarks.
if (!firstLevel.HasValue)
{
@@ -224,7 +224,10 @@ namespace Umbraco.Core.Publishing
_logger.Info<PublishingStrategy>(
string.Format("Content '{0}' with Id '{1}' will not be published because some of it's content is not passing validation rules.",
item.Name, item.Id));
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid, evtMsgs)));
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid, evtMsgs)
{
InvalidProperties = ((ContentBase)item).LastInvalidProperties
}));
//Does this document apply to our rule to cancel it's children being published?
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
@@ -296,11 +299,11 @@ namespace Umbraco.Core.Publishing
/// <param name="includeUnpublishedDocuments"></param>
/// <remarks>
/// See remarks on method: PublishWithChildrenInternal
/// </remarks>
/// </remarks>
private void CheckCancellingOfChildPublishing(IContent content, List<int> parentsIdsCancelled, bool includeUnpublishedDocuments)
{
//Does this document apply to our rule to cancel it's children being published?
//TODO: We're going back to the service layer here... not sure how to avoid this? And this will add extra overhead to
//TODO: We're going back to the service layer here... not sure how to avoid this? And this will add extra overhead to
// any document that fails to publish...
var hasPublishedVersion = ApplicationContext.Current.Services.ContentService.HasPublishedVersion(content.Id);
@@ -176,6 +176,7 @@ namespace Umbraco.Core.Scoping
}
}
// this is for tests exclusively until we have a proper accessor in v8
internal static Func<IDictionary> HttpContextItemsGetter { get; set; }
private static IDictionary HttpContextItems
@@ -324,6 +324,14 @@ namespace Umbraco.Core.Security
throw new MembershipPasswordException("Change password canceled due to password validation failure.");
}
//Special case to allow changing password without validating existing credentials
//This is used during installation only
if (AllowManuallyChangingPassword == false && ApplicationContext.Current != null
&& ApplicationContext.Current.IsConfigured == false && oldPassword == "default")
{
return PerformChangePassword(username, oldPassword, newPassword);
}
if (AllowManuallyChangingPassword == false)
{
if (ValidateUser(username, oldPassword) == false) return false;
@@ -358,9 +358,8 @@ namespace Umbraco.Core.Services
{
var applicationAlias = (string)addElement.Attribute("application");
var type = (string)addElement.Attribute("type");
var assembly = (string)addElement.Attribute("assembly");
var clrType = Type.GetType(type);
var clrType = ApplicationTree.TryGetType(type);
if (clrType == null)
{
_logger.Warn<ApplicationTreeService>("The tree definition: " + addElement.ToString() + " could not be resolved to a .Net object type");
File diff suppressed because it is too large Load Diff
+188 -162
View File
@@ -1,22 +1,15 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Threading;
using AutoMapper;
using Umbraco.Core.Auditing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
@@ -26,14 +19,15 @@ namespace Umbraco.Core.Services
/// </summary>
public class ContentTypeService : ContentTypeServiceBase, IContentTypeService
{
private readonly IContentService _contentService;
private readonly IContentService _contentService;
private readonly IMediaService _mediaService;
//Support recursive locks because some of the methods that require locking call other methods that require locking.
//for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
public ContentTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService, IMediaService mediaService)
public ContentTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService,
IMediaService mediaService)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
if (contentService == null) throw new ArgumentNullException("contentService");
@@ -76,6 +70,7 @@ namespace Umbraco.Core.Services
}
catch (Exception ex)
{
uow.Commit();
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(null, OperationStatusType.FailedExceptionThrown, evtMsgs), ex);
}
}
@@ -113,6 +108,7 @@ namespace Umbraco.Core.Services
}
catch (Exception ex)
{
uow.Commit();
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(null, OperationStatusType.FailedExceptionThrown, evtMsgs), ex);
}
}
@@ -139,7 +135,7 @@ namespace Umbraco.Core.Services
TypedEventHandler<IContentTypeService, SaveEventArgs<EntityContainer>> savedEvent,
EntityContainer container,
Guid containerObjectType,
string objectTypeName,
string objectTypeName,
string savedEventName,
int userId)
{
@@ -159,10 +155,9 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
// fixme - how does it work w/name?!
if (uow.Events.DispatchCancelable(savingEvent, this, new SaveEventArgs<EntityContainer>(container, evtMsgs)))
//if (savingEvent.IsRaisedEventCancelled(new SaveEventArgs<EntityContainer>(container, evtMsgs), this, UowProvider))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
@@ -189,7 +184,7 @@ namespace Umbraco.Core.Services
private EntityContainer GetContainer(int containerId, Guid containerObjectType)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, containerObjectType);
return repo.Get(containerId);
@@ -198,7 +193,7 @@ namespace Umbraco.Core.Services
public IEnumerable<EntityContainer> GetMediaTypeContainers(int[] containerIds)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.MediaTypeContainerGuid);
return repo.GetAll(containerIds);
@@ -207,7 +202,7 @@ namespace Umbraco.Core.Services
public IEnumerable<EntityContainer> GetMediaTypeContainers(string name, int level)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.MediaTypeContainerGuid);
return repo.Get(name, level);
@@ -216,7 +211,7 @@ namespace Umbraco.Core.Services
public IEnumerable<EntityContainer> GetMediaTypeContainers(IMediaType mediaType)
{
var ancestorIds = mediaType.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
var ancestorIds = mediaType.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
.Select(x =>
{
var asInt = x.TryConvertTo<int>();
@@ -236,7 +231,7 @@ namespace Umbraco.Core.Services
public IEnumerable<EntityContainer> GetContentTypeContainers(int[] containerIds)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DocumentTypeContainerGuid);
return repo.GetAll(containerIds);
@@ -265,7 +260,7 @@ namespace Umbraco.Core.Services
private EntityContainer GetContainer(Guid containerId, Guid containerObjectType)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, containerObjectType);
return repo.Get(containerId);
@@ -274,7 +269,7 @@ namespace Umbraco.Core.Services
public IEnumerable<EntityContainer> GetContentTypeContainers(string name, int level)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DocumentTypeContainerGuid);
return repo.Get(name, level);
@@ -288,7 +283,11 @@ namespace Umbraco.Core.Services
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DocumentTypeContainerGuid);
var container = repo.Get(containerId);
if (container == null) return OperationStatus.NoOperation(evtMsgs); // fixme commit?
if (container == null)
{
uow.Commit();
return OperationStatus.NoOperation(evtMsgs);
}
if (uow.Events.DispatchCancelable(DeletingContentTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs)))
{
@@ -299,7 +298,7 @@ namespace Umbraco.Core.Services
repo.Delete(container);
uow.Commit();
uow.Events.Dispatch(DeletedContentTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs));
uow.Events.Dispatch(DeletedContentTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs), "DeletedContentTypeContainer");
return OperationStatus.Success(evtMsgs);
//TODO: Audit trail ?
@@ -314,7 +313,11 @@ namespace Umbraco.Core.Services
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.MediaTypeContainerGuid);
var container = repo.Get(containerId);
if (container == null) return OperationStatus.NoOperation(evtMsgs); // fixme commit?
if (container == null)
{
uow.Commit();
return OperationStatus.NoOperation(evtMsgs);
}
if (uow.Events.DispatchCancelable(DeletingMediaTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs)))
{
@@ -340,7 +343,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public IEnumerable<string> GetAllPropertyTypeAliases()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
return repository.GetAllPropertyTypeAliases();
@@ -357,7 +360,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public IEnumerable<string> GetAllContentTypeAliases(params Guid[] objectTypes)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
return repository.GetAllContentTypeAliases(objectTypes);
@@ -423,7 +426,7 @@ namespace Umbraco.Core.Services
clone.Name = name;
var compositionAliases = clone.CompositionAliases().Except(new[] { alias }).ToList();
var compositionAliases = clone.CompositionAliases().Except(new[] {alias}).ToList();
//remove all composition that is not it's current alias
foreach (var a in compositionAliases)
{
@@ -454,7 +457,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IContentType"/></returns>
public IContentType GetContentType(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
return repository.Get(id);
@@ -468,7 +471,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IContentType"/></returns>
public IContentType GetContentType(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
return repository.Get(alias);
@@ -482,7 +485,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IContentType"/></returns>
public IContentType GetContentType(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
return repository.Get(id);
@@ -496,7 +499,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IContentType"/> objects</returns>
public IEnumerable<IContentType> GetAllContentTypes(params int[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
return repository.GetAll(ids);
@@ -510,7 +513,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IContentType"/> objects</returns>
public IEnumerable<IContentType> GetAllContentTypes(IEnumerable<Guid> ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
return repository.GetAll(ids.ToArray());
@@ -524,7 +527,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IContentType"/> objects</returns>
public IEnumerable<IContentType> GetContentTypeChildren(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
var query = Query<IContentType>.Builder.Where(x => x.ParentId == id);
@@ -539,7 +542,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IContentType"/> objects</returns>
public IEnumerable<IContentType> GetContentTypeChildren(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
@@ -557,7 +560,7 @@ namespace Umbraco.Core.Services
/// <returns>True if the content type has any children otherwise False</returns>
public bool HasChildren(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
@@ -573,7 +576,7 @@ namespace Umbraco.Core.Services
/// <returns>True if the content type has any children otherwise False</returns>
public bool HasChildren(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
@@ -584,6 +587,27 @@ namespace Umbraco.Core.Services
}
}
public override IEnumerable<IContentTypeBase> GetDescendants(IContentTypeBase contentType)
{
var ctype = contentType as IContentType;
if (ctype != null) return GetDescendants(ctype);
var mtype = contentType as IMediaType;
if (mtype != null) return GetDescendants(mtype);
return Enumerable.Empty<IContentTypeBase>();
}
public IEnumerable<IContentType> GetDescendants(IContentType contentType)
{
return GetContentTypeChildren(contentType.Id)
.SelectRecursive(type => GetContentTypeChildren(type.Id));
}
public IEnumerable<IMediaType> GetDescendants(IMediaType contentType)
{
return GetMediaTypeChildren(contentType.Id)
.SelectRecursive(type => GetMediaTypeChildren(type.Id));
}
/// <summary>
/// This is called after an IContentType is saved and is used to update the content xml structures in the database
/// if they are required to be updated.
@@ -591,42 +615,39 @@ namespace Umbraco.Core.Services
/// <param name="contentTypes">A tuple of a content type and a boolean indicating if it is new (HasIdentity was false before committing)</param>
private void UpdateContentXmlStructure(params IContentTypeBase[] contentTypes)
{
var toUpdate = GetContentTypesForXmlUpdates(contentTypes).ToArray();
if (toUpdate.Any())
if (toUpdate.Any() == false) return;
var firstType = toUpdate.First();
//if it is a content type then call the rebuilding methods or content
if (firstType is IContentType)
{
var firstType = toUpdate.First();
//if it is a content type then call the rebuilding methods or content
if (firstType is IContentType)
var typedContentService = _contentService as ContentService;
if (typedContentService != null)
{
var typedContentService = _contentService as ContentService;
if (typedContentService != null)
{
typedContentService.RePublishAll(toUpdate.Select(x => x.Id).ToArray());
}
else
{
//this should never occur, the content service should always be typed but we'll check anyways.
_contentService.RePublishAll();
}
typedContentService.RePublishAll(toUpdate.Select(x => x.Id).ToArray());
}
else if (firstType is IMediaType)
else
{
//if it is a media type then call the rebuilding methods for media
var typedContentService = _mediaService as MediaService;
if (typedContentService != null)
{
typedContentService.RebuildXmlStructures(toUpdate.Select(x => x.Id).ToArray());
}
//this should never occur, the content service should always be typed but we'll check anyways.
_contentService.RePublishAll();
}
}
else if (firstType is IMediaType)
{
//if it is a media type then call the rebuilding methods for media
var typedContentService = _mediaService as MediaService;
if (typedContentService != null)
{
typedContentService.RebuildXmlStructures(toUpdate.Select(x => x.Id).ToArray());
}
}
}
public int CountContentTypes()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
return repository.Count(Query<IContentType>.Builder);
@@ -635,7 +656,7 @@ namespace Umbraco.Core.Services
public int CountMediaTypes()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
return repository.Count(Query<IMediaType>.Builder);
@@ -692,7 +713,7 @@ namespace Umbraco.Core.Services
var comparer = new DelegateEqualityComparer<IContentTypeComposition>((x, y) => x.Id == y.Id, x => x.Id);
var dependencies = new HashSet<IContentTypeComposition>(compositions, comparer);
var stack = new Stack<IContentTypeComposition>();
indirectReferences.ForEach(stack.Push);//Push indirect references to a stack, so we can add recursively
indirectReferences.ForEach(stack.Push); //Push indirect references to a stack, so we can add recursively
while (stack.Count > 0)
{
var indirectReference = stack.Pop();
@@ -750,19 +771,20 @@ namespace Umbraco.Core.Services
ValidateLocked(contentType); // throws if invalid
contentType.CreatorId = userId;
if (contentType.Description == string.Empty)
contentType.Description = null;
repository.AddOrUpdate(contentType);
uow.Commit();
}
UpdateContentXmlStructure(contentType); // fixme wtf here?
UpdateContentXmlStructure(contentType);
uow.Events.Dispatch(SavedContentType, this, new SaveEventArgs<IContentType>(contentType, false));
Audit(uow, AuditType.Save, "Save ContentType performed by user", userId, contentType.Id);
uow.Commit();
}
}
using (var scope = UowProvider.ScopeProvider.CreateScope()) // fixme what a mess
{
scope.Events.Dispatch(SavedContentType, this, new SaveEventArgs<IContentType>(contentType, false));
scope.Complete();
}
Audit(AuditType.Save, "Save ContentType performed by user", userId, contentType.Id);
}
/// <summary>
@@ -783,7 +805,7 @@ namespace Umbraco.Core.Services
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
foreach (var contentType in asArray)
@@ -793,21 +815,22 @@ namespace Umbraco.Core.Services
foreach (var contentType in asArray)
{
contentType.CreatorId = userId;
if (contentType.Description == string.Empty)
contentType.Description = null;
repository.AddOrUpdate(contentType);
}
//save it all in one go
uow.Commit();
}
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray()); // fixme wtf
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray());
uow.Events.Dispatch(SavedContentType, this, new SaveEventArgs<IContentType>(asArray, false));
Audit(uow, AuditType.Save, "Save ContentTypes performed by user", userId, -1);
uow.Commit();
}
}
using (var scope = UowProvider.ScopeProvider.CreateScope()) // fixme what a mess
{
scope.Events.Dispatch(SavedContentType, this, new SaveEventArgs<IContentType>(asArray, false));
scope.Complete();
}
Audit(AuditType.Save, "Save ContentTypes performed by user", userId, -1);
}
/// <summary>
@@ -817,7 +840,7 @@ namespace Umbraco.Core.Services
/// <param name="userId">Optional id of the user issueing the delete</param>
/// <remarks>Deleting a <see cref="IContentType"/> will delete all the <see cref="IContent"/> objects based on this <see cref="IContentType"/></remarks>
public void Delete(IContentType contentType, int userId = 0)
{
{
using (new WriteLock(Locker))
{
using (var uow = UowProvider.GetUnitOfWork())
@@ -829,20 +852,20 @@ namespace Umbraco.Core.Services
}
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
//If we are deleting this content type, we are also deleting it's descendents!
var deletedContentTypes = new List<IContentType>() {contentType};
deletedContentTypes.AddRange(contentType.Descendants((IContentTypeService)this).OfType<IContentType>());
var deletedContentTypes = new List<IContentType> {contentType};
deletedContentTypes.AddRange(GetDescendants(contentType));
_contentService.DeleteContentOfTypes(deletedContentTypes.Select(x => x.Id), userId);
repository.Delete(contentType);
uow.Commit();
uow.Events.Dispatch(DeletedContentType, this, new DeleteEventArgs<IContentType>(deletedContentTypes.DistinctBy(x => x.Id), false));
}
Audit(AuditType.Delete, string.Format("Delete ContentType performed by user"), userId, contentType.Id);
Audit(uow, AuditType.Delete, string.Format("Delete ContentType performed by user"), userId, contentType.Id);
uow.Commit();
}
}
}
@@ -857,7 +880,7 @@ namespace Umbraco.Core.Services
public void Delete(IEnumerable<IContentType> contentTypes, int userId = 0)
{
var asArray = contentTypes.ToArray();
using (new WriteLock(Locker))
{
using (var uow = UowProvider.GetUnitOfWork())
@@ -874,22 +897,21 @@ namespace Umbraco.Core.Services
var deletedContentTypes = new List<IContentType>(asArray);
foreach (var contentType in asArray)
{
deletedContentTypes.AddRange(contentType.Descendants((IContentTypeService)this).OfType<IContentType>());
deletedContentTypes.AddRange(GetDescendants(contentType));
}
_contentService.DeleteContentOfTypes(deletedContentTypes.Select(x => x.Id), userId);
_contentService.DeleteContentOfTypes(deletedContentTypes.Select(x => x.Id), userId);
foreach (var contentType in asArray)
{
repository.Delete(contentType);
}
uow.Commit();
uow.Events.Dispatch(DeletedContentType, this, new DeleteEventArgs<IContentType>(deletedContentTypes.DistinctBy(x => x.Id), false));
}
Audit(AuditType.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1);
Audit(uow, AuditType.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1);
uow.Commit();
}
}
}
@@ -900,7 +922,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMediaType"/></returns>
public IMediaType GetMediaType(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
return repository.Get(id);
@@ -914,7 +936,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMediaType"/></returns>
public IMediaType GetMediaType(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
return repository.Get(alias);
@@ -928,7 +950,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMediaType"/></returns>
public IMediaType GetMediaType(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
return repository.Get(id);
@@ -942,7 +964,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMediaType"/> objects</returns>
public IEnumerable<IMediaType> GetAllMediaTypes(params int[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
return repository.GetAll(ids);
@@ -956,7 +978,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMediaType"/> objects</returns>
public IEnumerable<IMediaType> GetAllMediaTypes(IEnumerable<Guid> ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
return repository.GetAll(ids.ToArray());
@@ -970,7 +992,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMediaType"/> objects</returns>
public IEnumerable<IMediaType> GetMediaTypeChildren(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
var query = Query<IMediaType>.Builder.Where(x => x.ParentId == id);
@@ -985,7 +1007,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMediaType"/> objects</returns>
public IEnumerable<IMediaType> GetMediaTypeChildren(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
var found = GetMediaType(id);
@@ -1002,7 +1024,7 @@ namespace Umbraco.Core.Services
/// <returns>True if the media type has any children otherwise False</returns>
public bool MediaTypeHasChildren(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
var query = Query<IMediaType>.Builder.Where(x => x.ParentId == id);
@@ -1017,7 +1039,7 @@ namespace Umbraco.Core.Services
/// <returns>True if the media type has any children otherwise False</returns>
public bool MediaTypeHasChildren(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
var found = GetMediaType(id);
@@ -1035,7 +1057,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(MovingMediaType, this, new MoveEventArgs<IMediaType>(evtMsgs, new MoveEventInfo<IMediaType>(toMove, toMove.Path, containerId))))
{
uow.Commit();
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs));
}
var containerRepository = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.MediaTypeContainerGuid);
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
@@ -1052,8 +1077,8 @@ namespace Umbraco.Core.Services
}
catch (DataOperationException<MoveOperationStatusType> ex)
{
return Attempt.Fail(
new OperationStatus<MoveOperationStatusType>(ex.Operation, evtMsgs));
uow.Commit();
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(ex.Operation, evtMsgs));
}
uow.Commit();
uow.Events.Dispatch(MovedMediaType, this, new MoveEventArgs<IMediaType>(false, evtMsgs, moveInfo.ToArray()));
@@ -1071,7 +1096,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(MovingContentType, this, new MoveEventArgs<IContentType>(evtMsgs, new MoveEventInfo<IContentType>(toMove, toMove.Path, containerId))))
{
uow.Commit();
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs));
}
var containerRepository = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DocumentTypeContainerGuid);
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
@@ -1088,8 +1116,8 @@ namespace Umbraco.Core.Services
}
catch (DataOperationException<MoveOperationStatusType> ex)
{
return Attempt.Fail(
new OperationStatus<MoveOperationStatusType>(ex.Operation, evtMsgs));
uow.Commit();
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(ex.Operation, evtMsgs));
}
uow.Commit();
uow.Events.Dispatch(MovedContentType, this, new MoveEventArgs<IContentType>(false, evtMsgs, moveInfo.ToArray()));
@@ -1135,6 +1163,7 @@ namespace Umbraco.Core.Services
}
catch (DataOperationException<MoveOperationStatusType> ex)
{
uow.Commit();
return Attempt.Fail(new OperationStatus<IMediaType, MoveOperationStatusType>(null, ex.Operation, evtMsgs));
}
uow.Commit();
@@ -1179,6 +1208,7 @@ namespace Umbraco.Core.Services
}
catch (DataOperationException<MoveOperationStatusType> ex)
{
uow.Commit();
return Attempt.Fail(new OperationStatus<IContentType, MoveOperationStatusType>(null, ex.Operation, evtMsgs));
}
uow.Commit();
@@ -1203,23 +1233,23 @@ namespace Umbraco.Core.Services
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
ValidateLocked(mediaType); // throws if invalid
mediaType.CreatorId = userId;
if (mediaType.Description == string.Empty)
mediaType.Description = null;
repository.AddOrUpdate(mediaType);
uow.Commit();
}
UpdateContentXmlStructure(mediaType); // fixme wtf
UpdateContentXmlStructure(mediaType);
using (var scope = UowProvider.ScopeProvider.CreateScope()) // fixme what a mess
{
scope.Events.Dispatch(SavedMediaType, this, new SaveEventArgs<IMediaType>(mediaType, false));
scope.Complete();
uow.Events.Dispatch(SavedMediaType, this, new SaveEventArgs<IMediaType>(mediaType, false));
Audit(uow, AuditType.Save, "Save MediaType performed by user", userId, mediaType.Id);
uow.Commit();
}
Audit(AuditType.Save, "Save MediaType performed by user", userId, mediaType.Id);
}
}
@@ -1231,7 +1261,7 @@ namespace Umbraco.Core.Services
public void Save(IEnumerable<IMediaType> mediaTypes, int userId = 0)
{
var asArray = mediaTypes.ToArray();
using (new WriteLock(Locker))
{
using (var uow = UowProvider.GetUnitOfWork())
@@ -1241,7 +1271,7 @@ namespace Umbraco.Core.Services
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
foreach (var mediaType in asArray)
@@ -1251,20 +1281,21 @@ namespace Umbraco.Core.Services
foreach (var mediaType in asArray)
{
mediaType.CreatorId = userId;
if (mediaType.Description == string.Empty)
mediaType.Description = null;
repository.AddOrUpdate(mediaType);
}
//save it all in one go
uow.Commit();
}
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray()); // fixme wtf
using (var scope = UowProvider.ScopeProvider.CreateScope()) // fixme what a mess
{
scope.Events.Dispatch(SavedMediaType, this, new SaveEventArgs<IMediaType>(asArray, false));
scope.Complete();
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray());
uow.Events.Dispatch(SavedMediaType, this, new SaveEventArgs<IMediaType>(asArray, false));
Audit(uow, AuditType.Save, "Save MediaTypes performed by user", userId, -1);
uow.Commit();
}
Audit(AuditType.Save, "Save MediaTypes performed by user", userId, -1);
}
}
@@ -1292,17 +1323,17 @@ namespace Umbraco.Core.Services
//If we are deleting this content type, we are also deleting it's descendents!
var deletedMediaTypes = new List<IMediaType> { mediaType };
deletedMediaTypes.AddRange(mediaType.Descendants((IContentTypeService)this).OfType<IMediaType>());
deletedMediaTypes.AddRange(GetDescendants(mediaType));
_mediaService.DeleteMediaOfTypes(deletedMediaTypes.Select(x => x.Id), userId);
repository.Delete(mediaType);
uow.Commit();
uow.Events.Dispatch(DeletedMediaType, this, new DeleteEventArgs<IMediaType>(deletedMediaTypes.DistinctBy(x => x.Id), false));
}
Audit(AuditType.Delete, "Delete MediaType performed by user", userId, mediaType.Id);
Audit(uow, AuditType.Delete, "Delete MediaType performed by user", userId, mediaType.Id);
uow.Commit();
}
}
}
@@ -1317,7 +1348,7 @@ namespace Umbraco.Core.Services
//TODO: Share all of this logic with the Delete IContentType methods, no need for code duplication
var asArray = mediaTypes.ToArray();
using (new WriteLock(Locker))
{
using (var uow = UowProvider.GetUnitOfWork())
@@ -1329,12 +1360,12 @@ namespace Umbraco.Core.Services
}
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
//If we are deleting this content type, we are also deleting it's descendents!
var deletedMediaTypes = new List<IMediaType>(asArray);
foreach (var mediaType in asArray)
{
deletedMediaTypes.AddRange(mediaType.Descendants((IContentTypeService)this).OfType<IMediaType>());
deletedMediaTypes.AddRange(GetDescendants(mediaType));
}
_mediaService.DeleteMediaOfTypes(deletedMediaTypes.Select(x => x.Id), userId);
@@ -1344,12 +1375,11 @@ namespace Umbraco.Core.Services
repository.Delete(mediaType);
}
uow.Commit();
uow.Events.Dispatch(DeletedMediaType, this, new DeleteEventArgs<IMediaType>(deletedMediaTypes.DistinctBy(x => x.Id), false));
}
Audit(AuditType.Delete, "Delete MediaTypes performed by user", userId, -1);
Audit(uow, AuditType.Delete, "Delete MediaTypes performed by user", userId, -1);
uow.Commit();
}
}
}
@@ -1408,14 +1438,10 @@ namespace Umbraco.Core.Services
return dtd.ToString();
}
private void Audit(AuditType type, string message, int userId, int objectId)
private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId)
{
using (var uow = UowProvider.GetUnitOfWork())
{
var auditRepo = RepositoryFactory.CreateAuditRepository(uow);
auditRepo.AddOrUpdate(new AuditItem(objectId, message, type, userId));
uow.Commit();
}
var auditRepo = RepositoryFactory.CreateAuditRepository(uow);
auditRepo.AddOrUpdate(new AuditItem(objectId, message, type, userId));
}
#region Event Handlers
@@ -1435,40 +1461,40 @@ namespace Umbraco.Core.Services
/// </summary>
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletingContentType;
/// <summary>
/// Occurs after Delete
/// </summary>
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletedContentType;
/// <summary>
/// Occurs after Delete
/// </summary>
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletedContentType;
/// <summary>
/// Occurs before Delete
/// </summary>
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletingMediaType;
/// <summary>
/// Occurs before Delete
/// </summary>
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletingMediaType;
/// <summary>
/// Occurs after Delete
/// </summary>
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletedMediaType;
/// <summary>
/// Occurs after Delete
/// </summary>
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IMediaType>> DeletedMediaType;
/// <summary>
/// Occurs before Save
/// </summary>
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavingContentType;
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavingContentType;
/// <summary>
/// Occurs after Save
/// </summary>
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavedContentType;
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IContentType>> SavedContentType;
/// <summary>
/// Occurs before Save
/// </summary>
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavingMediaType;
/// <summary>
/// Occurs before Save
/// </summary>
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavingMediaType;
/// <summary>
/// Occurs after Save
/// </summary>
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavedMediaType;
/// <summary>
/// Occurs after Save
/// </summary>
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<IMediaType>> SavedMediaType;
/// <summary>
/// Occurs before Move
@@ -5,6 +5,7 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
@@ -13,9 +14,8 @@ namespace Umbraco.Core.Services
{
public ContentTypeServiceBase(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
}
{ }
/// <summary>
/// This is called after an content type is saved and is used to update the content xml structures in the database
/// if they are required to be updated.
@@ -33,7 +33,7 @@ namespace Umbraco.Core.Services
// - a content type changes it's alias OR
// - if a content type has it's property removed OR
// - if a content type has a property whose alias has changed
//here we need to check if the alias of the content type changed or if one of the properties was removed.
//here we need to check if the alias of the content type changed or if one of the properties was removed.
var dirty = contentType as IRememberBeingDirty;
if (dirty == null) continue;
@@ -50,25 +50,45 @@ namespace Umbraco.Core.Services
&& (dirty.WasPropertyDirty("Alias") || dirty.WasPropertyDirty("HasPropertyTypeBeenRemoved") || hasAnyPropertiesChangedAlias))
{
//If the alias was changed then we only need to update the xml structures for content of the current content type.
//If a property was deleted or a property alias was changed then we need to update the xml structures for any
//If a property was deleted or a property alias was changed then we need to update the xml structures for any
// content of the current content type and any of the content type's child content types.
if (dirty.WasPropertyDirty("Alias")
&& dirty.WasPropertyDirty("HasPropertyTypeBeenRemoved") == false && hasAnyPropertiesChangedAlias == false)
{
//if only the alias changed then only update the current content type
//if only the alias changed then only update the current content type
toUpdate.Add(contentType);
}
else
{
//if a property was deleted or alias changed, then update all content of the current content type
// and all of it's desscendant doc types.
toUpdate.AddRange(contentType.DescendantsAndSelf(this));
// and all of it's desscendant doc types.
toUpdate.Add(contentType);
toUpdate.AddRange(GetDescendants(contentType));
}
}
}
return toUpdate;
}
public virtual IEnumerable<IContentTypeBase> GetDescendants(IContentTypeBase contentType)
{
return Enumerable.Empty<IContentTypeBase>();
}
/// <summary>
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
/// </summary>
/// <param name="contentPath"></param>
/// <returns></returns>
public bool HasContainerInPath(string contentPath)
{
using (var uow = UowProvider.GetUnitOfWork())
{
// can use same repo for both content and media
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
return repository.HasContainerInPath(contentPath);
}
}
}
}
+32 -33
View File
@@ -66,7 +66,7 @@ namespace Umbraco.Core.Services
public EntityContainer GetContainer(int containerId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DataTypeContainerGuid);
return repo.Get(containerId);
@@ -75,7 +75,7 @@ namespace Umbraco.Core.Services
public EntityContainer GetContainer(Guid containerId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DataTypeContainerGuid);
return repo.Get(containerId);
@@ -84,7 +84,7 @@ namespace Umbraco.Core.Services
public IEnumerable<EntityContainer> GetContainers(string name, int level)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DataTypeContainerGuid);
return repo.Get(name, level);
@@ -108,7 +108,7 @@ namespace Umbraco.Core.Services
public IEnumerable<EntityContainer> GetContainers(int[] containerIds)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DataTypeContainerGuid);
return repo.GetAll(containerIds);
@@ -181,7 +181,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IDataTypeDefinition"/></returns>
public IDataTypeDefinition GetDataTypeDefinitionByName(string name)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
return repository.GetByQuery(new Query<IDataTypeDefinition>().Where(x => x.Name == name)).FirstOrDefault();
@@ -195,7 +195,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IDataTypeDefinition"/></returns>
public IDataTypeDefinition GetDataTypeDefinitionById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
return repository.Get(id);
@@ -209,7 +209,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IDataTypeDefinition"/></returns>
public IDataTypeDefinition GetDataTypeDefinitionById(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
var query = Query<IDataTypeDefinition>.Builder.Where(x => x.Key == id);
@@ -238,7 +238,7 @@ namespace Umbraco.Core.Services
/// <returns>Collection of <see cref="IDataTypeDefinition"/> objects with a matching contorl id</returns>
public IEnumerable<IDataTypeDefinition> GetDataTypeDefinitionByPropertyEditorAlias(string propertyEditorAlias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
var query = Query<IDataTypeDefinition>.Builder.Where(x => x.PropertyEditorAlias == propertyEditorAlias);
@@ -253,7 +253,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IDataTypeDefinition"/> objects</returns>
public IEnumerable<IDataTypeDefinition> GetAllDataTypeDefinitions(params int[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
return repository.GetAll(ids);
@@ -267,7 +267,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of string values</returns>
public IEnumerable<string> GetPreValuesByDataTypeId(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
//now convert the collection to a string list
@@ -284,7 +284,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public PreValueCollection GetPreValuesCollectionByDataTypeId(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
return repository.GetPreValuesCollectionByDataTypeId(id);
@@ -298,7 +298,7 @@ namespace Umbraco.Core.Services
/// <returns>PreValue as a string</returns>
public string GetPreValueAsString(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
return repository.GetPreValueAsString(id);
@@ -313,7 +313,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Moving, this, new MoveEventArgs<IDataTypeDefinition>(evtMsgs, new MoveEventInfo<IDataTypeDefinition>(toMove, toMove.Path, parentId))))
{
uow.Commit();
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs));
}
var containerRepository = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DataTypeContainerGuid);
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
@@ -366,13 +369,12 @@ namespace Umbraco.Core.Services
dataTypeDefinition.CreatorId = userId;
repository.AddOrUpdate(dataTypeDefinition);
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition, false));
}
// FIXME transaction!
Audit(AuditType.Save, "Save DataTypeDefinition performed by user", userId, dataTypeDefinition.Id);
Audit(uow, AuditType.Save, "Save DataTypeDefinition performed by user", userId, dataTypeDefinition.Id);
uow.Commit();
}
}
/// <summary>
@@ -411,13 +413,13 @@ namespace Umbraco.Core.Services
dataTypeDefinition.CreatorId = userId;
repository.AddOrUpdate(dataTypeDefinition);
}
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions, false));
}
Audit(AuditType.Save, string.Format("Save DataTypeDefinition performed by user"), userId, -1);
Audit(uow, AuditType.Save, string.Format("Save DataTypeDefinition performed by user"), userId, -1);
uow.Commit();
}
}
/// <summary>
@@ -487,7 +489,6 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
repository.AddOrUpdatePreValues(dataTypeDefinition, values);
uow.Commit();
}
@@ -504,7 +505,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition)))
{
uow.Commit();
return;
}
// if preValues contain the data type, override the data type definition accordingly
if (values != null && values.ContainsKey(Constants.PropertyEditors.PreValueKeys.DataValueType))
@@ -520,12 +524,11 @@ namespace Umbraco.Core.Services
//add/update the prevalues
repository.AddOrUpdatePreValues(dataTypeDefinition, values);
Audit(uow, AuditType.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition, false));
}
Audit(AuditType.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
}
/// <summary>
@@ -542,18 +545,20 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IDataTypeDefinition>(dataTypeDefinition)))
{
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow);
repository.Delete(dataTypeDefinition);
Audit(uow, AuditType.Delete, "Delete DataTypeDefinition performed by user", userId, dataTypeDefinition.Id);
uow.Commit();
uow.Events.Dispatch(Deleted, this, new DeleteEventArgs<IDataTypeDefinition>(dataTypeDefinition, false));
}
Audit(AuditType.Delete, "Delete DataTypeDefinition performed by user", userId, dataTypeDefinition.Id);
}
/// <summary>
@@ -577,14 +582,10 @@ namespace Umbraco.Core.Services
return DataTypesResolver.Current.DataTypes;
}
private void Audit(AuditType type, string message, int userId, int objectId)
private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId)
{
using (var uow = UowProvider.GetUnitOfWork())
{
var auditRepo = RepositoryFactory.CreateAuditRepository(uow);
auditRepo.AddOrUpdate(new AuditItem(objectId, message, type, userId));
uow.Commit();
}
var auditRepo = RepositoryFactory.CreateAuditRepository(uow);
auditRepo.AddOrUpdate(new AuditItem(objectId, message, type, userId));
}
#region Event Handlers
@@ -624,7 +625,5 @@ namespace Umbraco.Core.Services
/// </summary>
public static event TypedEventHandler<IDataTypeService, MoveEventArgs<IDataTypeDefinition>> Moved;
#endregion
}
}
+11 -5
View File
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Services
public bool Exists(string domainName)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateDomainRepository(uow);
return repo.Exists(domainName);
@@ -33,7 +33,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IDomain>(domain, evtMsgs)))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
var repository = RepositoryFactory.CreateDomainRepository(uow);
repository.Delete(domain);
@@ -49,7 +52,7 @@ namespace Umbraco.Core.Services
public IDomain GetByName(string name)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDomainRepository(uow);
return repository.GetByName(name);
@@ -58,7 +61,7 @@ namespace Umbraco.Core.Services
public IDomain GetById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateDomainRepository(uow);
return repo.Get(id);
@@ -67,7 +70,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IDomain> GetAll(bool includeWildcards)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateDomainRepository(uow);
return repo.GetAll(includeWildcards);
@@ -76,7 +79,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IDomain> GetAssignedDomains(int contentId, bool includeWildcards)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreateDomainRepository(uow);
return repo.GetAssignedDomains(contentId, includeWildcards);
@@ -90,7 +93,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IDomain>(domainEntity, evtMsgs)))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
var repository = RepositoryFactory.CreateDomainRepository(uow);
repository.AddOrUpdate(domainEntity);
+23 -44
View File
@@ -79,7 +79,7 @@ namespace Umbraco.Core.Services
{
var result = _runtimeCache.GetCacheItem<int?>(CacheKeys.IdToKeyCacheKey + key, () =>
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
switch (umbracoObjectType)
{
@@ -92,7 +92,6 @@ namespace Umbraco.Core.Services
case UmbracoObjectTypes.Member:
case UmbracoObjectTypes.DataType:
case UmbracoObjectTypes.DocumentTypeContainer:
uow.Commit();
return uow.Database.ExecuteScalar<int?>(new Sql().Select("id").From<NodeDto>().Where<NodeDto>(dto => dto.UniqueId == key));
case UmbracoObjectTypes.RecycleBin:
case UmbracoObjectTypes.Stylesheet:
@@ -119,7 +118,7 @@ namespace Umbraco.Core.Services
{
var result = _runtimeCache.GetCacheItem<Guid?>(CacheKeys.KeyToIdCacheKey + id, () =>
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
switch (umbracoObjectType)
{
@@ -131,7 +130,6 @@ namespace Umbraco.Core.Services
case UmbracoObjectTypes.DocumentType:
case UmbracoObjectTypes.Member:
case UmbracoObjectTypes.DataType:
uow.Commit();
return uow.Database.ExecuteScalar<Guid?>(new Sql().Select("uniqueID").From<NodeDto>().Where<NodeDto>(dto => dto.NodeId == id));
case UmbracoObjectTypes.RecycleBin:
case UmbracoObjectTypes.Stylesheet:
@@ -185,11 +183,10 @@ namespace Umbraco.Core.Services
{
if (loadBaseType)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var ret = repository.Get(id);
uow.Commit();
return ret;
}
}
@@ -207,11 +204,10 @@ namespace Umbraco.Core.Services
if (loadBaseType)
{
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var ret = repository.GetByKey(key, objectTypeId);
uow.Commit();
return ret;
}
}
@@ -241,11 +237,10 @@ namespace Umbraco.Core.Services
if (loadBaseType)
{
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var ret = repository.Get(id, objectTypeId);
uow.Commit();
return ret;
}
}
@@ -276,11 +271,10 @@ namespace Umbraco.Core.Services
{
if (loadBaseType)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var ret = repository.Get(id);
uow.Commit();
return ret;
}
}
@@ -303,7 +297,7 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IUmbracoEntity"/></returns>
public virtual IUmbracoEntity GetParent(int id)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var entity = repository.Get(id);
@@ -311,7 +305,6 @@ namespace Umbraco.Core.Services
if (entity.ParentId == -1 || entity.ParentId == -20 || entity.ParentId == -21)
return null;
var ret = repository.Get(entity.ParentId);
uow.Commit();
return ret;
}
}
@@ -324,7 +317,7 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IUmbracoEntity"/></returns>
public virtual IUmbracoEntity GetParent(int id, UmbracoObjectTypes umbracoObjectType)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var entity = repository.Get(id);
@@ -334,7 +327,6 @@ namespace Umbraco.Core.Services
var objectTypeId = umbracoObjectType.GetGuid();
var ret = repository.Get(entity.ParentId, objectTypeId);
uow.Commit();
return ret;
}
}
@@ -346,13 +338,12 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
public virtual IEnumerable<IUmbracoEntity> GetChildren(int parentId)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
var contents = repository.GetByQuery(query);
uow.Commit();
return contents;
}
}
@@ -366,13 +357,12 @@ namespace Umbraco.Core.Services
public virtual IEnumerable<IUmbracoEntity> GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType)
{
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
var contents = repository.GetByQuery(query, objectTypeId);
uow.Commit();
return contents;
}
}
@@ -393,7 +383,7 @@ namespace Umbraco.Core.Services
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "")
{
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId && x.Trashed == false);
@@ -405,7 +395,6 @@ namespace Umbraco.Core.Services
}
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
uow.Commit();
return contents;
}
}
@@ -426,7 +415,7 @@ namespace Umbraco.Core.Services
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "")
{
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
@@ -442,7 +431,6 @@ namespace Umbraco.Core.Services
}
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
uow.Commit();
return contents;
}
}
@@ -463,7 +451,7 @@ namespace Umbraco.Core.Services
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true)
{
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
@@ -481,7 +469,6 @@ namespace Umbraco.Core.Services
}
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
uow.Commit();
return contents;
}
}
@@ -493,7 +480,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
public virtual IEnumerable<IUmbracoEntity> GetDescendents(int id)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var entity = repository.Get(id);
@@ -501,7 +488,6 @@ namespace Umbraco.Core.Services
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(pathMatch) && x.Id != id);
var entities = repository.GetByQuery(query);
uow.Commit();
return entities;
}
}
@@ -515,14 +501,13 @@ namespace Umbraco.Core.Services
public virtual IEnumerable<IUmbracoEntity> GetDescendents(int id, UmbracoObjectTypes umbracoObjectType)
{
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var entity = repository.Get(id);
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(entity.Path) && x.Id != id);
var entities = repository.GetByQuery(query, objectTypeId);
uow.Commit();
return entities;
}
}
@@ -541,11 +526,10 @@ namespace Umbraco.Core.Services
}
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var entities = repository.GetByQuery(_rootEntityQuery, objectTypeId);
uow.Commit();
return entities;
}
}
@@ -585,11 +569,10 @@ namespace Umbraco.Core.Services
});
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var ret = repository.GetAll(objectTypeId, ids);
uow.Commit();
return ret;
}
}
@@ -605,11 +588,10 @@ namespace Umbraco.Core.Services
});
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var ret = repository.GetAll(objectTypeId, keys);
uow.Commit();
return ret;
}
}
@@ -631,11 +613,10 @@ namespace Umbraco.Core.Services
("The passed in type is not supported");
});
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var ret = repository.GetAll(objectTypeId, ids);
uow.Commit();
return ret;
}
}
@@ -647,7 +628,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="UmbracoObjectTypes"/></returns>
public virtual UmbracoObjectTypes GetObjectType(int id)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var sql = new Sql().Select("nodeObjectType").From<NodeDto>().Where<NodeDto>(x => x.NodeId == id);
var nodeObjectTypeId = uow.Database.ExecuteScalar<Guid>(sql);
@@ -663,7 +644,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="UmbracoObjectTypes"/></returns>
public virtual UmbracoObjectTypes GetObjectType(Guid key)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var sql = new Sql().Select("nodeObjectType").From<NodeDto>().Where<NodeDto>(x => x.UniqueId == key);
var nodeObjectTypeId = uow.Database.ExecuteScalar<Guid>(sql);
@@ -721,22 +702,20 @@ namespace Umbraco.Core.Services
public bool Exists(Guid key)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var exists = repository.Exists(key);
uow.Commit();
return exists;
}
}
public bool Exists(int id)
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var exists = repository.Exists(id);
uow.Commit();
return exists;
}
}
+109 -123
View File
@@ -15,31 +15,21 @@ using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
{
// note
// file unit of work are just IUnitOfWork which is not IDisposable
// they don't really participate in the scope etc ;(
// FIXME not anymore now that Shan's made FileUnitOfWork a normal UOW? then WTF?
/// <summary>
/// Represents the File Service, which is an easy access to operations involving <see cref="IFile"/> objects like Scripts, Stylesheets and Templates
/// </summary>
public class FileService : ScopeRepositoryService, IFileService
{
private readonly IScopeUnitOfWorkProvider _fileUowProvider;
private const string PartialViewHeader = "@inherits Umbraco.Web.Mvc.UmbracoTemplatePage";
private const string PartialViewMacroHeader = "@inherits Umbraco.Web.Macros.PartialViewMacroPage";
public FileService(
IScopeUnitOfWorkProvider fileProvider,
IDatabaseUnitOfWorkProvider dataProvider,
IDatabaseUnitOfWorkProvider provider,
RepositoryFactory repositoryFactory,
ILogger logger,
IEventMessagesFactory eventMessagesFactory)
: base(dataProvider, repositoryFactory, logger, eventMessagesFactory)
{
_fileUowProvider = fileProvider;
}
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{ }
#region Stylesheets
@@ -50,11 +40,9 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="Stylesheet"/> objects</returns>
public IEnumerable<Stylesheet> GetStylesheets(params string[] names)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
// FIXME is it ok to use the same UOW here twice?
// review everywhere in this file!!
var repository = RepositoryFactory.CreateStylesheetRepository(uow, uow);
var repository = RepositoryFactory.CreateStylesheetRepository(uow);
return repository.GetAll(names);
}
}
@@ -66,9 +54,9 @@ namespace Umbraco.Core.Services
/// <returns>A <see cref="Stylesheet"/> object</returns>
public Stylesheet GetStylesheetByName(string name)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateStylesheetRepository(uow, uow);
var repository = RepositoryFactory.CreateStylesheetRepository(uow);
return repository.Get(name);
}
}
@@ -88,13 +76,14 @@ namespace Umbraco.Core.Services
return;
}
var repository = RepositoryFactory.CreateStylesheetRepository(uow, uow);
var repository = RepositoryFactory.CreateStylesheetRepository(uow);
repository.AddOrUpdate(stylesheet);
uow.Commit();
uow.Events.Dispatch(SavedStylesheet, this, new SaveEventArgs<Stylesheet>(stylesheet, false));
}
Audit(AuditType.Save, "Save Stylesheet performed by user", userId, -1);
uow.Events.Dispatch(SavedStylesheet, this, new SaveEventArgs<Stylesheet>(stylesheet, false));
Audit(uow, AuditType.Save, "Save Stylesheet performed by user", userId, -1);
uow.Commit();
}
}
/// <summary>
@@ -106,7 +95,7 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateStylesheetRepository(uow, uow);
var repository = RepositoryFactory.CreateStylesheetRepository(uow);
var stylesheet = repository.Get(path);
if (stylesheet == null)
{
@@ -121,12 +110,12 @@ namespace Umbraco.Core.Services
}
repository.Delete(stylesheet);
uow.Commit();
uow.Events.Dispatch(DeletedStylesheet, this, new DeleteEventArgs<Stylesheet>(stylesheet, false));
}
Audit(AuditType.Delete, string.Format("Delete Stylesheet performed by user"), userId, -1);
Audit(uow, AuditType.Delete, string.Format("Delete Stylesheet performed by user"), userId, -1);
uow.Commit();
}
}
/// <summary>
@@ -136,9 +125,9 @@ namespace Umbraco.Core.Services
/// <returns>True if Stylesheet is valid, otherwise false</returns>
public bool ValidateStylesheet(Stylesheet stylesheet)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateStylesheetRepository(uow, uow);
var repository = RepositoryFactory.CreateStylesheetRepository(uow);
return repository.ValidateStylesheet(stylesheet);
}
}
@@ -152,7 +141,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="Script"/> objects</returns>
public IEnumerable<Script> GetScripts(params string[] names)
{
using (var uow = _fileUowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateScriptRepository(uow);
return repository.GetAll(names);
@@ -166,7 +155,7 @@ namespace Umbraco.Core.Services
/// <returns>A <see cref="Script"/> object</returns>
public Script GetScriptByName(string name)
{
using (var uow = _fileUowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateScriptRepository(uow);
return repository.Get(name);
@@ -180,7 +169,7 @@ namespace Umbraco.Core.Services
/// <param name="userId"></param>
public void SaveScript(Script script, int userId = 0)
{
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingScript, this, new SaveEventArgs<Script>(script)))
{
@@ -190,12 +179,12 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateScriptRepository(uow);
repository.AddOrUpdate(script);
uow.Commit();
uow.Events.Dispatch(SavedScript, this, new SaveEventArgs<Script>(script, false));
}
Audit(AuditType.Save, "Save Script performed by user", userId, -1);
Audit(uow, AuditType.Save, "Save Script performed by user", userId, -1);
uow.Commit();
}
}
/// <summary>
@@ -205,7 +194,7 @@ namespace Umbraco.Core.Services
/// <param name="userId"></param>
public void DeleteScript(string path, int userId = 0)
{
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateScriptRepository(uow);
var script = repository.Get(path);
@@ -222,12 +211,12 @@ namespace Umbraco.Core.Services
}
repository.Delete(script);
uow.Commit();
uow.Events.Dispatch(DeletedScript, this, new DeleteEventArgs<Script>(script, false));
}
Audit(AuditType.Delete, string.Format("Delete Script performed by user"), userId, -1);
Audit(uow, AuditType.Delete, string.Format("Delete Script performed by user"), userId, -1);
uow.Commit();
}
}
/// <summary>
@@ -237,7 +226,7 @@ namespace Umbraco.Core.Services
/// <returns>True if Script is valid, otherwise false</returns>
public bool ValidateScript(Script script)
{
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateScriptRepository(uow);
return repository.ValidateScript(script);
@@ -246,7 +235,7 @@ namespace Umbraco.Core.Services
public void CreateScriptFolder(string folderPath)
{
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateScriptRepository(uow);
((ScriptRepository)repository).AddFolder(folderPath);
@@ -256,7 +245,7 @@ namespace Umbraco.Core.Services
public void DeleteScriptFolder(string folderPath)
{
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateScriptRepository(uow);
((ScriptRepository)repository).DeleteFolder(folderPath);
@@ -308,12 +297,12 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateTemplateRepository(uow);
repository.AddOrUpdate(template);
uow.Commit();
uow.Events.Dispatch(SavedTemplate, this, new SaveEventArgs<ITemplate>(template, false, evtMsgs));
}
Audit(AuditType.Save, "Save Template performed by user", userId, template.Id);
Audit(uow, AuditType.Save, "Save Template performed by user", userId, template.Id);
uow.Commit();
}
return Attempt.Succeed(new OperationStatus<ITemplate, OperationStatusType>(template, OperationStatusType.Success, evtMsgs));
}
@@ -338,7 +327,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="ITemplate"/> objects</returns>
public IEnumerable<ITemplate> GetTemplates(params string[] aliases)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.GetAll(aliases).OrderBy(x => x.Name);
@@ -351,7 +340,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="ITemplate"/> objects</returns>
public IEnumerable<ITemplate> GetTemplates(int masterTemplateId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.GetChildren(masterTemplateId).OrderBy(x => x.Name);
@@ -365,7 +354,7 @@ namespace Umbraco.Core.Services
/// <returns>The <see cref="ITemplate"/> object matching the alias, or null.</returns>
public ITemplate GetTemplate(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.Get(alias);
@@ -379,7 +368,7 @@ namespace Umbraco.Core.Services
/// <returns>The <see cref="ITemplate"/> object matching the identifier, or null.</returns>
public ITemplate GetTemplate(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.Get(id);
@@ -393,7 +382,7 @@ namespace Umbraco.Core.Services
/// <returns>The <see cref="ITemplate"/> object matching the identifier, or null.</returns>
public ITemplate GetTemplate(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
var query = Query<ITemplate>.Builder.Where(x => x.Key == id);
@@ -403,7 +392,7 @@ namespace Umbraco.Core.Services
public IEnumerable<ITemplate> GetTemplateDescendants(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.GetDescendants(alias);
@@ -417,7 +406,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public IEnumerable<ITemplate> GetTemplateDescendants(int masterTemplateId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.GetDescendants(masterTemplateId);
@@ -431,7 +420,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public IEnumerable<ITemplate> GetTemplateChildren(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.GetChildren(alias);
@@ -445,7 +434,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public IEnumerable<ITemplate> GetTemplateChildren(int masterTemplateId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.GetChildren(masterTemplateId);
@@ -461,7 +450,7 @@ namespace Umbraco.Core.Services
[EditorBrowsable(EditorBrowsableState.Never)]
public TemplateNode GetTemplateNode(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.GetTemplateNode(alias);
@@ -478,7 +467,7 @@ namespace Umbraco.Core.Services
[EditorBrowsable(EditorBrowsableState.Never)]
public TemplateNode FindTemplateInTree(TemplateNode anyNode, string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.FindTemplateInTree(anyNode, alias);
@@ -502,12 +491,12 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateTemplateRepository(uow);
repository.AddOrUpdate(template);
uow.Commit();
uow.Events.Dispatch(SavedTemplate, this, new SaveEventArgs<ITemplate>(template, false));
}
Audit(AuditType.Save, "Save Template performed by user", userId, template.Id);
Audit(uow, AuditType.Save, "Save Template performed by user", userId, template.Id);
uow.Commit();
}
}
/// <summary>
@@ -529,12 +518,12 @@ namespace Umbraco.Core.Services
{
repository.AddOrUpdate(template);
}
uow.Commit();
uow.Events.Dispatch(SavedTemplate, this, new SaveEventArgs<ITemplate>(templates, false));
}
Audit(AuditType.Save, "Save Template performed by user", userId, -1);
Audit(uow, AuditType.Save, "Save Template performed by user", userId, -1);
uow.Commit();
}
}
/// <summary>
@@ -552,7 +541,7 @@ namespace Umbraco.Core.Services
/// </remarks>
public RenderingEngine DetermineTemplateRenderingEngine(ITemplate template)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.DetermineTemplateRenderingEngine(template);
@@ -566,12 +555,10 @@ namespace Umbraco.Core.Services
/// <param name="userId"></param>
public void DeleteTemplate(string alias, int userId = 0)
{
// fixme - WHY outside of UOW?!
// v8 - that should be part of the uow / scope
var template = GetTemplate(alias);
if (template == null)
{
return;
}
using (var uow = UowProvider.GetUnitOfWork())
{
@@ -584,12 +571,12 @@ namespace Umbraco.Core.Services
}
repository.Delete(template);
uow.Commit();
uow.Events.Dispatch(DeletedTemplate, this, new DeleteEventArgs<ITemplate>(template, false));
}
Audit(AuditType.Delete, "Delete Template performed by user", userId, template.Id);
Audit(uow, AuditType.Delete, "Delete Template performed by user", userId, template.Id);
uow.Commit();
}
}
/// <summary>
@@ -599,7 +586,7 @@ namespace Umbraco.Core.Services
/// <returns>True if Script is valid, otherwise false</returns>
public bool ValidateTemplate(ITemplate template)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.ValidateTemplate(template);
@@ -608,7 +595,7 @@ namespace Umbraco.Core.Services
public Stream GetTemplateFileContentStream(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.GetFileContentStream(filepath);
@@ -617,17 +604,17 @@ namespace Umbraco.Core.Services
public void SetTemplateFileContent(string filepath, Stream content)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
repository.SetFileContent(filepath, content);
// fixme - no need to commit... always committing?????
uow.Commit();
}
}
public long GetTemplateFileSize(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
return repository.GetFileSize(filepath);
@@ -638,7 +625,7 @@ namespace Umbraco.Core.Services
public Stream GetStylesheetFileContentStream(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateStylesheetRepository(uow);
return repository.GetFileContentStream(filepath);
@@ -647,16 +634,17 @@ namespace Umbraco.Core.Services
public void SetStylesheetFileContent(string filepath, Stream content)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateStylesheetRepository(uow);
repository.SetFileContent(filepath, content);
uow.Commit();
}
}
public long GetStylesheetFileSize(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateStylesheetRepository(uow);
return repository.GetFileSize(filepath);
@@ -665,7 +653,7 @@ namespace Umbraco.Core.Services
public Stream GetScriptFileContentStream(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateScriptRepository(uow);
return repository.GetFileContentStream(filepath);
@@ -674,16 +662,17 @@ namespace Umbraco.Core.Services
public void SetScriptFileContent(string filepath, Stream content)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateScriptRepository(uow);
repository.SetFileContent(filepath, content);
uow.Commit();
}
}
public long GetScriptFileSize(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateScriptRepository(uow);
return repository.GetFileSize(filepath);
@@ -692,7 +681,7 @@ namespace Umbraco.Core.Services
public Stream GetXsltFileContentStream(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateXsltFileRepository(uow);
return repository.GetFileContentStream(filepath);
@@ -701,16 +690,17 @@ namespace Umbraco.Core.Services
public void SetXsltFileContent(string filepath, Stream content)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateXsltFileRepository(uow);
repository.SetFileContent(filepath, content);
uow.Commit();
}
}
public long GetXsltFileSize(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateXsltFileRepository(uow);
return repository.GetFileSize(filepath);
@@ -737,9 +727,9 @@ namespace Umbraco.Core.Services
public void CreatePartialViewFolder(string folderPath)
{
var uow = _fileUowProvider.GetUnitOfWork();
using (var repository = RepositoryFactory.CreatePartialViewRepository(uow))
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreatePartialViewRepository(uow);
((PartialViewRepository)repository).AddFolder(folderPath);
uow.Commit();
}
@@ -747,9 +737,9 @@ namespace Umbraco.Core.Services
public void CreatePartialViewMacroFolder(string folderPath)
{
var uow = _fileUowProvider.GetUnitOfWork();
using (var repository = RepositoryFactory.CreatePartialViewMacroRepository(uow))
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreatePartialViewMacroRepository(uow);
((PartialViewMacroRepository)repository).AddFolder(folderPath);
uow.Commit();
}
@@ -757,7 +747,7 @@ namespace Umbraco.Core.Services
public void DeletePartialViewFolder(string folderPath)
{
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreatePartialViewRepository(uow);
((PartialViewRepository)repository).DeleteFolder(folderPath);
@@ -767,7 +757,7 @@ namespace Umbraco.Core.Services
public void DeletePartialViewMacroFolder(string folderPath)
{
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreatePartialViewMacroRepository(uow);
((PartialViewMacroRepository)repository).DeleteFolder(folderPath);
@@ -777,7 +767,7 @@ namespace Umbraco.Core.Services
public IPartialView GetPartialView(string path)
{
using (var uow = _fileUowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreatePartialViewRepository(uow);
return repository.Get(path);
@@ -786,7 +776,7 @@ namespace Umbraco.Core.Services
public IPartialView GetPartialViewMacro(string path)
{
using (var uow = _fileUowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreatePartialViewMacroRepository(uow);
return repository.Get(path);
@@ -795,7 +785,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IPartialView> GetPartialViewMacros(params string[] names)
{
using (var uow = _fileUowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreatePartialViewMacroRepository(uow);
return repository.GetAll(names).OrderBy(x => x.Name);
@@ -804,7 +794,7 @@ namespace Umbraco.Core.Services
public IXsltFile GetXsltFile(string path)
{
using (var uow = _fileUowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateXsltFileRepository(uow);
return repository.Get(path);
@@ -813,7 +803,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IXsltFile> GetXsltFiles(params string[] names)
{
using (var uow = _fileUowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateXsltFileRepository(uow);
return repository.GetAll(names).OrderBy(x => x.Name);
@@ -845,16 +835,16 @@ namespace Umbraco.Core.Services
}
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = GetPartialViewRepository(partialViewType, uow);
repository.AddOrUpdate(partialView);
uow.Commit();
uow.Events.Dispatch(CreatedPartialView, this, new NewEventArgs<IPartialView>(partialView, false, partialView.Alias, -1));
}
Audit(AuditType.Save, string.Format("Save {0} performed by user", partialViewType), userId, -1);
Audit(uow, AuditType.Save, string.Format("Save {0} performed by user", partialViewType), userId, -1);
uow.Commit();
}
return Attempt<IPartialView>.Succeed(partialView);
}
@@ -871,14 +861,14 @@ namespace Umbraco.Core.Services
private bool DeletePartialViewMacro(string path, PartialViewType partialViewType, int userId = 0)
{
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = GetPartialViewRepository(partialViewType, uow);
var partialView = repository.Get(path);
if (partialView == null)
{
uow.Commit();
return true;
return false;
}
if (uow.Events.DispatchCancelable(DeletingPartialView, this, new DeleteEventArgs<IPartialView>(partialView)))
@@ -888,12 +878,12 @@ namespace Umbraco.Core.Services
}
repository.Delete(partialView);
uow.Commit();
uow.Events.Dispatch(DeletedPartialView, this, new DeleteEventArgs<IPartialView>(partialView, false));
}
Audit(AuditType.Delete, string.Format("Delete {0} performed by user", partialViewType), userId, -1);
Audit(uow, AuditType.Delete, string.Format("Delete {0} performed by user", partialViewType), userId, -1);
uow.Commit();
}
return true;
@@ -911,7 +901,7 @@ namespace Umbraco.Core.Services
private Attempt<IPartialView> SavePartialView(IPartialView partialView, PartialViewType partialViewType, int userId = 0)
{
using (var uow = _fileUowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingPartialView, this, new SaveEventArgs<IPartialView>(partialView)))
{
@@ -921,18 +911,19 @@ namespace Umbraco.Core.Services
var repository = GetPartialViewRepository(partialViewType, uow);
repository.AddOrUpdate(partialView);
uow.Commit();
uow.Events.Dispatch(SavedPartialView, this, new SaveEventArgs<IPartialView>(partialView, false));
}
Audit(AuditType.Save, string.Format("Save {0} performed by user", partialViewType), userId, -1);
uow.Events.Dispatch(SavedPartialView, this, new SaveEventArgs<IPartialView>(partialView, false));
Audit(uow, AuditType.Save, string.Format("Save {0} performed by user", partialViewType), userId, -1);
uow.Commit();
}
return Attempt.Succeed(partialView);
}
public bool ValidatePartialView(PartialView partialView)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreatePartialViewRepository(uow);
return repository.ValidatePartialView(partialView);
@@ -941,7 +932,7 @@ namespace Umbraco.Core.Services
public bool ValidatePartialViewMacro(PartialView partialView)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreatePartialViewMacroRepository(uow);
return repository.ValidatePartialView(partialView);
@@ -981,7 +972,7 @@ namespace Umbraco.Core.Services
public Stream GetPartialViewMacroFileContentStream(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = GetPartialViewRepository(PartialViewType.PartialViewMacro, uow);
return repository.GetFileContentStream(filepath);
@@ -1039,7 +1030,6 @@ namespace Umbraco.Core.Services
public void SetPartialViewMacroFileContent(string filepath, Stream content)
{
// FIXME FTW would we use a READONLY unit of work to SET FILE CONTENT
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = GetPartialViewRepository(PartialViewType.PartialViewMacro, uow);
@@ -1050,7 +1040,7 @@ namespace Umbraco.Core.Services
public long GetPartialViewMacroFileSize(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = GetPartialViewRepository(PartialViewType.PartialViewMacro, uow);
return repository.GetFileSize(filepath);
@@ -1059,7 +1049,7 @@ namespace Umbraco.Core.Services
public Stream GetPartialViewFileContentStream(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = GetPartialViewRepository(PartialViewType.PartialView, uow);
return repository.GetFileContentStream(filepath);
@@ -1078,7 +1068,7 @@ namespace Umbraco.Core.Services
public long GetPartialViewFileSize(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = GetPartialViewRepository(PartialViewType.PartialView, uow);
return repository.GetFileSize(filepath);
@@ -1087,14 +1077,10 @@ namespace Umbraco.Core.Services
#endregion
private void Audit(AuditType type, string message, int userId, int objectId)
private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId)
{
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
uow.Commit();
}
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
}
//TODO Method to change name and/or alias of view/masterpage template
@@ -11,6 +11,13 @@ namespace Umbraco.Core.Services
/// </summary>
public interface IContentTypeService : IService
{
/// <summary>
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
/// </summary>
/// <param name="contentPath"></param>
/// <returns></returns>
bool HasContainerInPath(string contentPath);
int CountContentTypes();
int CountMediaTypes();
+1 -6
View File
@@ -468,12 +468,7 @@ namespace Umbraco.Core.Services
/// <param name="filepath">The filesystem path to the media.</param>
void DeleteMediaFile(string filepath);
/// <summary>
/// Generates thumbnails.
/// </summary>
/// <param name="filepath">The filesystem-relative path to the original image.</param>
/// <param name="propertyType">The property type.</param>
/// <remarks>This should be obsoleted, we should not generate thumbnails.</remarks>
[Obsolete("This should no longer be used, thumbnail generation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
void GenerateThumbnails(string filepath, PropertyType propertyType);
}
}
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Auditing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
@@ -18,12 +15,9 @@ namespace Umbraco.Core.Services
/// </summary>
public class LocalizationService : ScopeRepositoryService, ILocalizationService
{
public LocalizationService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
}
{ }
/// <summary>
/// Adds or updates a translation for a dictionary item and language
@@ -110,7 +104,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IDictionaryItem"/></returns>
public IDictionaryItem GetDictionaryItemById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
//ensure the lazy Language callback is assigned
@@ -128,7 +122,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="DictionaryItem"/></returns>
public IDictionaryItem GetDictionaryItemById(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
//ensure the lazy Language callback is assigned
@@ -146,7 +140,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IDictionaryItem"/></returns>
public IDictionaryItem GetDictionaryItemByKey(string key)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
//ensure the lazy Language callback is assigned
@@ -164,7 +158,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IDictionaryItem"/> objects</returns>
public IEnumerable<IDictionaryItem> GetDictionaryItemChildren(Guid parentId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
var query = Query<IDictionaryItem>.Builder.Where(x => x.ParentId == parentId);
@@ -183,7 +177,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IDictionaryItem"/> objects</returns>
public IEnumerable<IDictionaryItem> GetDictionaryItemDescendants(Guid? parentId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
//ensure the lazy Language callback is assigned
@@ -200,7 +194,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IDictionaryItem"/> objects</returns>
public IEnumerable<IDictionaryItem> GetRootDictionaryItems()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
var query = Query<IDictionaryItem>.Builder.Where(x => x.ParentId == null);
@@ -219,7 +213,7 @@ namespace Umbraco.Core.Services
/// <returns>True if a <see cref="IDictionaryItem"/> exists, otherwise false</returns>
public bool DictionaryItemExists(string key)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
return repository.Get(key) != null;
@@ -242,14 +236,14 @@ namespace Umbraco.Core.Services
}
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
repository.AddOrUpdate(dictionaryItem);
uow.Commit();
//ensure the lazy Language callback is assigned
EnsureDictionaryItemLanguageCallback(dictionaryItem);
uow.Commit(); // FIXME do we need this? what's the func above doing?
uow.Events.Dispatch(SavedDictionaryItem, this, new SaveEventArgs<IDictionaryItem>(dictionaryItem, false));
}
Audit(AuditType.Save, "Save DictionaryItem performed by user", userId, dictionaryItem.Id);
// ensure the lazy Language callback is assigned (not using the uow)
EnsureDictionaryItemLanguageCallback(dictionaryItem);
uow.Events.Dispatch(SavedDictionaryItem, this, new SaveEventArgs<IDictionaryItem>(dictionaryItem, false));
Audit(uow, AuditType.Save, "Save DictionaryItem performed by user", userId, dictionaryItem.Id);
uow.Commit();
}
}
/// <summary>
@@ -270,11 +264,12 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
repository.Delete(dictionaryItem);
uow.Commit();
uow.Events.Dispatch(DeletedDictionaryItem, this, new DeleteEventArgs<IDictionaryItem>(dictionaryItem, false));
}
Audit(AuditType.Delete, "Delete DictionaryItem performed by user", userId, dictionaryItem.Id);
uow.Events.Dispatch(DeletedDictionaryItem, this, new DeleteEventArgs<IDictionaryItem>(dictionaryItem, false));
Audit(uow, AuditType.Delete, "Delete DictionaryItem performed by user", userId, dictionaryItem.Id);
uow.Commit();
}
}
/// <summary>
@@ -284,7 +279,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="Language"/></returns>
public ILanguage GetLanguageById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateLanguageRepository(uow);
return repository.Get(id);
@@ -298,7 +293,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="Language"/></returns>
public ILanguage GetLanguageByCultureCode(string cultureName)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateLanguageRepository(uow);
return repository.GetByCultureName(cultureName);
@@ -312,7 +307,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="Language"/></returns>
public ILanguage GetLanguageByIsoCode(string isoCode)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateLanguageRepository(uow);
return repository.GetByIsoCode(isoCode);
@@ -325,7 +320,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="ILanguage"/> objects</returns>
public IEnumerable<ILanguage> GetAllLanguages()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateLanguageRepository(uow);
return repository.GetAll();
@@ -348,11 +343,12 @@ namespace Umbraco.Core.Services
}
var repository = RepositoryFactory.CreateLanguageRepository(uow);
repository.AddOrUpdate(language);
uow.Commit();
uow.Events.Dispatch(SavedLanguage, this, new SaveEventArgs<ILanguage>(language, false));
}
Audit(AuditType.Save, "Save Language performed by user", userId, language.Id);
uow.Events.Dispatch(SavedLanguage, this, new SaveEventArgs<ILanguage>(language, false));
Audit(uow, AuditType.Save, "Save Language performed by user", userId, language.Id);
uow.Commit();
}
}
/// <summary>
@@ -372,27 +368,24 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateLanguageRepository(uow);
repository.Delete(language);
uow.Commit();
uow.Events.Dispatch(DeletedLanguage, this, new DeleteEventArgs<ILanguage>(language, false));
}
Audit(AuditType.Delete, "Delete Language performed by user", userId, language.Id);
uow.Events.Dispatch(DeletedLanguage, this, new DeleteEventArgs<ILanguage>(language, false));
Audit(uow, AuditType.Delete, "Delete Language performed by user", userId, language.Id);
uow.Commit();
}
}
private void Audit(AuditType type, string message, int userId, int objectId)
private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId)
{
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
uow.Commit();
}
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
}
/// <summary>
/// This is here to take care of a hack - the DictionaryTranslation model contains an ILanguage reference which we don't want but
/// This is here to take care of a hack - the DictionaryTranslation model contains an ILanguage reference which we don't want but
/// we cannot remove it because it would be a large breaking change, so we need to make sure it's resolved lazily. This is because
/// if developers have a lot of dictionary items and translations, the caching and cloning size gets much much larger because of
/// if developers have a lot of dictionary items and translations, the caching and cloning size gets much much larger because of
/// the large object graphs. So now we don't cache or clone the attached ILanguage
/// </summary>
private void EnsureDictionaryItemLanguageCallback(IDictionaryItem d)
+14 -18
View File
@@ -57,7 +57,7 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IMacro"/> object</returns>
public IMacro GetByAlias(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMacroRepository(uow);
var q = new Query<IMacro>();
@@ -91,7 +91,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IMacro> GetAll(params int[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMacroRepository(uow);
return repository.GetAll(ids);
@@ -100,7 +100,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IMacro> GetAll(params Guid[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMacroRepository(uow);
return repository.GetAll(ids);
@@ -109,7 +109,7 @@ namespace Umbraco.Core.Services
public IMacro GetById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMacroRepository(uow);
return repository.Get(id);
@@ -118,7 +118,7 @@ namespace Umbraco.Core.Services
public IMacro GetById(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMacroRepository(uow);
return repository.Get(id);
@@ -151,12 +151,12 @@ namespace Umbraco.Core.Services
}
var repository = RepositoryFactory.CreateMacroRepository(uow);
repository.Delete(macro);
uow.Commit();
uow.Events.Dispatch(Deleted, this, new DeleteEventArgs<IMacro>(macro, false));
}
Audit(AuditType.Delete, "Delete Macro performed by user", userId, -1);
Audit(uow, AuditType.Delete, "Delete Macro performed by user", userId, -1);
uow.Commit();
}
}
/// <summary>
@@ -181,12 +181,12 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateMacroRepository(uow);
repository.AddOrUpdate(macro);
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMacro>(macro, false));
}
Audit(AuditType.Save, "Save Macro performed by user", userId, -1);
Audit(uow, AuditType.Save, "Save Macro performed by user", userId, -1);
uow.Commit();
}
}
///// <summary>
@@ -208,14 +208,10 @@ namespace Umbraco.Core.Services
// return MacroPropertyTypeResolver.Current.MacroPropertyTypes.FirstOrDefault(x => x.Alias == alias);
//}
private void Audit(AuditType type, string message, int userId, int objectId)
private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId)
{
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
uow.Commit();
}
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
}
#region Event Handlers
+141 -164
View File
@@ -11,7 +11,6 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Media;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
@@ -28,7 +27,7 @@ namespace Umbraco.Core.Services
public class MediaService : ScopeRepositoryService, IMediaService, IMediaServiceOperations
{
//Support recursive locks because some of the methods that require locking call other methods that require locking.
//Support recursive locks because some of the methods that require locking call other methods that require locking.
//for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
@@ -67,9 +66,7 @@ namespace Umbraco.Core.Services
var parent = GetById(media.ParentId);
media.Path = string.Concat(parent.IfNotNull(x => x.Path, media.ParentId.ToString()), ",", media.Id);
//we are using GetReadOnlyUnitOfWork because this actually doesn't write anything!
// fixme - IS IT EVEN DOING ANYTHING WITH REPO? NO! SO USE A SCOPE INSTEAD!
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Creating, this, new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId)))
{
@@ -79,15 +76,12 @@ namespace Umbraco.Core.Services
}
media.CreatorId = userId;
uow.Events.Dispatch(Created, this, new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId));
Audit(AuditType.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
Audit(uow, AuditType.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
uow.Commit();
return media;
}
}
/// <summary>
@@ -112,9 +106,7 @@ namespace Umbraco.Core.Services
var media = new Models.Media(name, parent, mediaType);
media.Path = string.Concat(parent.Path, ",", media.Id);
//we are using GetReadOnlyUnitOfWork because this actually doesn't write anything!
// fixme
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Creating, this, new NewEventArgs<IMedia>(media, mediaTypeAlias, parent)))
{
@@ -127,7 +119,8 @@ namespace Umbraco.Core.Services
uow.Events.Dispatch(Created, this, new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parent));
Audit(AuditType.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
Audit(uow, AuditType.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
uow.Commit();
return media;
}
@@ -157,12 +150,14 @@ namespace Umbraco.Core.Services
// out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
if (uow.Events.DispatchCancelable(Creating, this, new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId)))
{
uow.Commit();
media.WasCancelled = true;
return media;
}
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(media)))
{
uow.Commit();
media.WasCancelled = true;
return media;
}
@@ -170,21 +165,19 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateMediaRepository(uow);
media.CreatorId = userId;
repository.AddOrUpdate(media);
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, m));
// generate preview for blame history?
if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
{
repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, m));
}
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(media, false));
uow.Events.Dispatch(Created, this, new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId));
}
Audit(AuditType.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
Audit(uow, AuditType.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
uow.Commit();
}
return media;
}
@@ -215,17 +208,18 @@ namespace Umbraco.Core.Services
// out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
if (uow.Events.DispatchCancelable(Creating, this, new NewEventArgs<IMedia>(media, mediaTypeAlias, parent)))
{
uow.Commit();
media.WasCancelled = true;
return media;
}
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(media)))
{
uow.Commit();
media.WasCancelled = true;
return media;
}
var repository = RepositoryFactory.CreateMediaRepository(uow);
media.CreatorId = userId;
repository.AddOrUpdate(media);
@@ -236,13 +230,12 @@ namespace Umbraco.Core.Services
repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, m));
}
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(media, false));
uow.Events.Dispatch(Created, this, new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parent));
}
Audit(AuditType.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
Audit(uow, AuditType.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
uow.Commit();
}
return media;
}
@@ -254,7 +247,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMedia"/></returns>
public IMedia GetById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
return repository.Get(id);
@@ -286,7 +279,7 @@ namespace Umbraco.Core.Services
public int Count(string contentTypeAlias = null)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
return repository.Count(contentTypeAlias);
@@ -295,7 +288,7 @@ namespace Umbraco.Core.Services
public int CountChildren(int parentId, string contentTypeAlias = null)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
return repository.CountChildren(parentId, contentTypeAlias);
@@ -304,7 +297,7 @@ namespace Umbraco.Core.Services
public int CountDescendants(int parentId, string contentTypeAlias = null)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
return repository.CountDescendants(parentId, contentTypeAlias);
@@ -320,7 +313,7 @@ namespace Umbraco.Core.Services
{
if (ids.Any() == false) return Enumerable.Empty<IMedia>();
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
return repository.GetAll(ids.ToArray());
@@ -334,7 +327,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMedia"/></returns>
public IMedia GetById(Guid key)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.Key == key);
@@ -349,7 +342,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
public IEnumerable<IMedia> GetByLevel(int level)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.Level == level && x.Path.StartsWith("-21") == false);
@@ -364,7 +357,7 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IMedia"/> item</returns>
public IMedia GetByVersion(Guid versionId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
return repository.GetByVersion(versionId);
@@ -378,7 +371,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
public IEnumerable<IMedia> GetVersions(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
return repository.GetAllVersions(id);
@@ -407,7 +400,7 @@ namespace Umbraco.Core.Services
if (ids.Any() == false)
return new List<IMedia>();
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
return repository.GetAll(ids);
@@ -421,7 +414,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
public IEnumerable<IMedia> GetChildren(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.ParentId == id);
@@ -494,7 +487,7 @@ namespace Umbraco.Core.Services
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
@@ -558,7 +551,7 @@ namespace Umbraco.Core.Services
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder;
@@ -602,7 +595,7 @@ namespace Umbraco.Core.Services
if (media.ValidatePath() == false)
throw new InvalidDataException(string.Format("The content item {0} has an invalid path: {1} with parentID: {2}", media.Id, media.Path, media.ParentId));
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var pathMatch = media.Path + ",";
@@ -642,7 +635,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
public IEnumerable<IMedia> GetMediaOfMediaType(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.ContentTypeId == id);
@@ -656,7 +649,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
public IEnumerable<IMedia> GetRootMedia()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.ParentId == -1);
@@ -670,7 +663,7 @@ namespace Umbraco.Core.Services
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
public IEnumerable<IMedia> GetMediaInRecycleBin()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.Path.Contains("-21"));
@@ -707,11 +700,11 @@ namespace Umbraco.Core.Services
var sql = createSql(umbracoFileValue);
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var propertyDataDto = uow.Database.Fetch<PropertyDataDto, PropertyTypeDto>(sql).FirstOrDefault();
// If the stripped-down url returns null, we try again with the original url.
// If the stripped-down url returns null, we try again with the original url.
// Previously, the function would fail on e.g. "my_x_image.jpg"
if (propertyDataDto == null)
{
@@ -754,7 +747,7 @@ namespace Umbraco.Core.Services
/// <returns>True if the media has any children otherwise False</returns>
public bool HasChildren(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.ParentId == id);
@@ -784,14 +777,13 @@ namespace Umbraco.Core.Services
return;
}
using (var scope = UowProvider.ScopeProvider.CreateScope())
using (var uow = UowProvider.GetUnitOfWork())
{
scope.Complete(); // always complete
var originalPath = media.Path;
if (scope.Events.DispatchCancelable(Moving, this, new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(media, originalPath, parentId)), "Moving"))
if (uow.Events.DispatchCancelable(Moving, this, new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(media, originalPath, parentId)), "Moving"))
{
uow.Commit();
return;
}
@@ -800,15 +792,13 @@ namespace Umbraco.Core.Services
{
media.ChangeTrashedState(false, parentId);
}
Save(media, userId,
//no events!
false);
Save(media, userId, false); //no events!
//used to track all the moved entities to be given to the event
var moveInfo = new List<MoveEventInfo<IMedia>>
{
new MoveEventInfo<IMedia>(media, originalPath, parentId)
};
{
new MoveEventInfo<IMedia>(media, originalPath, parentId)
};
//Ensure that relevant properties are updated on children
var children = GetChildren(media.Id).ToArray();
@@ -818,14 +808,13 @@ namespace Umbraco.Core.Services
var parentLevel = media.Level;
var parentTrashed = media.Trashed;
var updatedDescendants = UpdatePropertiesOnChildren(children, parentPath, parentLevel, parentTrashed, moveInfo);
Save(updatedDescendants, userId,
//no events!
false);
Save(updatedDescendants, userId, false); //no events!
}
scope.Events.Dispatch(Moved, this, new MoveEventArgs<IMedia>(false, moveInfo.ToArray()), "Moved");
uow.Events.Dispatch(Moved, this, new MoveEventArgs<IMedia>(false, moveInfo.ToArray()), "Moved");
Audit(AuditType.Move, "Move Media performed by user", userId, media.Id);
Audit(uow, AuditType.Move, "Move Media performed by user", userId, media.Id);
uow.Commit();
}
}
}
@@ -854,31 +843,35 @@ namespace Umbraco.Core.Services
//TODO: IT would be much nicer to mass delete all in one trans in the repo level!
var evtMsgs = EventMessagesFactory.Get();
using (var scope = UowProvider.ScopeProvider.CreateScope())
using (var uow = UowProvider.GetUnitOfWork())
{
scope.Complete(); // always
if (scope.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMedia>(media, evtMsgs)))
return OperationStatus.Cancelled(evtMsgs);
var ret = DeleteUow(uow, media, userId, evtMsgs);
uow.Commit();
return ret;
}
}
private Attempt<OperationStatus> DeleteUow(IScopeUnitOfWork uow, IMedia media, int userId, EventMessages evtMsgs)
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMedia>(media, evtMsgs)))
{
return OperationStatus.Cancelled(evtMsgs);
}
//Delete children before deleting the 'possible parent'
// delete children first
var children = GetChildren(media.Id);
foreach (var child in children)
{
Delete(child, userId);
DeleteUow(uow, child, userId, evtMsgs);
}
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.Delete(media);
uow.Commit();
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.Delete(media);
var args = new DeleteEventArgs<IMedia>(media, false, evtMsgs);
uow.Events.Dispatch(Deleted, this, args);
}
var args = new DeleteEventArgs<IMedia>(media, false, evtMsgs);
uow.Events.Dispatch(Deleted, this, args);
Audit(AuditType.Delete, "Delete Media performed by user", userId, media.Id);
Audit(uow, AuditType.Delete, "Delete Media performed by user", userId, media.Id);
return OperationStatus.Success(evtMsgs);
}
@@ -895,10 +888,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents)
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(media, evtMsgs)))
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(media, evtMsgs)))
return OperationStatus.Cancelled(evtMsgs);
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
if (string.IsNullOrWhiteSpace(media.Name))
@@ -916,13 +909,12 @@ namespace Umbraco.Core.Services
repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, m));
}
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(media, false, evtMsgs));
}
Audit(AuditType.Save, "Save Media performed by user", userId, media.Id);
Audit(uow, AuditType.Save, "Save Media performed by user", userId, media.Id);
uow.Commit();
}
return OperationStatus.Success(evtMsgs);
}
@@ -940,10 +932,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents)
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(asArray, evtMsgs)))
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(asArray, evtMsgs)))
return OperationStatus.Cancelled(evtMsgs);
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
var repository = RepositoryFactory.CreateMediaRepository(uow);
@@ -959,14 +951,12 @@ namespace Umbraco.Core.Services
}
}
//commit the whole lot in one go
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(asArray, false, evtMsgs));
}
Audit(AuditType.Save, "Save Media items performed by user", userId, -1);
Audit(uow, AuditType.Save, "Save Media items performed by user", userId, -1);
uow.Commit();
}
return OperationStatus.Success(evtMsgs);
}
@@ -978,18 +968,14 @@ namespace Umbraco.Core.Services
{
using (new WriteLock(Locker))
{
Dictionary<int, IEnumerable<Property>> entities;
List<string> files;
bool success;
var nodeObjectType = new Guid(Constants.ObjectTypes.Media);
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
entities = repository.GetEntitiesInRecycleBin().ToDictionary(key => key.Id, val => (IEnumerable<Property>)val.Properties);
var entities = repository.GetEntitiesInRecycleBin().ToDictionary(key => key.Id, val => (IEnumerable<Property>)val.Properties);
files = ((MediaRepository)repository).GetFilesInRecycleBinForUploadField();
uow.Commit();
var files = ((MediaRepository)repository).GetFilesInRecycleBinForUploadField();
if (uow.Events.DispatchCancelable(EmptyingRecycleBin, this, new RecycleBinEventArgs(nodeObjectType, entities, files)))
{
@@ -997,17 +983,19 @@ namespace Umbraco.Core.Services
return;
}
success = repository.EmptyRecycleBin();
// FIXME shouldn't we commit here?!
var success = repository.EmptyRecycleBin();
uow.Events.Dispatch(EmptiedRecycleBin, this, new RecycleBinEventArgs(nodeObjectType, entities, files, success));
Audit(uow, AuditType.Delete, "Empty Media Recycle Bin performed by user", 0, -21);
uow.Commit();
}
}
Audit(AuditType.Delete, "Empty Media Recycle Bin performed by user", 0, -21);
}
/// <summary>
/// Deletes all content of the specified types. All Descendants of deleted content that is not of these types is moved to Recycle Bin.
/// </summary>
/// </summary>
/// <param name="mediaTypeIds">Id of the <see cref="IContentType"/></param>
/// <param name="userId">Optional Id of the user issueing the delete operation</param>
public void DeleteMediaOfTypes(IEnumerable<int> mediaTypeIds, int userId = 0)
@@ -1032,12 +1020,8 @@ namespace Umbraco.Core.Services
//Determine the items that will need to be recycled (that are children of these content items but not of these content types)
var mediaToRecycle = this.TrackTrashedForDeleteContentOfTypes(mediaTypeIds, rootItems, repository);
// do it INSIDE the UOW because nested UOW kinda should work
// fixme - and then we probably don't need the whole mess?
// nesting UOW works, it's just that the outer one NEEDS to be flushed beforehand
// nevertheless, it would be nicer to create a global scope and inner uow
//move each item to the bin starting with the deepest items
// move each item to the bin starting with the deepest items
// nesting uow - technically supported though not ideal
foreach (var child in mediaToRecycle.OrderByDescending(x => x.Level))
{
MoveToRecycleBinDo(child, userId, true);
@@ -1048,12 +1032,10 @@ namespace Umbraco.Core.Services
Delete(content, userId);
}
uow.Commit();
Audit(AuditType.Delete,
Audit(uow, AuditType.Delete,
string.Format("Delete Media of Types {0} performed by user", string.Join(",", mediaTypeIds)),
userId, Constants.System.Root);
uow.Commit();
}
}
@@ -1105,13 +1087,13 @@ namespace Umbraco.Core.Services
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
}
var moveInfo = new List<MoveEventInfo<IMedia>>
{
new MoveEventInfo<IMedia>(media, originalPath, Constants.System.RecycleBinMedia)
};
//get descendents to process of the content item that is being moved to trash - must be done before changing the state below,
//get descendents to process of the content item that is being moved to trash - must be done before changing the state below,
//must be processed with shallowest levels first
var descendants = ignoreDescendants ? Enumerable.Empty<IMedia>() : GetDescendants(media).OrderBy(x => x.Level);
@@ -1120,7 +1102,7 @@ namespace Umbraco.Core.Services
repository.DeleteContentXml(media);
media.ChangeTrashedState(true, Constants.System.RecycleBinMedia);
repository.AddOrUpdate(media);
//Loop through descendants to update their trash state, but ensuring structure by keeping the ParentId
foreach (var descendant in descendants)
{
@@ -1131,12 +1113,11 @@ namespace Umbraco.Core.Services
moveInfo.Add(new MoveEventInfo<IMedia>(descendant, descendant.Path, descendant.ParentId));
}
uow.Commit();
uow.Events.Dispatch(Trashed, this, new MoveEventArgs<IMedia>(false, evtMsgs, moveInfo.ToArray()), "Trashed");
}
Audit(AuditType.Move, "Move Media to Recycle Bin performed by user", userId, media.Id);
Audit(uow, AuditType.Move, "Move Media to Recycle Bin performed by user", userId, media.Id);
uow.Commit();
}
return OperationStatus.Success(evtMsgs);
}
@@ -1166,19 +1147,22 @@ namespace Umbraco.Core.Services
/// <param name="userId">Optional Id of the User deleting versions of a Content object</param>
public void DeleteVersions(int id, DateTime versionDate, int userId = 0)
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingVersions, this, new DeleteRevisionsEventArgs(id, dateToRetain: versionDate)))
return;
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.DeleteVersions(id, versionDate);
DeleteVersions(uow, id, versionDate, userId);
uow.Commit();
uow.Events.Dispatch(DeletedVersions, this, new DeleteRevisionsEventArgs(id, false, dateToRetain: versionDate));
}
}
Audit(AuditType.Delete, "Delete Media by version date performed by user", userId, -1);
private void DeleteVersions(IScopeUnitOfWork uow, int id, DateTime versionDate, int userId = 0)
{
if (uow.Events.DispatchCancelable(DeletingVersions, this, new DeleteRevisionsEventArgs(id, dateToRetain: versionDate)))
return;
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.DeleteVersions(id, versionDate);
uow.Events.Dispatch(DeletedVersions, this, new DeleteRevisionsEventArgs(id, false, dateToRetain: versionDate));
Audit(uow, AuditType.Delete, "Delete Media by version date performed by user", userId, -1);
}
/// <summary>
@@ -1191,28 +1175,28 @@ namespace Umbraco.Core.Services
/// <param name="userId">Optional Id of the User deleting versions of a Content object</param>
public void DeleteVersion(int id, Guid versionId, bool deletePriorVersions, int userId = 0)
{
using (var scope = UowProvider.ScopeProvider.CreateScope())
{
scope.Complete(); // always
if (scope.Events.DispatchCancelable(DeletingVersions, this, new DeleteRevisionsEventArgs(id, specificVersion: versionId)))
return;
}
if (deletePriorVersions)
{
var content = GetByVersion(versionId);
DeleteVersions(id, content.UpdateDate, userId);
}
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingVersions, this, new DeleteRevisionsEventArgs(id, specificVersion: versionId)))
{
uow.Commit();
return;
}
if (deletePriorVersions)
{
var content = GetByVersion(versionId);
DeleteVersions(uow, id, content.UpdateDate, userId);
}
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.DeleteVersion(versionId);
uow.Commit();
uow.Events.Dispatch(DeletedVersions, this, new DeleteRevisionsEventArgs(id, false, specificVersion: versionId));
}
Audit(AuditType.Delete, "Delete Media by version performed by user", userId, -1);
uow.Events.Dispatch(DeletedVersions, this, new DeleteRevisionsEventArgs(id, false, specificVersion: versionId));
Audit(uow, AuditType.Delete, "Delete Media by version performed by user", userId, -1);
uow.Commit();
}
}
/// <summary>
@@ -1251,13 +1235,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents)
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(asArray)))
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(asArray)))
{
uow.Commit();
return false;
}
uow.Commit();
return false;
}
var repository = RepositoryFactory.CreateMediaRepository(uow);
@@ -1285,13 +1266,12 @@ namespace Umbraco.Core.Services
}
}
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(asArray, false));
}
Audit(AuditType.Sort, "Sorting Media performed by user", userId, 0);
Audit(uow, AuditType.Sort, "Sorting Media performed by user", userId, 0);
uow.Commit();
}
return true;
}
@@ -1309,7 +1289,7 @@ namespace Umbraco.Core.Services
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
return repository.GetPagedXmlEntriesByPath(path, pageIndex, pageSize, null, out totalRecords);
@@ -1329,10 +1309,10 @@ namespace Umbraco.Core.Services
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.RebuildXmlStructures(media => _entitySerializer.Serialize(this, _dataTypeService, _userService, media), contentTypeIds: contentTypeIds.Length == 0 ? null : contentTypeIds);
Audit(uow, AuditType.Publish, "MediaService.RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
uow.Commit();
}
Audit(AuditType.Publish, "MediaService.RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
}
/// <summary>
@@ -1381,7 +1361,7 @@ namespace Umbraco.Core.Services
{
Mandate.ParameterNotNullOrEmpty(mediaTypeAlias, "mediaTypeAlias");
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaTypeRepository(uow);
var query = Query<IMediaType>.Builder.Where(x => x.Alias == mediaTypeAlias);
@@ -1399,14 +1379,10 @@ namespace Umbraco.Core.Services
}
}
private void Audit(AuditType type, string message, int userId, int objectId)
private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId)
{
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
uow.Commit();
}
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
}
/// <summary>
@@ -1455,6 +1431,7 @@ namespace Umbraco.Core.Services
_mediaFileSystem.DeleteFile(filepath, true);
}
[Obsolete("This should no longer be used, thumbnail generation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public void GenerateThumbnails(string filepath, PropertyType propertyType)
{
using (var filestream = _mediaFileSystem.OpenFile(filepath))
@@ -1468,7 +1445,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Occurs before Delete
/// </summary>
/// </summary>
public static event TypedEventHandler<IMediaService, DeleteRevisionsEventArgs> DeletingVersions;
/// <summary>
+13 -16
View File
@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
@@ -40,12 +37,12 @@ namespace Umbraco.Core.Services
scope.Complete(); // always complete
scope.Events.Dispatch(Saved, this, new SaveEventArgs<IMemberGroup>(e.SavedEntities, false));
}
}
}
#endregion
public IEnumerable<IMemberGroup> GetAll()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
return repository.GetAll();
@@ -54,7 +51,7 @@ namespace Umbraco.Core.Services
public IMemberGroup GetById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
return repository.Get(id);
@@ -63,7 +60,7 @@ namespace Umbraco.Core.Services
public IMemberGroup GetByName(string name)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
return repository.GetByName(name);
@@ -74,13 +71,10 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents)
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMemberGroup>(memberGroup)))
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMemberGroup>(memberGroup)))
{
uow.Commit();
return;
}
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
@@ -90,7 +84,7 @@ namespace Umbraco.Core.Services
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMemberGroup>(memberGroup, false));
}
}
public void Delete(IMemberGroup memberGroup)
@@ -98,7 +92,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMemberGroup>(memberGroup)))
return; // FIXME COMMIT
{
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
repository.Delete(memberGroup);
uow.Commit();
@@ -118,7 +115,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Occurs before Save of a member group
/// </summary>
/// </summary>
/// <remarks>
/// We need to proxy these events because the events need to take place at the repo level
/// </remarks>
+61 -67
View File
@@ -4,17 +4,14 @@ using System.ComponentModel;
using System.Threading;
using System.Web.Security;
using System.Xml.Linq;
using Umbraco.Core.Auditing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using System.Linq;
using Umbraco.Core.Security;
@@ -50,7 +47,7 @@ namespace Umbraco.Core.Services
/// <returns>Alias of the default MemberType</returns>
public string GetDefaultMemberType()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberTypeRepository(uow);
@@ -76,7 +73,7 @@ namespace Umbraco.Core.Services
/// <returns><c>True</c> if the Member exists otherwise <c>False</c></returns>
public bool Exists(string username)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.Exists(username);
@@ -123,7 +120,7 @@ namespace Umbraco.Core.Services
/// <returns><c>True</c> if the Member exists otherwise <c>False</c></returns>
public bool Exists(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.Exists(id);
@@ -137,7 +134,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMember"/></returns>
public IMember GetById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.Get(id);
@@ -153,7 +150,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMember"/></returns>
public IMember GetByKey(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
var query = Query<IMember>.Builder.Where(x => x.Key == id);
@@ -168,7 +165,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> GetMembersByMemberType(string memberTypeAlias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
var query = Query<IMember>.Builder.Where(x => x.ContentTypeAlias == memberTypeAlias);
@@ -183,7 +180,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> GetMembersByMemberType(int memberTypeId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
repository.Get(memberTypeId);
@@ -199,7 +196,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> GetMembersByGroup(string memberGroupName)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.GetByMemberGroup(memberGroupName);
@@ -214,7 +211,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> GetAllMembers(params int[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.GetAll(ids);
@@ -229,8 +226,6 @@ namespace Umbraco.Core.Services
{
using (new WriteLock(Locker))
{
var memberList = new List<IMember>();
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
@@ -246,9 +241,8 @@ namespace Umbraco.Core.Services
}
foreach (var member in members)
{
//Permantly delete the member
// FIXME implies a nested UOW = bad so ?
Delete(member);
// permantly delete the member
Delete(uow, member);
}
uow.Commit();
@@ -277,7 +271,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> FindMembersByDisplayName(string displayNameToMatch, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
var query = new Query<IMember>();
@@ -328,7 +322,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> FindByEmail(string emailStringToMatch, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
var query = new Query<IMember>();
@@ -379,7 +373,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> FindByUsername(string login, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
var query = new Query<IMember>();
@@ -418,7 +412,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> GetMembersByPropertyValue(string propertyTypeAlias, string value, StringPropertyMatchType matchType = StringPropertyMatchType.Exact)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
@@ -467,7 +461,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> GetMembersByPropertyValue(string propertyTypeAlias, int value, ValuePropertyMatchType matchType = ValuePropertyMatchType.Exact)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
@@ -506,7 +500,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> GetMembersByPropertyValue(string propertyTypeAlias, bool value)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
@@ -524,7 +518,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> GetMembersByPropertyValue(string propertyTypeAlias, DateTime value, ValuePropertyMatchType matchType = ValuePropertyMatchType.Exact)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
@@ -572,10 +566,10 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateMemberRepository(uow);
repository.RebuildXmlStructures(member => _entitySerializer.Serialize(_dataTypeService, member),
contentTypeIds: memberTypeIds.Length == 0 ? null : memberTypeIds);
Audit(uow, AuditType.Publish, "MemberService.RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
uow.Commit();
}
Audit(AuditType.Publish, "MemberService.RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
}
/// <summary>
@@ -590,11 +584,10 @@ namespace Umbraco.Core.Services
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
var uow = UowProvider.GetUnitOfWork();
using (var repository = RepositoryFactory.CreateMemberRepository(uow))
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var contents = repository.GetPagedXmlEntriesByPath("-1", pageIndex, pageSize, null, out totalRecords);
return contents;
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.GetPagedXmlEntriesByPath("-1", pageIndex, pageSize, null, out totalRecords);
}
}
@@ -614,7 +607,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="System.int"/> with number of Members for passed in type</returns>
public int GetCount(MemberCountType countType)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
@@ -666,7 +659,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IMember> GetAll(long pageIndex, int pageSize, out long totalRecords)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending, true);
@@ -693,7 +686,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IMember> GetAll(long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, bool orderBySystemField, string memberTypeAlias, string filter)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
IQuery<IMember> filterQuery = null;
if (filter.IsNullOrWhiteSpace() == false)
@@ -725,7 +718,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="System.int"/> with number of Members</returns>
public int Count(string memberTypeAlias = null)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.Count(memberTypeAlias);
@@ -906,7 +899,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMember"/></returns>
public IMember GetByEmail(string email)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
var query = Query<IMember>.Builder.Where(x => x.Email.Equals(email));
@@ -925,7 +918,7 @@ namespace Umbraco.Core.Services
// a caching mechanism since this method is used by all the membership providers and could be
// called quite a bit when dealing with members.
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
var query = Query<IMember>.Builder.Where(x => x.Username.Equals(username));
@@ -941,21 +934,27 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMember>(member)))
{
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateMemberRepository(uow);
repository.Delete(member);
Delete(uow, member);
uow.Commit();
var args = new DeleteEventArgs<IMember>(member, false);
uow.Events.Dispatch(Deleted, this, args);
}
}
private void Delete(IScopeUnitOfWork uow, IMember member)
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMember>(member)))
{
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateMemberRepository(uow);
repository.Delete(member);
uow.Commit();
var args = new DeleteEventArgs<IMember>(member, false);
uow.Events.Dispatch(Deleted, this, args);
}
/// <summary>
/// Saves an <see cref="IMember"/>
/// </summary>
@@ -1011,14 +1010,12 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents)
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMember>(asArray)))
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMember>(asArray)))
{
uow.Commit();
return;
}
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateMemberRepository(uow);
foreach (var member in asArray)
{
@@ -1058,7 +1055,7 @@ namespace Umbraco.Core.Services
public IEnumerable<string> GetAllRoles()
{
using (var uow = UowProvider.GetUnitOfWork())
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
var result = repository.GetAll();
@@ -1068,7 +1065,7 @@ namespace Umbraco.Core.Services
public IEnumerable<string> GetAllRoles(int memberId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
var result = repository.GetMemberGroupsForMember(memberId);
@@ -1078,7 +1075,7 @@ namespace Umbraco.Core.Services
public IEnumerable<string> GetAllRoles(string username)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
var result = repository.GetMemberGroupsForMember(username);
@@ -1088,7 +1085,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IMember> GetMembersInRole(string roleName)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.GetByMemberGroup(roleName);
@@ -1097,7 +1094,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IMember> FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberRepository(uow);
return repository.FindMembersInRole(roleName, usernameToMatch, matchType);
@@ -1119,7 +1116,7 @@ namespace Umbraco.Core.Services
List<IMemberGroup> found;
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
var qry = new Query<IMemberGroup>().Where(g => g.Name == roleName);
@@ -1199,7 +1196,7 @@ namespace Umbraco.Core.Services
private IMemberType FindMemberTypeByAlias(string memberTypeAlias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateMemberTypeRepository(uow);
var query = Query<IMemberType>.Builder.Where(x => x.Alias == memberTypeAlias);
@@ -1213,19 +1210,16 @@ namespace Umbraco.Core.Services
if (contentType == null)
throw new Exception(string.Format("MemberType matching the passed in Alias: '{0}' was null", memberTypeAlias));
uow.Commit();
return contentType;
}
}
private void Audit(AuditType type, string message, int userId, int objectId)
private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId)
{
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
uow.Commit();
}
var repository = RepositoryFactory.CreateAuditRepository(uow);
repository.AddOrUpdate(new AuditItem(objectId, message, type, userId));
}
#region Event Handlers
+12 -14
View File
@@ -2,12 +2,10 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Umbraco.Core.Auditing;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
@@ -18,7 +16,6 @@ namespace Umbraco.Core.Services
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
public MemberTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IMemberService memberService)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
@@ -28,7 +25,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IMemberType> GetAll(params int[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberTypeRepository(uow);
return repository.GetAll(ids);
@@ -42,7 +39,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMemberType"/></returns>
public IMemberType Get(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberTypeRepository(uow);
return repository.Get(id);
@@ -56,7 +53,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMemberType"/></returns>
public IMemberType Get(Guid key)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberTypeRepository(uow);
return repository.Get(key);
@@ -70,7 +67,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMemberType"/></returns>
public IMemberType Get(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMemberTypeRepository(uow);
return repository.Get(alias);
@@ -96,11 +93,13 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateMemberTypeRepository(uow);
memberType.CreatorId = userId;
if (memberType.Description == string.Empty)
memberType.Description = null;
repository.AddOrUpdate(memberType);
uow.Commit(); // flush, so that the db contains the saved value
uow.Commit(); // fixme double?
UpdateContentXmlStructure(memberType);
uow.Commit();
uow.Commit(); // actually commit uow
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMemberType>(memberType, false));
}
@@ -124,15 +123,14 @@ namespace Umbraco.Core.Services
foreach (var memberType in asArray)
{
memberType.CreatorId = userId;
if (memberType.Description == string.Empty)
memberType.Description = null;
repository.AddOrUpdate(memberType);
}
uow.Commit(); // fixme double?
uow.Commit(); // flush, so that the db contains the saved values
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray());
//save it all in one go
uow.Commit();
uow.Commit(); // actually commit uow
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMemberType>(asArray, false));
}
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public IEnumerable<PublicAccessEntry> GetAll()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repo = RepositoryFactory.CreatePublicAccessRepository(uow);
return repo.GetAll();
@@ -69,7 +69,7 @@ namespace Umbraco.Core.Services
//start with the deepest id
ids.Reverse();
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
//This will retrieve from cache!
var repo = RepositoryFactory.CreatePublicAccessRepository(uow);
@@ -220,7 +220,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<PublicAccessEntry>(entry, evtMsgs)))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
var repo = RepositoryFactory.CreatePublicAccessRepository(uow);
repo.AddOrUpdate(entry);
@@ -243,7 +246,10 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<PublicAccessEntry>(entry, evtMsgs)))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
var repo = RepositoryFactory.CreatePublicAccessRepository(uow);
repo.Delete(entry);
+19 -33
View File
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Services
/// <returns>A <see cref="Relation"/> object</returns>
public IRelation GetById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
return repository.Get(id);
@@ -43,7 +43,7 @@ namespace Umbraco.Core.Services
/// <returns>A <see cref="RelationType"/> object</returns>
public IRelationType GetRelationTypeById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationTypeRepository(uow);
return repository.Get(id);
@@ -57,7 +57,7 @@ namespace Umbraco.Core.Services
/// <returns>A <see cref="RelationType"/> object</returns>
public IRelationType GetRelationTypeById(Guid id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationTypeRepository(uow);
return repository.Get(id);
@@ -71,7 +71,7 @@ namespace Umbraco.Core.Services
/// <returns>A <see cref="RelationType"/> object</returns>
public IRelationType GetRelationTypeByAlias(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationTypeRepository(uow);
var query = new Query<IRelationType>().Where(x => x.Alias == alias);
@@ -86,7 +86,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
public IEnumerable<IRelation> GetAllRelations(params int[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
return repository.GetAll(ids);
@@ -110,7 +110,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
public IEnumerable<IRelation> GetAllRelationsByRelationType(int relationTypeId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
var query = new Query<IRelation>().Where(x => x.RelationTypeId == relationTypeId);
@@ -125,7 +125,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="RelationType"/> objects</returns>
public IEnumerable<IRelationType> GetAllRelationTypes(params int[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationTypeRepository(uow);
return repository.GetAll(ids);
@@ -139,7 +139,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
public IEnumerable<IRelation> GetByParentId(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
var query = new Query<IRelation>().Where(x => x.ParentId == id);
@@ -175,7 +175,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
public IEnumerable<IRelation> GetByChildId(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
var query = new Query<IRelation>().Where(x => x.ChildId == id);
@@ -212,7 +212,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
public IEnumerable<IRelation> GetByParentOrChildId(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
var query = new Query<IRelation>().Where(x => x.ParentId == id || x.ChildId == id);
@@ -222,7 +222,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IRelation> GetByParentOrChildId(int id, string relationTypeAlias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var typeRepository = RepositoryFactory.CreateRelationTypeRepository(uow);
var rtQuery = new Query<IRelationType>().Where(x => x.Alias == relationTypeAlias);
@@ -243,7 +243,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IRelation> GetByRelationTypeName(string relationTypeName)
{
List<int> relationTypeIds = null;
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationTypeRepository(uow);
var query = new Query<IRelationType>().Where(x => x.Name == relationTypeName);
@@ -268,7 +268,7 @@ namespace Umbraco.Core.Services
public IEnumerable<IRelation> GetByRelationTypeAlias(string relationTypeAlias)
{
List<int> relationTypeIds = null;
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationTypeRepository(uow);
var query = new Query<IRelationType>().Where(x => x.Alias == relationTypeAlias);
@@ -292,7 +292,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
public IEnumerable<IRelation> GetByRelationTypeId(int relationTypeId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
var query = new Query<IRelation>().Where(x => x.RelationTypeId == relationTypeId);
@@ -423,8 +423,6 @@ namespace Umbraco.Core.Services
uow.Events.Dispatch(SavedRelation, this, new SaveEventArgs<IRelation>(relation, false));
return relation;
}
}
/// <summary>
@@ -456,8 +454,6 @@ namespace Umbraco.Core.Services
uow.Events.Dispatch(SavedRelation, this, new SaveEventArgs<IRelation>(relation, false));
return relation;
}
}
/// <summary>
@@ -467,7 +463,7 @@ namespace Umbraco.Core.Services
/// <returns>Returns <c>True</c> if any relations exists for the given <see cref="RelationType"/>, otherwise <c>False</c></returns>
public bool HasRelations(IRelationType relationType)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
var query = new Query<IRelation>().Where(x => x.RelationTypeId == relationType.Id);
@@ -482,7 +478,7 @@ namespace Umbraco.Core.Services
/// <returns>Returns <c>True</c> if any relations exists with the given Id, otherwise <c>False</c></returns>
public bool IsRelated(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
var query = new Query<IRelation>().Where(x => x.ParentId == id || x.ChildId == id);
@@ -498,7 +494,7 @@ namespace Umbraco.Core.Services
/// <returns>Returns <c>True</c> if any relations exists with the given Ids, otherwise <c>False</c></returns>
public bool AreRelated(int parentId, int childId)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
var query = new Query<IRelation>().Where(x => x.ParentId == parentId && x.ChildId == childId);
@@ -532,7 +528,7 @@ namespace Umbraco.Core.Services
/// <returns>Returns <c>True</c> if any relations exists with the given Ids and relation type, otherwise <c>False</c></returns>
public bool AreRelated(int parentId, int childId, IRelationType relationType)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
var query = new Query<IRelation>().Where(x => x.ParentId == parentId && x.ChildId == childId && x.RelationTypeId == relationType.Id);
@@ -582,8 +578,6 @@ namespace Umbraco.Core.Services
uow.Commit();
uow.Events.Dispatch(SavedRelation, this, new SaveEventArgs<IRelation>(relation, false));
}
}
/// <summary>
@@ -604,8 +598,6 @@ namespace Umbraco.Core.Services
uow.Commit();
uow.Events.Dispatch(SavedRelationType, this, new SaveEventArgs<IRelationType>(relationType, false));
}
}
/// <summary>
@@ -625,9 +617,7 @@ namespace Umbraco.Core.Services
repository.Delete(relation);
uow.Commit();
uow.Events.Dispatch(DeletedRelation, this, new DeleteEventArgs<IRelation>(relation, false));
}
}
/// <summary>
@@ -647,9 +637,7 @@ namespace Umbraco.Core.Services
repository.Delete(relationType);
uow.Commit();
uow.Events.Dispatch(DeletedRelationType, this, new DeleteEventArgs<IRelationType>(relationType, false));
}
}
/// <summary>
@@ -671,16 +659,14 @@ namespace Umbraco.Core.Services
}
uow.Commit();
uow.Events.Dispatch(DeletedRelation, this, new DeleteEventArgs<IRelation>(relations, false));
}
}
#region Private Methods
private IEnumerable<IRelation> GetRelationsByListOfTypeIds(IEnumerable<int> relationTypeIds)
{
var relations = new List<IRelation>();
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
foreach (var relationTypeId in relationTypeIds)
+2 -4
View File
@@ -2,13 +2,11 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.UnitOfWork;
using File = System.IO.File;
@@ -19,7 +17,7 @@ namespace Umbraco.Core.Services
private readonly IUserService _userService;
private IEnumerable<Section> _allAvailableSections;
private readonly IApplicationTreeService _applicationTreeService;
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly IScopeUnitOfWorkProvider _uowProvider;
private readonly CacheHelper _cache;
internal const string AppConfigFileName = "applications.config";
private static string _appConfig;
@@ -29,7 +27,7 @@ namespace Umbraco.Core.Services
public SectionService(
IUserService userService,
IApplicationTreeService applicationTreeService,
IDatabaseUnitOfWorkProvider uowProvider,
IScopeUnitOfWorkProvider uowProvider,
CacheHelper cache)
{
if (applicationTreeService == null) throw new ArgumentNullException("applicationTreeService");
+16 -41
View File
@@ -1,12 +1,10 @@
using System;
using System.ComponentModel;
using Umbraco.Core.Logging;
using System.IO;
using System.Linq;
using Umbraco.Core.IO;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
using Umbraco.Core.Events;
namespace Umbraco.Core.Services
@@ -15,7 +13,7 @@ namespace Umbraco.Core.Services
/// These are used currently to return the temporary 'operation' interfaces for services
/// which are used to return a status from operational methods so we can determine if things are
/// cancelled, etc...
///
///
/// These will be obsoleted in v8 since all real services methods will be changed to have the correct result.
/// </summary>
public static class ServiceWithResultExtensions
@@ -37,11 +35,11 @@ namespace Umbraco.Core.Services
/// </summary>
public class ServiceContext
{
private Lazy<IMigrationEntryService> _migrationEntryService;
private Lazy<IPublicAccessService> _publicAccessService;
private Lazy<ITaskService> _taskService;
private Lazy<IDomainService> _domainService;
private Lazy<IAuditService> _auditService;
private Lazy<IMigrationEntryService> _migrationEntryService;
private Lazy<IPublicAccessService> _publicAccessService;
private Lazy<ITaskService> _taskService;
private Lazy<IDomainService> _domainService;
private Lazy<IAuditService> _auditService;
private Lazy<ILocalizedTextService> _localizedTextService;
private Lazy<ITagService> _tagService;
private Lazy<IContentService> _contentService;
@@ -150,49 +148,30 @@ namespace Umbraco.Core.Services
if (redirectUrlService != null) _redirectUrlService = new Lazy<IRedirectUrlService>(() => redirectUrlService);
}
// fixme - but this is obsoleting a new method?!!?!!?
[Obsolete("The IPublishingStrategy parameter is no longer required and not used")]
[EditorBrowsable(EditorBrowsableState.Never)]
public ServiceContext(
RepositoryFactory repositoryFactory,
IScopeUnitOfWorkProvider dbUnitOfWorkProvider,
IScopeUnitOfWorkProvider fileUnitOfWorkProvider,
IPublishingStrategy publishingStrategy,
CacheHelper cache,
ILogger logger,
IEventMessagesFactory eventMessagesFactory)
: this(repositoryFactory, dbUnitOfWorkProvider, fileUnitOfWorkProvider, cache, logger, eventMessagesFactory)
{ }
// fixme CLEAN THIS
/// <summary>
/// Creates a service context with a RepositoryFactory which is used to construct Services
/// </summary>
/// <param name="repositoryFactory"></param>
/// <param name="dbUnitOfWorkProvider"></param>
/// <param name="fileUnitOfWorkProvider"></param>
/// <param name="provider"></param>
/// <param name="cache"></param>
/// <param name="logger"></param>
/// <param name="eventMessagesFactory"></param>
public ServiceContext(
RepositoryFactory repositoryFactory,
IScopeUnitOfWorkProvider dbUnitOfWorkProvider,
IScopeUnitOfWorkProvider fileUnitOfWorkProvider,
CacheHelper cache,
IScopeUnitOfWorkProvider provider,
CacheHelper cache,
ILogger logger,
IEventMessagesFactory eventMessagesFactory)
{
if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory");
if (dbUnitOfWorkProvider == null) throw new ArgumentNullException("dbUnitOfWorkProvider");
if (fileUnitOfWorkProvider == null) throw new ArgumentNullException("fileUnitOfWorkProvider");
if (provider == null) throw new ArgumentNullException("provider");
if (cache == null) throw new ArgumentNullException("cache");
if (logger == null) throw new ArgumentNullException("logger");
if (eventMessagesFactory == null) throw new ArgumentNullException("eventMessagesFactory");
EventMessagesFactory = eventMessagesFactory;
BuildServiceCache(dbUnitOfWorkProvider, fileUnitOfWorkProvider, cache,
BuildServiceCache(provider, cache,
repositoryFactory,
logger, eventMessagesFactory);
}
@@ -201,8 +180,7 @@ namespace Umbraco.Core.Services
/// Builds the various services
/// </summary>
private void BuildServiceCache(
IScopeUnitOfWorkProvider dbUnitOfWorkProvider,
IScopeUnitOfWorkProvider fileUnitOfWorkProvider,
IScopeUnitOfWorkProvider provider,
CacheHelper cache,
RepositoryFactory repositoryFactory,
ILogger logger,
@@ -210,9 +188,6 @@ namespace Umbraco.Core.Services
{
EventMessagesFactory = eventMessagesFactory;
var provider = dbUnitOfWorkProvider;
var fileProvider = fileUnitOfWorkProvider;
if (_migrationEntryService == null)
_migrationEntryService = new Lazy<IMigrationEntryService>(() => new MigrationEntryService(provider, repositoryFactory, logger, eventMessagesFactory));
@@ -233,7 +208,7 @@ namespace Umbraco.Core.Services
if (_localizedTextService == null)
{
_localizedTextService = new Lazy<ILocalizedTextService>(() => new LocalizedTextService(
new Lazy<LocalizedTextServiceFileSources>(() =>
{
@@ -266,7 +241,7 @@ namespace Umbraco.Core.Services
}),
logger));
}
if (_notificationService == null)
_notificationService = new Lazy<INotificationService>(() => new NotificationService(provider, _userService.Value, _contentService.Value, logger));
@@ -293,7 +268,7 @@ namespace Umbraco.Core.Services
_dataTypeService = new Lazy<IDataTypeService>(() => new DataTypeService(provider, repositoryFactory, logger, eventMessagesFactory));
if (_fileService == null)
_fileService = new Lazy<IFileService>(() => new FileService(fileProvider, provider, repositoryFactory, logger, eventMessagesFactory));
_fileService = new Lazy<IFileService>(() => new FileService(provider, repositoryFactory, logger, eventMessagesFactory));
if (_localizationService == null)
_localizationService = new Lazy<ILocalizationService>(() => new LocalizationService(provider, repositoryFactory, logger, eventMessagesFactory));
@@ -304,7 +279,7 @@ namespace Umbraco.Core.Services
_contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value, _memberService.Value, _memberTypeService.Value,
//TODO: Consider making this an isolated cache instead of using the global one
cache.RuntimeCache));
if (_packagingService == null)
_packagingService = new Lazy<IPackagingService>(() => new PackagingService(logger, _contentService.Value, _contentTypeService.Value, _mediaService.Value, _macroService.Value, _dataTypeService.Value, _fileService.Value, _localizationService.Value, _entityService.Value, _userService.Value, repositoryFactory, provider));
+39 -48
View File
@@ -1,8 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
@@ -38,12 +36,12 @@ namespace Umbraco.Core.Services
/// <summary>
/// Gets the default MemberType alias
/// </summary>
/// <remarks>By default we'll return the 'writer', but we need to check it exists. If it doesn't we'll
/// <remarks>By default we'll return the 'writer', but we need to check it exists. If it doesn't we'll
/// return the first type that is not an admin, otherwise if there's only one we will return that one.</remarks>
/// <returns>Alias of the default MemberType</returns>
public string GetDefaultMemberType()
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserTypeRepository(uow);
@@ -76,7 +74,7 @@ namespace Umbraco.Core.Services
/// <returns><c>True</c> if the User exists otherwise <c>False</c></returns>
public bool Exists(string username)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
return repository.Exists(username);
@@ -118,7 +116,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Creates and persists a Member
/// </summary>
/// <remarks>Using this method will persist the Member object before its returned
/// <remarks>Using this method will persist the Member object before its returned
/// meaning that it will have an Id available (unlike the CreateMember method)</remarks>
/// <param name="username">Username of the Member to create</param>
/// <param name="email">Email of the Member to create</param>
@@ -182,7 +180,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IUser"/></returns>
public IUser GetById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
return repository.Get(id);
@@ -212,7 +210,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IUser"/></returns>
public IUser GetByEmail(string email)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
var query = Query<IUser>.Builder.Where(x => x.Email.Equals(email));
@@ -227,7 +225,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IUser"/></returns>
public IUser GetByUsername(string username)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
var query = Query<IUser>.Builder.Where(x => x.Username.Equals(username));
@@ -305,9 +303,7 @@ namespace Umbraco.Core.Services
repository.Delete(user);
uow.Commit();
uow.Events.Dispatch(DeletedUser, this, new DeleteEventArgs<IUser>(user, false));
}
}
}
@@ -315,20 +311,16 @@ namespace Umbraco.Core.Services
/// Saves an <see cref="IUser"/>
/// </summary>
/// <param name="entity"><see cref="IUser"/> to Save</param>
/// <param name="raiseEvents">Optional parameter to raise events.
/// <param name="raiseEvents">Optional parameter to raise events.
/// Default is <c>True</c> otherwise set to <c>False</c> to not raise events</param>
public void Save(IUser entity, bool raiseEvents = true)
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents)
if (raiseEvents && uow.Events.DispatchCancelable(SavingUser, this, new SaveEventArgs<IUser>(entity)))
{
if (uow.Events.DispatchCancelable(SavingUser, this, new SaveEventArgs<IUser>(entity)))
{
uow.Commit();
return;
}
uow.Commit();
return;
}
if (string.IsNullOrWhiteSpace(entity.Username))
@@ -345,29 +337,34 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(entity);
try
{
uow.Commit(); // fixme? would throw on dispose not here
// try to flush the unit of work
// ie executes the SQL but does not commit the trx yet
// so we are *not* catching commit exceptions
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(SavedUser, this, new SaveEventArgs<IUser>(entity, false));
}
catch (DbException ex)
{
//Special case, if we are upgrading and an exception occurs, just continue
// if we are upgrading and an exception occurs, log and swallow it
if (IsUpgrading == false) throw;
Logger.WarnWithException<UserService>("An error occurred attempting to save a user instance during upgrade, normally this warning can be ignored", ex);
return;
// we don't want the uow to rollback its scope! and yet
// we cannot try and uow.Commit() again as it would fail again,
// we have to bypass the uow entirely and complete its inner scope.
// (when the uow disposes, it won't complete the scope again, just dispose it)
uow.Scope.Complete();
}
}
}
/// <summary>
/// Saves a list of <see cref="IUser"/> objects
/// </summary>
/// <param name="entities"><see cref="IEnumerable{IUser}"/> to save</param>
/// <param name="raiseEvents">Optional parameter to raise events.
/// <param name="raiseEvents">Optional parameter to raise events.
/// Default is <c>True</c> otherwise set to <c>False</c> to not raise events</param>
public void Save(IEnumerable<IUser> entities, bool raiseEvents = true)
{
@@ -416,7 +413,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IUser}"/></returns>
public IEnumerable<IUser> FindByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
var query = new Query<IUser>();
@@ -457,7 +454,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IUser}"/></returns>
public IEnumerable<IUser> FindByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
var query = new Query<IUser>();
@@ -499,7 +496,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="System.int"/> with number of Users for passed in type</returns>
public int GetCount(MemberCountType countType)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
@@ -545,7 +542,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IEnumerable{IMember}"/></returns>
public IEnumerable<IUser> GetAll(int pageIndex, int pageSize, out int totalRecords)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Username);
@@ -554,7 +551,7 @@ namespace Umbraco.Core.Services
internal IEnumerable<IUser> GetNextUsers(int id, int count)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = (UserRepository)RepositoryFactory.CreateUserRepository(uow);
return repository.GetNextUsers(id, count);
@@ -594,7 +591,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IUser"/></returns>
public IUser GetUserById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
return repository.Get(id);
@@ -641,7 +638,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IUserType"/></returns>
public IEnumerable<IUserType> GetAllUserTypes(params int[] ids)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserTypeRepository(uow);
return repository.GetAll(ids);
@@ -655,7 +652,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IUserType"/></returns>
public IUserType GetUserTypeByAlias(string alias)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserTypeRepository(uow);
var query = Query<IUserType>.Builder.Where(x => x.Alias == alias);
@@ -670,7 +667,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IUserType"/></returns>
public IUserType GetUserTypeById(int id)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserTypeRepository(uow);
return repository.Get(id);
@@ -684,7 +681,7 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IUserType"/></returns>
public IUserType GetUserTypeByName(string name)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserTypeRepository(uow);
var query = Query<IUserType>.Builder.Where(x => x.Name == name);
@@ -696,28 +693,24 @@ namespace Umbraco.Core.Services
/// Saves a UserType
/// </summary>
/// <param name="userType">UserType to save</param>
/// <param name="raiseEvents">Optional parameter to raise events.
/// <param name="raiseEvents">Optional parameter to raise events.
/// Default is <c>True</c> otherwise set to <c>False</c> to not raise events</param>
public void SaveUserType(IUserType userType, bool raiseEvents = true)
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents)
if (raiseEvents && uow.Events.DispatchCancelable(SavingUserType, this, new SaveEventArgs<IUserType>(userType)))
{
if (uow.Events.DispatchCancelable(SavingUserType, this, new SaveEventArgs<IUserType>(userType)))
{
uow.Commit();
return;
}
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateUserTypeRepository(uow);
repository.AddOrUpdate(userType);
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(SavedUserType, this, new SaveEventArgs<IUserType>(userType, false));
}
}
/// <summary>
@@ -737,9 +730,7 @@ namespace Umbraco.Core.Services
repository.Delete(userType);
uow.Commit();
uow.Events.Dispatch(DeletedUserType, this, new DeleteEventArgs<IUserType>(userType, false));
}
}
/// <summary>
@@ -804,7 +795,7 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="EntityPermission"/></returns>
public IEnumerable<EntityPermission> GetPermissions(IUser user, params int[] nodeIds)
{
using (var uow = UowProvider.GetUnitOfWork(commit: true))
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
var explicitPermissions = repository.GetUserPermissionsForEntities(user.Id, nodeIds);
+118 -225
View File
@@ -1,32 +1,24 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Security;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Compilation;
using System.Web.Hosting;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core
{
/// <summary>
/// A utility class to find all classes of a certain type by reflection in the current bin folder
/// of the web application.
/// </summary>
public static class TypeFinder
{
private static volatile HashSet<Assembly> _localFilteredAssemblyCache = null;
private static volatile HashSet<Assembly> _localFilteredAssemblyCache;
private static readonly object LocalFilteredAssemblyCacheLocker = new object();
/// <summary>
@@ -63,7 +55,7 @@ namespace Umbraco.Core
}
catch (InvalidOperationException e)
{
if (!(e.InnerException is SecurityException))
if ((e.InnerException is SecurityException) == false)
throw;
}
@@ -99,7 +91,7 @@ namespace Umbraco.Core
}
//if for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies.
if (!assemblies.Any())
if (assemblies.Any() == false)
{
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
@@ -111,12 +103,12 @@ namespace Umbraco.Core
var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported
var appCodeFolder = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code")));
//check if the folder exists and if there are any files in it with the supported file extensions
if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any())))
if (appCodeFolder.Exists && fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))
{
try
{
var appCodeAssembly = Assembly.Load("App_Code");
if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already
if (assemblies.Contains(appCodeAssembly) == false) // BuildManager will find App_Code already
assemblies.Add(appCodeAssembly);
}
catch (FileNotFoundException ex)
@@ -128,7 +120,7 @@ namespace Umbraco.Core
}
catch (InvalidOperationException e)
{
if (!(e.InnerException is SecurityException))
if (e.InnerException is SecurityException == false)
throw;
}
@@ -145,23 +137,15 @@ namespace Umbraco.Core
internal static HashSet<Assembly> GetAssembliesWithKnownExclusions(
IEnumerable<Assembly> excludeFromResults = null)
{
if (_localFilteredAssemblyCache == null)
lock (LocalFilteredAssemblyCacheLocker)
{
lock (LocalFilteredAssemblyCacheLocker)
{
//double check
if (_localFilteredAssemblyCache == null)
{
_localFilteredAssemblyCache = new HashSet<Assembly>();
var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
foreach (var a in assemblies)
{
_localFilteredAssemblyCache.Add(a);
}
}
}
if (_localFilteredAssemblyCache != null)
return _localFilteredAssemblyCache;
var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
_localFilteredAssemblyCache = new HashSet<Assembly>(assemblies);
return _localFilteredAssemblyCache;
}
return _localFilteredAssemblyCache;
}
/// <summary>
@@ -180,9 +164,9 @@ namespace Umbraco.Core
exclusionFilter = new string[] { };
return GetAllAssemblies()
.Where(x => !excludeFromResults.Contains(x)
&& !x.GlobalAssemblyCache
&& !exclusionFilter.Any(f => x.FullName.StartsWith(f)));
.Where(x => excludeFromResults.Contains(x) == false
&& x.GlobalAssemblyCache == false
&& exclusionFilter.Any(f => x.FullName.StartsWith(f)) == false);
}
/// <summary>
@@ -298,7 +282,7 @@ namespace Umbraco.Core
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
return GetClasses(assignTypeFrom, assemblies, onlyConcreteClasses,
return GetClassesWithBaseType(assignTypeFrom, assemblies, onlyConcreteClasses,
//the additional filter will ensure that any found types also have the attribute applied.
t => t.GetCustomAttributes<TAttribute>(false).Any());
}
@@ -324,7 +308,7 @@ namespace Umbraco.Core
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
return GetClasses(typeof(T), assemblies, onlyConcreteClasses);
return GetClassesWithBaseType(typeof(T), assemblies, onlyConcreteClasses);
}
/// <summary>
@@ -363,105 +347,9 @@ namespace Umbraco.Core
IEnumerable<Assembly> assemblies,
bool onlyConcreteClasses)
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
if (TypeHelper.IsTypeAssignableFrom<Attribute>(attributeType) == false)
throw new ArgumentException("The type specified: " + attributeType + " is not an Attribute type");
var foundAttributedTypes = new HashSet<Type>();
var assemblyList = assemblies.ToArray();
//find all assembly references that are referencing the attribute type's assembly since we
//should only be scanning those assemblies because any other assembly will definitely not
//contain a class that has this attribute.
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(attributeType, assemblyList);
//get a list of non-referenced assemblies (we'll use this when we recurse below)
var otherAssemblies = assemblyList.Where(x => referencedAssemblies.Contains(x) == false).ToArray();
//loop through the referenced assemblies
foreach (var a in referencedAssemblies)
{
//get all types in this assembly
var allTypes = GetTypesWithFormattedException(a)
.ToArray();
var attributedTypes = new Type[] { };
try
{
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes but have
//the specified attribute
attributedTypes = allTypes
.Where(t => (TypeHelper.IsNonStaticClass(t)
&& (onlyConcreteClasses == false || t.IsAbstract == false))
//the type must have this attribute
&& t.GetCustomAttributes(attributeType, false).Any())
.ToArray();
}
catch (TypeLoadException ex)
{
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", a), ex);
continue;
}
//add the types to our list to return
foreach (var t in attributedTypes)
{
foundAttributedTypes.Add(t);
}
//get all attributes of the type being searched for
var allAttributeTypes = allTypes.Where(attributeType.IsAssignableFrom);
//now we need to include types that may be inheriting from sub classes of the attribute type being searched for
//so we will search in assemblies that reference those types too.
foreach (var subTypesInAssembly in allAttributeTypes.GroupBy(x => x.Assembly))
{
//So that we are not scanning too much, we need to group the sub types:
// * if there is more than 1 sub type in the same assembly then we should only search on the 'lowest base' type.
// * We should also not search for sub types if the type is sealed since you cannot inherit from a sealed class
// * We should not search for sub types if the type is static since you cannot inherit from them.
var subTypeList = subTypesInAssembly
.Where(t => t.IsSealed == false && TypeHelper.IsStaticClass(t) == false)
.ToArray();
var baseClassAttempt = TypeHelper.GetLowestBaseType(subTypeList);
//if there's a base class amongst the types then we'll only search for that type.
//otherwise we'll have to search for all of them.
var subTypesToSearch = new HashSet<Type>();
if (baseClassAttempt.Success)
{
subTypesToSearch.Add(baseClassAttempt.Result);
}
else
{
foreach (var t in subTypeList)
{
subTypesToSearch.Add(t);
}
}
foreach (var typeToSearch in subTypesToSearch)
{
//recursively find the types inheriting from this sub type in the other non-scanned assemblies.
var foundTypes = FindClassesWithAttribute(typeToSearch, otherAssemblies, onlyConcreteClasses);
foreach (var f in foundTypes)
{
foundAttributedTypes.Add(f);
}
}
}
}
return foundAttributedTypes;
return GetClassesWithAttribute(attributeType, assemblies, onlyConcreteClasses);
}
/// <summary>
/// Finds the classes with attribute.
/// </summary>
@@ -485,122 +373,129 @@ namespace Umbraco.Core
return FindClassesWithAttribute<T>(GetAssembliesWithKnownExclusions());
}
#region Private methods
private static IEnumerable<Type> GetClassesWithAttribute(
Type attributeType,
IEnumerable<Assembly> assemblies,
bool onlyConcreteClasses)
{
if (typeof(Attribute).IsAssignableFrom(attributeType) == false)
throw new ArgumentException("Type " + attributeType + " is not an Attribute type.");
var candidateAssemblies = new HashSet<Assembly>(assemblies);
var attributeAssemblyIsCandidate = candidateAssemblies.Contains(attributeType.Assembly);
candidateAssemblies.Remove(attributeType.Assembly);
var types = new List<Type>();
var stack = new Stack<Assembly>();
stack.Push(attributeType.Assembly);
while (stack.Count > 0)
{
var assembly = stack.Pop();
Type[] assemblyTypes = null;
if (assembly != attributeType.Assembly || attributeAssemblyIsCandidate)
{
// get all assembly types that can be assigned to baseType
try
{
assemblyTypes = GetTypesWithFormattedException(assembly)
.ToArray(); // in try block
}
catch (TypeLoadException ex)
{
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", assembly), ex);
continue;
}
types.AddRange(assemblyTypes.Where(x =>
x.IsClass // only classes
&& (x.IsAbstract == false || x.IsSealed == false) // ie non-static, static is abstract and sealed
&& x.IsNestedPrivate == false // exclude nested private
&& (onlyConcreteClasses == false || x.IsAbstract == false) // exclude abstract
&& x.GetCustomAttribute<HideFromTypeFinderAttribute>() == null // exclude hidden
&& x.GetCustomAttributes(attributeType, false).Any())); // marked with the attribute
}
if (assembly != attributeType.Assembly && assemblyTypes.Where(attributeType.IsAssignableFrom).Any() == false)
continue;
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
{
candidateAssemblies.Remove(referencing);
stack.Push(referencing);
}
}
return types;
}
/// <summary>
/// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly
/// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
/// deriving from the base type.
/// </summary>
/// <param name="assignTypeFrom"></param>
/// <param name="baseType"></param>
/// <param name="assemblies"></param>
/// <param name="onlyConcreteClasses"></param>
/// <param name="additionalFilter">An additional filter to apply for what types will actually be included in the return value</param>
/// <returns></returns>
private static IEnumerable<Type> GetClasses(
Type assignTypeFrom,
private static IEnumerable<Type> GetClassesWithBaseType(
Type baseType,
IEnumerable<Assembly> assemblies,
bool onlyConcreteClasses,
Func<Type, bool> additionalFilter = null)
{
//the default filter will always return true.
if (additionalFilter == null)
var candidateAssemblies = new HashSet<Assembly>(assemblies);
var baseTypeAssemblyIsCandidate = candidateAssemblies.Contains(baseType.Assembly);
candidateAssemblies.Remove(baseType.Assembly);
var types = new List<Type>();
var stack = new Stack<Assembly>();
stack.Push(baseType.Assembly);
while (stack.Count > 0)
{
additionalFilter = type => true;
}
var assembly = stack.Pop();
var foundAssignableTypes = new HashSet<Type>();
var assemblyList = assemblies.ToArray();
//find all assembly references that are referencing the current type's assembly since we
//should only be scanning those assemblies because any other assembly will definitely not
//contain sub type's of the one we're currently looking for
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(assignTypeFrom, assemblyList);
//get a list of non-referenced assemblies (we'll use this when we recurse below)
var otherAssemblies = assemblyList.Where(x => referencedAssemblies.Contains(x) == false).ToArray();
//loop through the referenced assemblies
foreach (var a in referencedAssemblies)
{
//get all types in the assembly that are sub types of the current type
var allSubTypes = GetTypesWithFormattedException(a)
.Where(assignTypeFrom.IsAssignableFrom)
.ToArray();
var filteredTypes = new Type[] { };
try
// get all assembly types that can be assigned to baseType
Type[] assemblyTypes = null;
if (assembly != baseType.Assembly || baseTypeAssemblyIsCandidate)
{
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes
filteredTypes = allSubTypes
.Where(t => (TypeHelper.IsNonStaticClass(t)
//Do not include nested private classes - since we are in full trust now this will find those too!
&& t.IsNestedPrivate == false
&& (onlyConcreteClasses == false || t.IsAbstract == false)
//Do not include classes that are flagged to hide from the type finder
&& t.GetCustomAttribute<HideFromTypeFinderAttribute>() == null
&& additionalFilter(t)))
.ToArray();
try
{
assemblyTypes = GetTypesWithFormattedException(assembly)
.Where(baseType.IsAssignableFrom)
.ToArray(); // in try block
}
catch (TypeLoadException ex)
{
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", assembly), ex);
continue;
}
types.AddRange(assemblyTypes.Where(x =>
x.IsClass // only classes
&& (x.IsAbstract == false || x.IsSealed == false) // ie non-static, static is abstract and sealed
&& x.IsNestedPrivate == false // exclude nested private
&& (onlyConcreteClasses == false || x.IsAbstract == false) // exclude abstract
&& x.GetCustomAttribute<HideFromTypeFinderAttribute>() == null // exclude hidden
&& (additionalFilter == null || additionalFilter(x)))); // filter
}
catch (TypeLoadException ex)
{
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", a), ex);
if (assembly != baseType.Assembly && assemblyTypes.All(x => x.IsSealed))
continue;
}
//add the types to our list to return
foreach (var t in filteredTypes)
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
{
foundAssignableTypes.Add(t);
candidateAssemblies.Remove(referencing);
stack.Push(referencing);
}
//now we need to include types that may be inheriting from sub classes of the type being searched for
//so we will search in assemblies that reference those types too.
foreach (var subTypesInAssembly in allSubTypes.GroupBy(x => x.Assembly))
{
//So that we are not scanning too much, we need to group the sub types:
// * if there is more than 1 sub type in the same assembly then we should only search on the 'lowest base' type.
// * We should also not search for sub types if the type is sealed since you cannot inherit from a sealed class
// * We should not search for sub types if the type is static since you cannot inherit from them.
var subTypeList = subTypesInAssembly
.Where(t => t.IsSealed == false && TypeHelper.IsStaticClass(t) == false)
.ToArray();
var baseClassAttempt = TypeHelper.GetLowestBaseType(subTypeList);
//if there's a base class amongst the types then we'll only search for that type.
//otherwise we'll have to search for all of them.
var subTypesToSearch = new HashSet<Type>();
if (baseClassAttempt.Success)
{
subTypesToSearch.Add(baseClassAttempt.Result);
}
else
{
foreach (var t in subTypeList)
{
subTypesToSearch.Add(t);
}
}
foreach (var typeToSearch in subTypesToSearch)
{
//recursively find the types inheriting from this sub type in the other non-scanned assemblies.
var foundTypes = GetClasses(typeToSearch, otherAssemblies, onlyConcreteClasses, additionalFilter);
foreach (var f in foundTypes)
{
foundAssignableTypes.Add(f);
}
}
}
}
return foundAssignableTypes;
return types;
}
internal static IEnumerable<Type> GetTypesWithFormattedException(Assembly a)
@@ -666,7 +561,6 @@ namespace Umbraco.Core
#endregion
public static Type GetTypeByName(string typeName)
{
var type = BuildManager.GetType(typeName, false);
@@ -684,6 +578,5 @@ namespace Umbraco.Core
.Select(x => x.GetType(typeName))
.FirstOrDefault(x => x != null);
}
}
}
+40 -50
View File
@@ -13,9 +13,12 @@ namespace Umbraco.Core
/// </summary>
internal static class TypeHelper
{
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache = new ConcurrentDictionary<Type, FieldInfo[]>();
private static readonly ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]> GetPropertiesCache = new ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]>();
private static readonly ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]> GetPropertiesCache
= new ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]>();
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache
= new ConcurrentDictionary<Type, FieldInfo[]>();
private static readonly Assembly[] EmptyAssemblies = new Assembly[0];
/// <summary>
/// Checks if the method is actually overriding a base method
@@ -30,44 +33,40 @@ namespace Umbraco.Core
/// <summary>
/// Find all assembly references that are referencing the assignTypeFrom Type's assembly found in the assemblyList
/// </summary>
/// <param name="assignTypeFrom"></param>
/// <param name="assemblies"></param>
/// <param name="assembly">The referenced assembly.</param>
/// <param name="assemblies">A list of assemblies.</param>
/// <returns></returns>
/// <remarks>
/// If the assembly of the assignTypeFrom Type is in the App_Code assembly, then we return nothing since things cannot
/// reference that assembly, same with the global.asax assembly.
/// </remarks>
public static Assembly[] GetReferencedAssemblies(Type assignTypeFrom, IEnumerable<Assembly> assemblies)
public static Assembly[] GetReferencingAssemblies(Assembly assembly, IEnumerable<Assembly> assemblies)
{
//check if it is the app_code assembly.
//check if it is App_global.asax assembly
if (assignTypeFrom.Assembly.IsAppCodeAssembly() || assignTypeFrom.Assembly.IsGlobalAsaxAssembly())
{
return Enumerable.Empty<Assembly>().ToArray();
}
if (assembly.IsAppCodeAssembly() || assembly.IsGlobalAsaxAssembly())
return EmptyAssemblies;
//find all assembly references that are referencing the current type's assembly since we
//should only be scanning those assemblies because any other assembly will definitely not
//contain sub type's of the one we're currently looking for
return assemblies
.Where(assembly =>
assembly == assignTypeFrom.Assembly
|| HasReferenceToAssemblyWithName(assembly, assignTypeFrom.Assembly.GetName().Name))
.ToArray();
// find all assembly references that are referencing the current type's assembly since we
// should only be scanning those assemblies because any other assembly will definitely not
// contain sub type's of the one we're currently looking for
var name = assembly.GetName().Name;
return assemblies.Where(x => x == assembly || HasReference(x, name)).ToArray();
}
/// <summary>
/// checks if the assembly has a reference with the same name as the expected assembly name.
/// Determines if an assembly references another assembly.
/// </summary>
/// <param name="assembly"></param>
/// <param name="expectedAssemblyName"></param>
/// <param name="name"></param>
/// <returns></returns>
private static bool HasReferenceToAssemblyWithName(Assembly assembly, string expectedAssemblyName)
{
return assembly
.GetReferencedAssemblies()
.Select(a => a.Name)
.Contains(expectedAssemblyName, StringComparer.Ordinal);
public static bool HasReference(Assembly assembly, string name)
{
// ReSharper disable once LoopCanBeConvertedToQuery - no!
foreach (var a in assembly.GetReferencedAssemblies())
{
if (string.Equals(a.Name, name, StringComparison.Ordinal)) return true;
}
return false;
}
/// <summary>
@@ -106,13 +105,10 @@ namespace Umbraco.Core
public static Attempt<Type> GetLowestBaseType(params Type[] types)
{
if (types.Length == 0)
{
return Attempt<Type>.Fail();
}
if (types.Length == 1)
{
if (types.Length == 1)
return Attempt.Succeed(types[0]);
}
foreach (var curr in types)
{
@@ -196,20 +192,15 @@ namespace Umbraco.Core
/// <param name="includeIndexed"></param>
/// <param name="caseSensitive"> </param>
/// <returns></returns>
public static PropertyInfo GetProperty(Type type, string name,
bool mustRead = true,
bool mustWrite = true,
public static PropertyInfo GetProperty(Type type, string name,
bool mustRead = true,
bool mustWrite = true,
bool includeIndexed = false,
bool caseSensitive = true)
{
return CachedDiscoverableProperties(type, mustRead, mustWrite, includeIndexed)
.FirstOrDefault(x =>
{
if (caseSensitive)
return x.Name == name;
return x.Name.InvariantEquals(name);
});
}
return CachedDiscoverableProperties(type, mustRead, mustWrite, includeIndexed)
.FirstOrDefault(x => caseSensitive ? (x.Name == name) : x.Name.InvariantEquals(name));
}
/// <summary>
/// Gets (and caches) <see cref="FieldInfo"/> discoverable in the current <see cref="AppDomain"/> for a given <paramref name="type"/>.
@@ -222,7 +213,7 @@ namespace Umbraco.Core
type,
x => type
.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(y => !y.IsInitOnly)
.Where(y => y.IsInitOnly == false)
.ToArray());
}
@@ -240,13 +231,12 @@ namespace Umbraco.Core
new Tuple<Type, bool, bool, bool>(type, mustRead, mustWrite, includeIndexed),
x => type
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(y => (!mustRead || y.CanRead)
&& (!mustWrite || y.CanWrite)
&& (includeIndexed || !y.GetIndexParameters().Any()))
.Where(y => (mustRead == false || y.CanRead)
&& (mustWrite == false || y.CanWrite)
&& (includeIndexed || y.GetIndexParameters().Any() == false))
.ToArray());
}
#region Match Type
//TODO: Need to determine if these methods should replace/combine/merge etc with IsTypeAssignableFrom, IsAssignableFromGeneric
@@ -337,9 +327,9 @@ namespace Umbraco.Core
// not a generic type, not a generic parameter
// so normal class or interface
// fixme structs? enums? array types?
// about primitive types, value types, etc:
// http://stackoverflow.com/questions/1827425/how-to-check-programatically-if-a-type-is-a-struct-or-a-class
// if it's a primitive type... it needs to be ==
if (implementation == contract) return true;
if (contract.IsClass && implementation.IsClass && implementation.IsSubclassOf(contract)) return true;

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