Compare commits

..

409 Commits

Author SHA1 Message Date
Stephan 9a06c3a5ff Implement ILocalizationService.GetDictionaryItemKeyMap 2017-09-04 11:31:20 +02:00
Sebastiaan Janssen 44102df36f Merge pull request #2167 from umbraco/temp-U4-10370
U4-10370 Culture and hostnames with "æøå" after /
2017-09-04 11:25:55 +02:00
Sebastiaan Janssen 617a91c57e Merge pull request #2119 from umbraco/temp-U4-10274
U4-10274 Umbraco.MemberHasAccess isn't cached
2017-09-01 15:45:55 +02:00
Sebastiaan Janssen cb0e5414b9 Merge pull request #2155 from umbraco/temp-U4-10361
U4-10361 Creating new member when `AllowManuallyChangingPassword="fal…
2017-09-01 14:46:58 +02:00
Claus 22cef52261 removing using. 2017-09-01 13:50:51 +02:00
Claus 41e419a49e U4-10370 Culture and hostnames with "æøå" after / 2017-09-01 13:48:39 +02:00
Stephan efbe97a01d Merge pull request #2149 from umbraco/temp-deploy-358
Updates the underlying event args base class's AdditionalData diction…
2017-08-31 18:25:07 +02:00
Stephan 0babb7f28a deploy-358 - reduce allocations in CancellableEventArgs 2017-08-31 18:03:34 +02:00
Stephan 5ba801386c Merge branch 'dev-v7' into temp-deploy-358 2017-08-31 18:03:19 +02:00
Shannon 8c998fd4e6 Creates a virtual ConfigureUmbracoUserManager in UmbracoDefaultOwinStartup so inheritors can just override that if they want to simplify the startup owin code process 2017-08-30 11:02:58 +10:00
Shannon Deminick 88f332f5c7 Merge pull request #2157 from umbraco/temp-U4-10367
U4-10367 417 missing token error due to cookie being overwritten
2017-08-30 10:54:29 +10:00
Sebastiaan Janssen a1b9842215 Merge pull request #2131 from bjarnef/dev-v7-U4-10281
U4-10281 - Fix maxchars javascript errors on macro parameter editors
2017-08-29 11:23:16 +02:00
Sebastiaan Janssen d300bf8d6d U4-10367 417 missing token error due to cookie being overwritten
Changes the cookie and header names to be Umbraco specific
2017-08-29 11:17:52 +02:00
Shannon 78e66ce25f ok, hope this fixes tests 2017-08-29 16:34:30 +10:00
Shannon dcc0374464 trying to fix unit tests 2017-08-29 15:18:16 +10:00
Shannon a95afa610f updates unit test config to work with new unit tests 2017-08-29 12:01:32 +10:00
Shannon 13e2112c3c U4-10361 Creating new member when AllowManuallyChangingPassword="false" - can't set a password 2017-08-29 11:56:38 +10:00
Shannon Deminick cf10f5f0ee Merge pull request #2154 from umbraco/temp-U4-10363
U4-10363 417 missing token error due to invalid cookie name
2017-08-29 11:11:35 +10:00
Shannon ca00246236 another update to perform a little better again (cookies are read VERY often) 2017-08-29 11:10:28 +10:00
Shannon d71b8a139f Moves GetCookieValue to an extension method, cleans up code, adds unit tests 2017-08-29 10:50:20 +10:00
Sebastiaan Janssen 6bf0d6e175 U4-10363 417 missing token error due to invalid cookie name
Manually parse the cookie header instead of using the buggy extension method
2017-08-28 20:36:56 +02:00
Sebastiaan Janssen 7a0c6ab975 Merge pull request #2135 from umbraco/temp-U4-10301
U4-10301 Change the PluginManager hash to use more reliable and consi…
2017-08-28 11:44:40 +02:00
Stephan 49d5005453 Merge pull request #2151 from umbraco/temp-U4-10358
U4-10358 Upgrade error from 7.1.8 to 7.6.5: The index 'IX_umbracoNode…
2017-08-26 15:26:41 +02:00
Sebastiaan Janssen f2db0fe80e U4-10358 Upgrade error from 7.1.8 to 7.6.5: The index 'IX_umbracoNodeUniqueID' is dependent on column 'uniqueID'
Removes migration that would add wrongly named index to a table, only to immediately be removed again in 7.3.0
2017-08-25 22:00:41 +02:00
Sebastiaan Janssen 9917fb20ca U4-10356 Update default Config/Lang after each update
Also makes sure UserExtensions returns the correct language
2017-08-25 16:13:04 +02:00
Shannon e71e9d7efb U4-10249 FolderAndFilePermissions HealthCheck causes the application to restart
(cherry picked from commit bdb991f6dc)
2017-08-24 18:51:53 +02:00
Shannon 93cd03da28 minor code cleanup 2017-08-24 18:38:40 +10:00
Shannon 1dade7bfd2 fixes tests 2017-08-24 17:22:33 +10:00
Shannon c3b1aa36b8 Updates remaining services with one event arg instance for both event pairs to flow the EventState 2017-08-24 17:19:57 +10:00
Shannon 9cc466775d Updates more services to only have one event arg instance per event pair to flow through EventState 2017-08-24 16:50:12 +10:00
Shannon d0a91bf98b Updates ContentTypeService to ensure a single event args instance is created per event pair so that EventState flows. 2017-08-24 16:35:09 +10:00
Shannon 085c06e043 Adds EventState to the event args instead of trying to change the AdditionalData which is a breaking change. Updates FileService and ContentService to use one event arg insteance for both before/after events so that the EventState flows and so we are allocating less objects. 2017-08-24 16:22:50 +10:00
Shannon 1e45f85f7c Updates the underlying event args base class's AdditionalData dictionary to be IDictionary instead of ReadOnlyDictionary. Ensures the same args are used for both events when Deleting Templates. 2017-08-24 15:21:54 +10:00
Shannon a0785f2e0d backports U4-10349 Optimize EnsureUniqueNodeName 2017-08-23 16:22:01 +10:00
Mads Rasmussen 583302faa2 Merge pull request #2077 from abryukhov/temp-U4-10200
U4-10200 Listview layouts - empty state not localized
2017-08-21 21:37:01 +02:00
Sebastiaan Janssen 4404ce94c5 Merge pull request #2142 from abjerner/patch-17
Typo
2017-08-21 14:24:52 +02:00
Anders Bjerner 86bc701511 Typo
Very minor typo, but still ;)
2017-08-21 14:16:01 +02:00
Stephan a86902bd91 Merge pull request #2128 from umbraco/temp-U4-10289
U4-10289 IdkMap cache can cause the entity service to return invalid …
2017-08-18 21:45:35 +02:00
Mads Rasmussen 7bdf76ffa7 Merge pull request #2098 from bjarnef/dev-v7-U4-10242
U4-10242 - Remove bottom margin of subtitle paragraph
2017-08-18 14:21:08 +02:00
Claus 528656a337 using val.value directly. 2017-08-18 11:44:44 +02:00
Mads Rasmussen 5ef46ad8df Merge pull request #2048 from umbraco/temp-U4-7497
Pressing Enter/Backspace in repeatable text strings now adds/removes text boxes
2017-08-18 11:34:52 +02:00
Mads Rasmussen 168dc0e5da small UX refinements 2017-08-18 11:24:51 +02:00
Claus 5a1fc91f3e simplified it a bit. 2017-08-17 12:50:15 +02:00
Robert 5e6b5a5cc1 Added a check so it's not possibile to delete the texboxes that are set as minimum 2017-08-17 12:09:20 +02:00
Robert 7213e3a6a0 Adding and removing text boxes should work properly now
Thanks Mads :)
2017-08-17 12:06:32 +02:00
Mads Rasmussen 217ca62ea0 Merge pull request #2099 from bjarnef/dev-v7-U4-10152
U4-10152 - Fix typo in localization of placeholder text
2017-08-17 11:09:40 +02:00
Mads Rasmussen d216d5755c Merge pull request #2094 from skttl/patch-6
U4-10225: Notification banner floats above context menu
2017-08-17 10:55:37 +02:00
Claus 8db748b738 Merge pull request #2123 from umbraco/temp-U4-7382-2
U4-7382 Text Properties Containing JSON Are Corrupted on Publish
2017-08-17 10:43:51 +02:00
Shannon 300c9aa258 fix test 2017-08-17 12:10:34 +10:00
Shannon f7097d571c U4-10301 Change the PluginManager hash to use more reliable and consistent hashes 2017-08-17 11:38:57 +10:00
Mads Rasmussen b151c39c3b Merge pull request #2097 from skttl/patch-9
U4-10232 Unsaved changes alert overlaps borders
2017-08-16 16:15:49 +02:00
Claus 542406c402 Merge pull request #2130 from umbraco/temp-U4-10136
U4-10136 Broken link to package action documentation
2017-08-15 11:02:52 +02:00
Claus c44b903261 changed to private structs and made immutable. 2017-08-15 10:10:40 +02:00
Bjarne Fyrstenborg c68d7a33ca Fix maxchars javascript errors on macro parameter editors 2017-08-14 19:57:28 +02:00
Robert 2773102441 Fixed tag 2017-08-14 14:58:48 +02:00
Claus ef0d6eff2c Merge pull request #2124 from umbraco/mikecp-U4-8967
U4-8967 Linkpicker localization issue
2017-08-14 14:58:31 +02:00
Robert 1efad78214 Package-actions link updated 2017-08-14 14:58:05 +02:00
Claus 46b2d8a4aa implement equality comparison to prevent duplicates in when used in dictionaries. 2017-08-14 13:34:47 +02:00
Claus 7a5cb7058b U4-10289 IdkMap cache can cause the entity service to return invalid results 2017-08-14 11:38:13 +02:00
Robert c1c2339827 U4-8967 Linkpicker localization issue
Did a few modifications to the PR - reverted back the default translations for "content_nodeName" and "content_urls" as they are being used in other places.
To fix this, I have created two new keys that are used only in the linkpicker :)
2017-08-11 10:31:04 +02:00
Shannon 0e273d1a08 U4-7382 Text Properties Containing JSON Are Corrupted on Publish 2017-08-11 15:11:53 +10:00
Mads Rasmussen 125c378274 fixes: U4-4848 If "Save and Publish" is clicked before page finishes loading, data is lost from MNTP 2017-08-10 14:11:48 +02:00
mikkelhm ca80a0cddc Bump version to 7.6.6 2017-08-10 08:41:06 +02:00
Shannon 21707f9e08 Updates the GetMemberGroupsForMember with a username to be a single query 2017-08-10 14:22:30 +10:00
Shannon d8cfd8f12e U4-10274 Umbraco.MemberHasAccess isn't cached 2017-08-10 13:46:18 +10:00
Mads Rasmussen 08150c05e9 Merge pull request #1971 from Bitmapped/U4-9977
Fix U4-9977
2017-08-09 13:28:04 +02:00
Mads Rasmussen 688f8c4170 Merge pull request #2053 from bjarnef/dev-v7-U4-10161
U4-10161 - Update localization of email
2017-08-09 11:51:05 +02:00
Mads Rasmussen 31cbb79ede Translate zip-code 2017-08-09 11:48:15 +02:00
Shannon Deminick 305ce84ef5 Merge pull request #2111 from umbraco/temp-U4-10266
U4-10266 Package installer need to handle files before handling entities
2017-08-09 19:47:45 +10:00
Shannon c6d7056a64 Updated to return nulls as opposed to the ex being caught with a meaningful message 2017-08-09 19:44:37 +10:00
Bitmapped 7db1055a0d Remove JSON files, which appear to be unnecessary. 2017-08-08 13:54:36 -04:00
Claus d625388786 U4-10266 Package installer need to handle files before handling entities 2017-08-08 13:10:33 +02:00
Claus fa1663ed51 Fixes build script to work with VS 2017 (only) and fixes BuildBelle since it didn't work and is missing tools 2017-08-08 13:08:29 +02:00
mikkelhm ca0de5acd3 Fix more xml format issues in pl.xml 2017-08-07 21:58:45 +02:00
mikkelhm 27168722ab fix xml in pl.xml 2017-08-07 20:33:49 +02:00
Sebastiaan Janssen 6dbeba0763 Merge pull request #2103 from ronaldbarendse/U4-10252
U4-10252: Slider property editor initial values not used when equal (range enabled)
2017-08-07 08:10:49 +02:00
Ronald Barendse 00e0f83c8e Fixed U4-10252
Umbraco.Slider property editor did not use the correct initial values
when range was enabled and both values were equal.
2017-08-06 22:41:20 +02:00
Bjarne Fyrstenborg 68ba0ca1e2 Fix typo in localization of placeholder text 2017-08-03 21:45:01 +02:00
Bjarne Fyrstenborg b22e9d0911 Remove bottom margin of subtitle paragraph 2017-08-03 21:35:03 +02:00
Søren Kottal 6a59a90964 Moves .alert-form.-no-border slightly
Moves .alert-form.-no-border slightly, so borders beneath are visible
2017-08-02 20:49:20 +02:00
Søren Kottal 26a042f291 U4-10225: Bumps z-index of #leftcolumn
http://issues.umbraco.org/issue/U4-10225

This bumps the z-index of #leftcolumn, so the notifications don't get in the way.
2017-08-02 19:41:55 +02:00
Sebastiaan Janssen 136b3db098 Merge pull request #2071 from umbraco/temp-U4-10123
U4-10123 Make sure the backoffice login is not susceptible to DOS att…
2017-08-01 17:16:31 +02:00
Sebastiaan Janssen 21f46d0a3c Adds debug level logging for failed attempts to get filestream 2017-08-01 09:16:39 +02:00
Sebastiaan Janssen 7fafea2370 Merge pull request #2087 from umbraco/temp-u4-10213
PluginManager - implement retries on list file
2017-07-31 17:03:55 +02:00
Stephan 86c37c7f6d PluginManager - fix 2017-07-31 16:38:39 +02:00
Stephan 7dd9f3e766 PluginManager - implement retries on list file 2017-07-31 16:24:22 +02:00
Alexander Bryukhov 6c91d54372 U4-10200 Listview layouts - empty state not localized 2017-07-26 10:24:03 +07:00
Shannon 1ccc8cc161 U4-10123 Make sure the backoffice login is not susceptible to DOS attacks 2017-07-25 19:40:30 +10:00
Stephan c5e7e1e39e U4-10144 - dont break again 2017-07-24 14:05:04 +02:00
Shannon db2a35dbce fixes a localized key that doesn't exist 2017-07-24 20:23:54 +10:00
Sebastiaan Janssen 3d006f1e08 Merge pull request #2065 from akierczynska/patch-2
Update pl.xml to match en.xml
2017-07-24 09:30:33 +02:00
akierczynska e0c891719f Update pl.xml to match en.xml
Updating pl.xml with new keys to match en.xml
2017-07-24 00:04:11 +01:00
Sebastiaan Janssen 89a14c13e5 Merge pull request #2060 from soreng/patch-4
Changed name of argument in validation
2017-07-21 15:14:33 +02:00
Sebastiaan Janssen ca9aa21c7b Merge pull request #2064 from pijemcolu/temp-U4-10187
U4-10187 - Fix link to training in Backoffice -> Settings->Dashboard
2017-07-21 14:42:49 +02:00
Stephan c0eaeb3168 Fix tests with issues 2017-07-21 13:06:23 +02:00
pijemcolu 74e16c0f8d fix link to training in Settings->Dashboard 2017-07-21 10:14:07 +02:00
Stephan f8fac9f84e U4-9430 - fix 2017-07-20 10:21:21 +02:00
Stephan 83ce359234 Merge pull request #1992 from Bitmapped/U4-9430
U4-9430 Fix
2017-07-20 10:20:06 +02:00
Søren Gregersen 2c64f91b25 Changed name of argument in validation
Minor change... :)
2017-07-19 22:23:22 +02:00
Sebastiaan Janssen e702fe2877 Merge pull request #2055 from dawoe/patch-2
Fix value converter work for legacy media picker
2017-07-19 12:31:46 +02:00
Sebastiaan Janssen 9d55656ae9 Merge pull request #2058 from umbraco/temp-u4-10128
U4-10128 - GetKey unwraps
2017-07-19 12:26:12 +02:00
Stephan d57de05453 U4-10128 - super improve 2017-07-19 12:24:00 +02:00
Stephan 11e4bf5de8 U4-10128 - improve 2017-07-19 12:08:31 +02:00
Stephan 82661d9af4 U4-10128 - GetKey unwraps 2017-07-19 11:51:46 +02:00
Dave Woestenborghs 56cff6bba8 implemented suggestions from @jeavon 2017-07-18 17:11:49 +02:00
Dave Woestenborghs 6b289e1a7d Fix value converter work for legacy media picker
Fix for issue http://issues.umbraco.org/issue/U4-10178
2017-07-18 14:44:57 +02:00
Bjarne Fyrstenborg 50d7114209 Update localization of email 2017-07-18 00:07:22 +02:00
Sebastiaan Janssen 91fa583f62 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-07-17 22:15:24 +02:00
Sebastiaan Janssen 23d91fd350 Adds removed method back in case someone is using it (would be breaking otherwise) 2017-07-17 22:14:59 +02:00
Sebastiaan Janssen d4714e1580 Merge pull request #2052 from umbraco/dev-v7.6
Oops was targeting old branch :)
2017-07-17 22:12:47 +02:00
Sebastiaan Janssen 2b22e6a784 Merge pull request #1940 from AndyButland/u4-9892
U4-9892 - ordered media types when returned for create dialog
2017-07-17 22:09:00 +02:00
Sebastiaan Janssen 59840926c8 Merge pull request #1952 from callumbwhyte/U4-9934
U4 9934: Fixes deleting members in list view using custom membership provider
2017-07-17 22:01:33 +02:00
Sebastiaan Janssen 338c7cc5a6 Merge branch 'callumbwhyte-U4-9934' into dev-v7 2017-07-17 21:31:43 +02:00
Sebastiaan Janssen 77850aea18 Merge branch 'U4-9934' of https://github.com/callumbwhyte/Umbraco-CMS into callumbwhyte-U4-9934 2017-07-17 21:31:25 +02:00
Sebastiaan Janssen 895f0a9dfe Merge pull request #1982 from AndyButland/u4-9987
Extended HttpsCheck healthcheck to check for expiring SSL certificate
2017-07-17 21:26:03 +02:00
Sebastiaan Janssen ec03a3dc42 Merge pull request #1989 from HarveyWilliams/patch-2
Fix for `IsDocumentTypeRecursive` - U4-9997
2017-07-17 21:23:18 +02:00
Sebastiaan Janssen 5a4dbba21b Merge pull request #1998 from Jeavon/temp-U4-10013
U4-10013 Umbraco.MediaPicker value converter does not understand ints
2017-07-17 20:40:24 +02:00
Sebastiaan Janssen 04546dd827 Merge pull request #2035 from bjarnef/dev-v7-U4-9945
U4-9945 - Fix vertical separator color and height of icon in custom section
2017-07-17 20:22:43 +02:00
Sebastiaan Janssen 4ecf1f919e Merge pull request #2038 from bjarnef/dev-v7-U4-4079
U4-4079 - Open context menu in member section, when clicking "do something else" button
2017-07-17 20:18:37 +02:00
Sebastiaan Janssen bdc4e1ae6a Merge pull request #2041 from blueboxes/dev-v7
U4-10143 - Improved error messages when we retrieve current xml node
2017-07-17 19:51:49 +02:00
Sebastiaan Janssen 3cb05870af Merge pull request #2051 from mistyn8/U4-10171
Update treepicker.html [U4-10171] add ability to remove picker item
2017-07-17 18:15:23 +02:00
Sebastiaan Janssen 95b0c342bb Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-07-17 17:51:39 +02:00
Sebastiaan Janssen 3a5584a1c1 Some updates to description and code style 2017-07-17 17:50:38 +02:00
Sebastiaan Janssen b425edbb45 Merge branch 'srmooney-U4-10088' into dev-v7 2017-07-17 17:30:56 +02:00
Sebastiaan Janssen b403283368 Merge branch 'U4-10088' of https://github.com/srmooney/Umbraco-CMS into srmooney-U4-10088 2017-07-17 17:30:32 +02:00
Mike Chambers cb1d347769 Update treepicker.html
resolves U4-10171 can't click remove icon, to remove picker item.
2017-07-17 15:54:11 +01:00
Warren Buckley 4d0a2c85b7 Merge pull request #2049 from umbraco/temp-U4-5672
U4-5672 Properties and Tabs moving/incorrect when Enable list view se…
2017-07-17 09:41:37 +01:00
Sebastiaan Janssen e1957b895f U4-5672 Properties and Tabs moving/incorrect when Enable list view selected 2017-07-17 09:46:30 +02:00
Robert 84de083d52 Merge remote-tracking branch 'origin/temp-U4-7497' into temp-U4-7497 2017-07-14 13:57:36 +02:00
Robert 6ccb822cb5 On textbox delete the next in line gets focused
umbfocusbackwards.directive.js file added
2017-07-14 13:56:11 +02:00
Robert c94338d2b6 Newly added text box now get's focused. 2017-07-14 13:56:11 +02:00
Robert 3ba001164f Changed to keyup 2017-07-14 13:56:11 +02:00
Robert a8c0367492 Add/Remove functionality on key press added 2017-07-14 13:56:11 +02:00
Robert 91646212fd add/remove functionality on keyDown added 2017-07-14 13:56:11 +02:00
Robert 4c9b2f552a On textbox delete the next in line gets focused
umbfocusbackwards.directive.js file added
2017-07-14 13:30:28 +02:00
Stephan c696c62185 More fsTreeController cleanup 2017-07-13 15:12:14 +02:00
Warren Buckley 0dfbb95033 Merge branch 'madjor5-U4-4413_-_maxlength' into dev-v7 2017-07-13 13:39:20 +01:00
Warren Buckley 17969e4537 Merge branch 'U4-4413_-_maxlength' of https://github.com/madjor5/Umbraco-CMS into madjor5-U4-4413_-_maxlength
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html
#	src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html
#	src/Umbraco.Web.UI/umbraco/config/lang/da.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
2017-07-13 13:09:06 +01:00
Robert 3395445d7c Newly added text box now get's focused. 2017-07-13 14:05:50 +02:00
mikkelhm 374fdcf29e Bumps version to 7.6.5 2017-07-13 12:14:32 +02:00
Claus bcb19eea35 Merge pull request #1678 from PeteDuncanson/patch-2
Fixed error label showing when you do a retry
2017-07-12 15:47:32 +02:00
Claus da00ad1444 Merge branch 'abryukhov-temp-U4-10139' into dev-v7 2017-07-12 15:10:51 +02:00
Claus 7bc52b3948 localization fixes. 2017-07-12 15:06:29 +02:00
Claus a77aec4156 Merge branch 'temp-U4-10139' of git://github.com/abryukhov/Umbraco-CMS into abryukhov-temp-U4-10139 2017-07-12 14:36:47 +02:00
Claus f7f3dccfc8 Merge pull request #2042 from umbraco/temp-fsTreeController
filesystem controller compatibility
2017-07-12 14:27:00 +02:00
Claus ab3469d703 cleanup. 2017-07-12 14:26:44 +02:00
Claus c78ea90cf5 cleaning up a bit. 2017-07-12 14:24:09 +02:00
Sebastiaan Janssen 3de0b85ae3 Merge pull request #2001 from umbraco/temp-u4-9993
U4-9993 - fix upgrade issues
2017-07-12 12:59:19 +02:00
Stephan 87b51d1418 Merge branch dev-v7 into temp-fsTreeController 2017-07-11 19:06:01 +02:00
John Kilmister 8ea1af56ab U4-10143 - Improved error messages when we retrieve current xml node 2017-07-11 16:22:21 +01:00
Stephan 219eb61194 Merge branch 'dev-v7' into temp-u4-9993 2017-07-11 14:47:54 +02:00
Robert 1d3279fe07 Merge pull request #2036 from bjarnef/dev-v7-U4-10130
U4-10130 - Equal height of input and button
2017-07-11 10:48:23 +02:00
Robert 88bb796f4d Merge branch 'dev-v7' into dev-v7-U4-10130 2017-07-11 10:41:58 +02:00
Robert 97878ac25a Merge pull request #2037 from bjarnef/dev-v7-U4-9933
U4-9933 - Update datepicker styles
2017-07-11 09:56:48 +02:00
Alexander Bryukhov c87e880b64 Minor localization issues U4-10139 2017-07-11 14:15:07 +07:00
Bjarne Fyrstenborg e28ba446a0 Open context menu when clicking "Do something else" 2017-07-08 01:20:26 +02:00
Bjarne Fyrstenborg c645a2cf15 Update styles of datepicker 2017-07-08 00:45:18 +02:00
Bjarne Fyrstenborg 5fb8d990f8 Include original missing changes 2017-07-07 23:52:20 +02:00
Bjarne Fyrstenborg 8626e4337f Adjust search icon position 2017-07-07 23:40:02 +02:00
Bjarne Fyrstenborg 0f22c41eee Update height of input in header 2017-07-07 23:21:19 +02:00
Bjarne Fyrstenborg e73fda14b5 Adjust height of input fields 2017-07-07 23:16:11 +02:00
Bjarne Fyrstenborg a04df8070a Revert "Make examine search input and button more consistent with UI"
This reverts commit 60c1052db1.
2017-07-07 22:51:32 +02:00
Bjarne Fyrstenborg 60c1052db1 Make examine search input and button more consistent with UI 2017-07-07 22:12:27 +02:00
Bjarne Fyrstenborg dd041a6f09 Ensure it override injected styles from custom font icon 2017-07-07 19:16:42 +02:00
Bjarne Fyrstenborg 733aab6eb5 Fix vertical separator color and height of icon in custom section 2017-07-07 18:57:57 +02:00
srmooney 1e6d50a86b Add option for Listview to change the tab name 2017-07-06 10:50:19 -04:00
Sebastiaan Janssen 0445588c6b Merge pull request #2033 from umbraco/temp-revert-newstarterkitdefault
Reverts the change for the installer screen which needs to be ready f…
2017-07-06 15:31:45 +02:00
mikkelhm 4d316cf0ce Reverts the change for the installer screen which needs to be ready for the new starterkit and Lessons 2017-07-06 15:06:55 +02:00
Mikkel Holck Madsen 864650193a Merge pull request #2032 from umbraco/temp-U4-10124
U4-10124 Update IFileService to handle MacroScripts and UserControls
2017-07-06 12:58:17 +02:00
Claus cfa7b0a092 U4-10124 Update IFileService to handle MacroScripts and UserControls 2017-07-06 10:44:51 +02:00
Mikkel Holck Madsen 5726420848 Merge pull request #2030 from umbraco/temp-U4-10098
U4-10098 Update FileService to support legacy MacroScript and UserCon…
2017-07-06 09:15:18 +02:00
Robert cc57cd6eb7 Changed to keyup 2017-07-05 12:57:29 +02:00
Robert 193eb259a6 Add/Remove functionality on key press added 2017-07-05 12:54:59 +02:00
Robert 6db18d83be add/remove functionality on keyDown added 2017-07-05 10:15:23 +02:00
Claus ca752f74bc updating array length. 2017-07-04 17:29:32 +02:00
Claus b840a0992c adding shadow filesystems. 2017-07-04 14:47:29 +02:00
Claus 51997d0651 U4-10098 Update FileService to support legacy MacroScript and UserControl folders 2017-07-04 14:28:15 +02:00
Shannon Deminick 9482104ec5 Merge pull request #2028 from umbraco/temp-U4-4905
Removed "remove paragraph tags" field
2017-07-04 12:33:25 +10:00
Robert 7053c175f8 Removed "remove paragraph tags" field 2017-07-03 13:44:37 +02:00
Claus b2116480fc fix formatting. 2017-07-03 11:17:05 +02:00
Claus caef6cc623 Merge pull request #2026 from wanddy/dev-v7
Improve Chinese translation
2017-07-03 08:32:47 +02:00
wanddy 280ad246ab Merge remote-tracking branch 'remotes/origin/dev-v7' into dev-v7 2017-06-30 19:46:09 +08:00
Stephan 43e0ef2472 Merge branch 'dev-v7' into temp-u4-9993 2017-06-30 11:02:43 +02:00
Claus 44cfe5da84 missing nullcheck. 2017-06-30 10:46:44 +02:00
Claus d5fd266b19 missing semicolon. 2017-06-30 10:34:58 +02:00
wanddy 5768992ccc Improve Chinese translation to match the newest version based on en.xml file.
Signed-off-by: wanddy <wanddy@163.com>
2017-06-30 12:10:59 +08:00
Mads Rasmussen 81aae79b42 Merge pull request #2015 from umbraco/temp-U4-9839
U4-9839 Media Picker: If I only upload one photo then select it as a …
2017-06-29 14:54:49 +02:00
Claus 9edbb3fc26 Merge pull request #1634 from soreng/patch-2
use already defined variable, instead of mapping the path twice
2017-06-29 14:47:21 +02:00
Claus 7fdd2bcdfc Merge pull request #2018 from AndyButland/u4-4090
Fixes U4-4090 - by preserved line breaks in property descriptions...
2017-06-29 14:43:13 +02:00
Claus ba90fdeb56 Merge pull request #1778 from bjarnef/dev-v7-U4-9585
Allow leading whitespace in textstring prevalue editor
2017-06-29 14:40:10 +02:00
Claus d6bae1b58f Merge pull request #1958 from poornimanayar/U4-9661
U4-9661 Remove "move" button in member section
2017-06-29 14:37:00 +02:00
Claus ef53db52f7 Merge pull request #1850 from pijemcolu/temp-U4-9710
U4-9710 ImageCropDataSet.HasImage returns wrong value
2017-06-29 14:07:59 +02:00
Claus 863b97039c Merge pull request #1632 from bjarnef/dev-v7-U4-9181
U4-9181 - Fix sorting of grid editor config
2017-06-29 13:55:12 +02:00
Claus 1a1adbf647 Merge pull request #2024 from greystate/drobar-partialviews
Updates to partialviews
2017-06-29 13:47:54 +02:00
Claus 5c745565da Merge pull request #2025 from umbraco/temp-U4-8970
U4-8988 Adding translations for Chinese (Taiwan)
2017-06-29 13:28:06 +02:00
Claus 5dec54badb U4-8988 Adding translations for Chinese (Taiwan) 2017-06-29 13:27:31 +02:00
Claus e5e725b376 Merge pull request #2022 from umbraco/temp-U4-5454
Temp u4 5454
2017-06-29 12:32:57 +02:00
Claus f0f25c67c6 refactoring method signatures to prevent breaking changes. 2017-06-29 10:00:16 +02:00
Claus da8c0726b1 Merge branch 'U4-5454' of git://github.com/trt/Umbraco-CMS into temp-U4-5454 2017-06-29 08:59:45 +02:00
Claus 2fbb9721fa updating language files. 2017-06-29 08:53:22 +02:00
Claus de6ffd456c Merge pull request #1972 from wanddy/dev-v7-chnfixnew
Fix translation didn't work in some tree node
2017-06-29 08:47:37 +02:00
Claus 5b3ff58ad8 Merge pull request #1964 from esn303/patch-2
Update "Element hinzufügen" (Add grid element)
2017-06-29 08:14:08 +02:00
Claus 9a4c1972b2 Merge pull request #2020 from umbraco/revert-2008-temp-old-client-files-clean-up
Revert "Removing unused v6 images"
2017-06-28 14:49:05 +02:00
Claus b993ce953b Revert "Removing unused v6 images" 2017-06-28 14:48:41 +02:00
Claus dde0f1aa36 Merge pull request #2008 from umbraco/temp-old-client-files-clean-up
Removing unused v6 images
2017-06-28 13:07:19 +02:00
Stephan 3fd6754057 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-06-28 12:46:46 +02:00
Stephan 8fbb459233 fix and annotate some tests 2017-06-28 12:46:40 +02:00
Shannon cb6f934792 fixes cache bust value 2017-06-27 19:40:24 +10:00
Shannon Deminick 7adbecf9a1 Merge pull request #2019 from lars-erik/U4-6695-internalsvisibleto-unittesting-adapter
U4-6695 Adds InternalsVisibleTo("Umbraco.UnitTesting.Adapter")
2017-06-27 10:06:36 +10:00
Claus 2fdf148610 localizing text https://github.com/umbraco/Umbraco-CMS/pull/1250 2017-06-26 15:41:17 +02:00
Claus 9d9e5e8274 Merge branch 'rodyvansambeek-patch-1' into dev-v7 2017-06-26 15:33:27 +02:00
Claus 89895dd592 Merge branch 'patch-1' of git://github.com/rodyvansambeek/Umbraco-CMS into rodyvansambeek-patch-1
# Conflicts:
#	src/Umbraco.Web.UI/umbraco/config/lang/nl.xml
2017-06-26 15:32:47 +02:00
Lars-Erik Aabech f9252372ea Adds InternalsVisibleTo("Umbraco.UnitTesting.Adapter") for more imperative exposure to custom unit test adapters. 2017-06-26 12:39:57 +02:00
Claus 02a2178029 Merge branch 'benjaminketron-temp-U4-9464' into dev-v7 2017-06-26 11:33:27 +02:00
Claus ee775a2fde adding a few more tests. 2017-06-26 11:31:46 +02:00
Claus 22af206626 Merge branch 'temp-U4-9464' of git://github.com/benjaminketron/Umbraco-CMS into benjaminketron-temp-U4-9464 2017-06-26 11:23:24 +02:00
AndyButland 67e109c0e6 Preserved line breaks in property descriptions when rendering in content area 2017-06-23 11:40:43 +02:00
Sebastiaan Janssen 8a4d85771b Merge pull request #2016 from mikecp/U4-10047
U4 10047
2017-06-23 11:14:49 +02:00
Sebastiaan Janssen 4688ac104e Merge pull request #1494 from AndyButland/u4-8999
U4-8999 - health check, debug compilation mode is being reported in error when config missing
2017-06-23 08:31:29 +02:00
Michael Latouche 032dbe5bf5 Update fr.xml 2017-06-23 00:52:10 +02:00
Michael Latouche a7695163b9 Update fr.xml 2017-06-23 00:21:33 +02:00
Michael Latouche cb4569677e Update fr.xml 2017-06-23 00:10:22 +02:00
Michael Latouche 4be704b968 Update fr.xml 2017-06-23 00:09:52 +02:00
Michael Latouche b7a5cb046a Update fr.xml 2017-06-22 23:56:33 +02:00
Claus eb52dafb33 U4-9839 Media Picker: If I only upload one photo then select it as a part of the upload process 2017-06-22 13:01:29 +02:00
Sebastiaan Janssen af382c171b Merge pull request #2009 from umbraco/temp-U4-10034
U4-10034 Package install may not wait for app domain restart in all cases
2017-06-22 11:22:18 +02:00
Claus 54fdfdd639 adding grunt watch interval to prevent insane cpu load. 2017-06-22 11:05:42 +02:00
Claus c4c99ef0b8 Merge pull request #2014 from umbraco/temp-deploy-348
deploy-348 - add support for languages
2017-06-22 10:53:31 +02:00
Stephan 0bd233815e deploy-348 - add support for languages 2017-06-22 10:04:48 +02:00
Michael Latouche 4c9fd4029f Merge pull request #3 from umbraco/dev-v7
Resync
2017-06-22 00:32:36 +02:00
Claus 3d65afabbf Merge branch 'temp-U4-10043' into dev-v7 2017-06-21 14:27:34 +02:00
Claus ef9bf155ef typo. 2017-06-21 14:21:39 +02:00
Sebastiaan Janssen e947f661a9 Merge pull request #2011 from akierczynska/patch-1
Updating pl.xml language version to cover en.xml
2017-06-21 14:20:19 +02:00
Claus 0eb8ebd82e fixing up translations. 2017-06-21 14:04:15 +02:00
Claus bc76fa8687 Merge branch 'localization-v764' of git://github.com/abryukhov/Umbraco-CMS into temp-U4-10043 2017-06-21 12:03:25 +02:00
Sebastiaan Janssen 8681d535f2 Merge pull request #2010 from umbraco/temp-U4-10035
Turns out when we empty the recycle bin we weren't removing associate…
2017-06-21 11:51:47 +02:00
Shannon 6d81705ece fixes the restart check 2017-06-21 18:34:22 +10:00
Sebastiaan Janssen b433af8611 Merge pull request #2013 from umbraco/temp-U4-10046
U4-10046 Stop resolving TreeController from the PluginManager for eve…
2017-06-21 10:15:07 +02:00
Shannon b0f4d0e16b U4-10046 Stop resolving TreeController from the PluginManager for every back office request 2017-06-21 18:11:03 +10:00
Shannon 2f24dfb8f0 changes name from versionHash to cacheBuster
(cherry picked from commit 439c30e2fd)
2017-06-21 08:26:44 +02:00
Shannon ad63050078 Fixes issue of rendering the umb version in the html markup
(cherry picked from commit c13b2fae4b)
2017-06-21 08:26:20 +02:00
Alexander Bryukhov 552c2ed4dc Localizing hardcoded strings 2017-06-21 02:45:18 +07:00
Alexander Bryukhov d7e522132e Localizing hardcoded strings 2017-06-21 02:45:12 +07:00
Alexander Bryukhov ca7c43d944 Localizing hardcoded strings 2017-06-21 02:45:05 +07:00
Alexander Bryukhov c35e842391 Localizing hardcoded strings 2017-06-21 02:44:59 +07:00
Alexander Bryukhov dae20cc986 Localizing hardcoded strings 2017-06-21 02:44:52 +07:00
Alexander Bryukhov c466514e7f Localizing hardcoded strings 2017-06-21 02:44:45 +07:00
Alexander Bryukhov 5e2aa7fa68 Localizing hardcoded strings 2017-06-21 02:44:39 +07:00
Alexander Bryukhov 11ccc88bc8 Localizing hardcoded strings 2017-06-21 02:44:33 +07:00
Alexander Bryukhov c83009c879 Localizing hardcoded strings 2017-06-21 02:44:26 +07:00
Alexander Bryukhov d6b9b41776 Localizing hardcoded strings 2017-06-21 02:44:19 +07:00
Alexander Bryukhov 508a4c32b4 Localizing hardcoded strings 2017-06-21 02:44:12 +07:00
Alexander Bryukhov dbf2538aae Localizing hardcoded strings 2017-06-21 02:44:06 +07:00
Alexander Bryukhov 5293b3bcc7 Localizing hardcoded strings 2017-06-21 02:44:00 +07:00
Alexander Bryukhov 940caba2c4 Localizing hardcoded strings 2017-06-21 02:43:53 +07:00
Alexander Bryukhov e31daef4fa Localizing hardcoded strings 2017-06-21 02:43:47 +07:00
Alexander Bryukhov 7984626433 Localizing hardcoded strings 2017-06-21 02:43:40 +07:00
Alexander Bryukhov ffa557b097 Localizing hardcoded strings 2017-06-21 02:43:33 +07:00
Alexander Bryukhov 9236bcbcd8 Localizing hardcoded strings 2017-06-21 02:43:26 +07:00
Alexander Bryukhov 1b875b0c67 Localizing hardcoded strings 2017-06-21 02:43:19 +07:00
Alexander Bryukhov ecce68da0a Localizing hardcoded strings 2017-06-21 02:43:12 +07:00
Alexander Bryukhov e27a882d2b Localizing hardcoded strings 2017-06-21 02:43:06 +07:00
Alexander Bryukhov c7ae379fd1 Localizing hardcoded strings 2017-06-21 02:42:59 +07:00
Alexander Bryukhov 8ad13f6853 Localizing hardcoded strings 2017-06-21 02:42:52 +07:00
Alexander Bryukhov e4ae40c2fe Localizing hardcoded strings 2017-06-21 02:42:45 +07:00
Alexander Bryukhov be61270e42 Localizing hardcoded strings 2017-06-21 02:42:38 +07:00
Alexander Bryukhov bd00b532eb Localizing hardcoded strings 2017-06-21 02:42:32 +07:00
Alexander Bryukhov ebc9478f2d Localizing hardcoded strings 2017-06-21 02:42:25 +07:00
Alexander Bryukhov ab72808a10 Localizing hardcoded strings 2017-06-21 02:42:18 +07:00
Alexander Bryukhov 068e82172a Localizing hardcoded strings 2017-06-21 02:42:10 +07:00
Alexander Bryukhov 45988d4f0c Localizing hardcoded strings 2017-06-21 02:42:02 +07:00
Alexander Bryukhov db330b3223 Localizing hardcoded strings 2017-06-21 02:41:54 +07:00
Alexander Bryukhov 03fd06cfa7 Localizing hardcoded strings 2017-06-21 02:41:45 +07:00
Alexander Bryukhov 775148d241 Localizing hardcoded strings 2017-06-21 02:41:37 +07:00
Alexander Bryukhov 8e65ecdc4a Localizing hardcoded strings 2017-06-21 02:41:27 +07:00
Alexander Bryukhov 6a43dd41c6 Localizing hardcoded strings 2017-06-21 02:41:19 +07:00
Alexander Bryukhov 82ae6a1aef Added localizationService
and localized two hardcoded strings
2017-06-21 02:41:04 +07:00
Alexander Bryukhov a127683d92 Adding & changing keys
for the views localization check
2017-06-21 02:40:47 +07:00
Alexander Bryukhov 06f3f4b191 Adding & changing keys
for the views localization check
2017-06-21 02:40:31 +07:00
Alexander Bryukhov a2f45a38f7 Adding & changing keys
for the views localization check
2017-06-21 02:40:05 +07:00
akierczynska 4b966ebe91 Update pl.xml 2017-06-20 17:31:18 +01:00
akierczynska da9e87d0ab Update pl.xml 2017-06-20 17:18:58 +01:00
akierczynska 84a206ce5e Update pl.xml 2017-06-20 16:12:12 +01:00
akierczynska 3c3c31c36e Update pl.xml 2017-06-20 16:08:17 +01:00
akierczynska 585f8e07f7 Update pl.xml 2017-06-20 16:03:46 +01:00
akierczynska f7c0e02bfd Update pl.xml 2017-06-20 16:00:47 +01:00
akierczynska e767eaa08b Update pl.xml
Update pl.xml to match en.xml and complete the translation
2017-06-20 15:57:50 +01:00
Claus ef32eda874 Merge branch 'temp-U4-8664' into dev-v7
fixing language selection.
2017-06-20 14:09:43 +02:00
Claus 01ccf8a6a6 Merge branch 'U4-8664' of https://github.com/DoctaJonez/Umbraco-CMS into temp-U4-8664 2017-06-20 12:59:28 +02:00
Sebastiaan Janssen c27ca1fb0d U4-9724 Tiny MCE error when adding a link "Cannot read property 'href' of undefined" 2017-06-20 10:16:00 +02:00
Shannon 68e287cf12 fixes $q reference 2017-06-20 18:11:26 +10:00
Shannon ad6946aa26 fixes error handler reference 2017-06-20 18:07:17 +10:00
Shannon Deminick 42d7c83a6d Merge pull request #2004 from umbraco/temp-u4-10026
U4-10026 - use id-key map for getting by guid
2017-06-20 17:01:35 +10:00
Stephan 1a435148d8 U4-10026 - inject idkmap 2017-06-20 08:55:08 +02:00
Stephan de348a9946 Merge remote-tracking branch 'origin/dev-v7' into temp-u4-10026 2017-06-20 08:41:04 +02:00
akierczynska 791e6a5f92 Update pl.xml 2017-06-19 18:19:35 +01:00
Shannon 1f6f8df5b5 Turns out when we empty the recycle bin we weren't removing associated cmsTask info. This also adds a null check since a SingleOrDefault call can return null. I've only seen this cause a problem when there is corrupt data but it should still be checked. 2017-06-19 23:48:18 +10:00
Niels Hartvig 7f5eff6e53 Fixes build, removes more unused client files 2017-06-19 15:43:53 +02:00
Shannon d885265818 Changes restart tracking to use code we used to have in there which is an in memory marker for the app domain, this is a little cleaner 2017-06-19 23:40:51 +10:00
Niels Hartvig be6140a38b Revert "More client files clean-up (including a duplicate tinymce)"
This reverts commit 8ee05063a2.
2017-06-19 15:27:36 +02:00
Niels Hartvig 8ee05063a2 More client files clean-up (including a duplicate tinymce) 2017-06-19 15:05:02 +02:00
Shannon 7920383904 U4-10034 Package install may not wait for app domain restart in all cases 2017-06-19 23:02:06 +10:00
Niels Hartvig 1a3d9e27f4 Removing unused v6 images 2017-06-19 14:46:21 +02:00
Shannon Deminick 2654f9189f Merge pull request #1973 from marcemarc/marcemarc-u4-9480
Revised fix for issue: U4-9489 - Just fix logResource.js parameters
2017-06-19 20:33:37 +10:00
Sebastiaan Janssen d7453b5a6e Updating the CG link so we can modify it without releasing a new version
Updated links to our/tv to be https
2017-06-19 09:49:15 +02:00
Sebastiaan Janssen 5ed8ceb85e Merge pull request #2000 from umbraco/updates-installer-764
Update installer photo + tlc on starter kit install screen
2017-06-19 09:34:40 +02:00
Mikkel Holck Madsen b7ea0840a9 Merge pull request #2007 from abryukhov/patch-6
Update ru.xml UI resources
2017-06-19 09:29:45 +02:00
Shannon Deminick 6b65f1c197 Merge pull request #1970 from Sam7/dev-v7
U4-9973 Remove sealed modifier from ExternalSignInAutoLinkOptions class
2017-06-19 17:27:24 +10:00
Alexander Bryukhov bc7dc8629e Update ru.xml UI resources
Couple of translation corrections
2017-06-18 18:35:48 +07:00
Michael Latouche d3c2b0a247 Merge pull request #2 from umbraco/dev-v7
Merge dev-v7 into my fork
2017-06-17 01:16:26 +02:00
Stephan 464711d3c8 U4-10026 - use id-key map for getting by guid 2017-06-16 14:09:20 +02:00
Mikkel Holck Madsen b15fd4496a Merge pull request #1699 from richarth/patch-2
Spelling and Grammar changes
2017-06-15 15:24:56 +02:00
Mikkel Holck Madsen b3ea0c83f9 Merge pull request #1832 from leekelleher/issue/U4-8098
Fixes U4-8900 - XPath: "$current" on Multinodetreepicker gives error in Document Type editor
2017-06-15 15:02:14 +02:00
Shannon Deminick c1aefe0686 Merge pull request #2002 from rmorrin/obsolete-namespace-errors
Fix incorrect namespace in deprecated class messages
2017-06-15 14:16:30 +02:00
Ryan Morrin 907dd8092a Fix incorrect namespace in deprecated class messages 2017-06-15 13:04:30 +01:00
Sebastiaan Janssen 7b5568ecb4 Merge pull request #1993 from AndersBrohus/U4-10008
U4-10008 - New danish translation for "Preview" - button
2017-06-15 12:43:25 +02:00
Shannon Deminick 2fd383960d Merge pull request #1997 from umbraco/temp-U4-10014
U4-10014 Making package install events public
2017-06-14 22:41:11 +02:00
Stephan 33f76d25f7 U4-9993 - fix upgrade issues 2017-06-14 15:04:56 +02:00
Niels Hartvig a2c5c35394 Update installer photo + tlc on starter kit install screen 2017-06-14 11:45:03 +02:00
Mikkel Holck Madsen c0616a37bf Merge pull request #1999 from umbraco/temp-tryAscii
Enable trying to convert urls to ascii
2017-06-14 10:12:58 +02:00
Mikkel Holck Madsen da4be3be65 Merge pull request #1995 from umbraco/temp-backofficeguids
Adds hoverstates for metadata(documenttypes, datatypes etc), making it possible to see their guids in the backoffice
2017-06-14 08:27:41 +02:00
Shannon Deminick 08c4a75af7 Merge pull request #1945 from protherj/U4-9792-fips-support
U4-9792 -- Update Umbraco to be FIPS compliant
2017-06-13 15:05:21 +02:00
Jeavon 047eb893eb Switches Umbraco.MediaPicker (double legacy) to being converted by MultipleMediaPickerPropertyConverter so that it actually works
Renames MultipleMediaPickerPropertyConverter to LegacyMediaPickerPropertyConverter (delete for v8)
2017-06-13 12:28:59 +01:00
Claus 308c381e17 U4-10014 Making package install events public 2017-06-13 13:28:23 +02:00
Jason Prothero e99309aa2f Merge pull request #3 from protherj/fips-refactoring
Added RFC 4122 compliant GUID support to StrringExtensions ToGuid()
2017-06-12 13:47:26 -07:00
Jason Prothero 917a2b78dd Added RFC 4122 compliant GUID support to the ToGuid() method on StrringExtensions.cs. Verified the SHA1 hash works with the ToGuid() method via unit tests. 2017-06-12 13:44:42 -07:00
Mads Rasmussen e559a6d485 add key as hover on name 2017-06-12 14:55:12 +02:00
Claus 160518e977 adding guids to backoffice. 2017-06-12 12:12:14 +02:00
Anders Brohus f985725118 Create da.xml 2017-06-11 22:01:57 +02:00
Brian Powell 5ec67ab3fd Apply Tom Fulton's fix for U4-9430 from https://github.com/tomfulton/Umbraco-CMS/commit/ba670586eba14092e6f1d20ee5e9aceb93e05f23 2017-06-09 11:40:38 -04:00
Harvey Williams 993513b138 Fix for IsDocumentTypeRecursive - U4-9997
Potential fix to issue logged on: http://issues.umbraco.org/issue/U4-9997
2017-06-08 15:17:34 +01:00
= 7f75802e4e allow DecimalValueConverter to understand signs in the front of the number. wonder if this could be more configurable as there are many other options avaialble." 2017-06-06 22:18:12 -06:00
Jeavon Leopold 5eb330b7d7 Add GetAbsoluteMediaUrl method to UrlHelper for the Open Graph starter kit lesson 2017-06-05 17:32:05 +02:00
AndyButland ce618d289b Extended HttpsCheck healthcheck to check for expiring SSL certificate 2017-06-05 16:43:17 +02:00
Sebastiaan Janssen 2191d33844 Bumps version 2017-06-05 16:33:47 +02:00
Sebastiaan Janssen 92a507bc87 New CG year 2017-06-05 16:02:04 +02:00
Niels Hartvig 1b844421fc Updates to installer to use the new starter kit (and updates core version) 2017-06-04 20:47:33 +02:00
Niels Hartvig df9c6baed7 Updates a few numbers in the installer 2017-06-04 18:10:29 +02:00
Sebastiaan Janssen 53357b0582 Merge pull request #1976 from umbraco/temp-U4-9980
Temp u4 9980
2017-06-04 14:55:23 +02:00
Sebastiaan Janssen 1164f1cdbb Merge branch 'dev-v7' into temp-U4-9980 2017-06-04 14:55:03 +02:00
Niels Hartvig 7f05b80a22 Make Seb happy 2017-06-04 14:02:05 +02:00
Niels Hartvig 20239a9b71 Adds a null check to avoid breaking tests (and to comform to coding standards) 2017-06-04 14:00:51 +02:00
Brian Powell 70a0bbbe61 Change font references: icomoon -> tinymce 2017-06-03 12:49:42 -04:00
Sebastiaan Janssen c4b07cc3ae Merge pull request #1974 from umbraco/temp-U4-9980
Adds support for keys in package content
2017-06-03 18:36:28 +02:00
Sebastiaan Janssen 771935b8a5 Update PackagingService.cs 2017-06-03 18:36:00 +02:00
Niels Hartvig 73bb401f81 Updating to TryParse to make Sir Janssen happy :-) 2017-06-03 18:34:09 +02:00
Niels Hartvig 8ccbe4c1e4 Adds support for keys in package content 2017-06-03 17:34:31 +02:00
Marc Goodson cf3343749f Revert fix to umbrequesthelper.service it was NEVER meant to be able to receive an array of a single dictionary item - actual fix is to change logResource to not pass params in this way 2017-06-02 21:04:12 +01:00
Marc Goodson 079df4a8b7 Pass logType and SinceDate as an array of key value pairs and not an array of a single dictionary - the logapi was never meant to be able to receive a dictionary... see comments on http://issues.umbraco.org/issue/U4-9489 for details 2017-06-02 21:02:46 +01:00
wanddy 7612884705 revert MediaService.cs 2017-06-02 23:41:19 +08:00
wanddy 74dc2d80fd Merge remote-tracking branch 'remotes/origin/dev-v7.6-chnfix' into dev-v7-chnfixnew
# Conflicts:
#	src/Umbraco.Core/Services/MediaService.cs
2017-06-02 23:33:16 +08:00
Wanddy Huang(黄仁祥) 647ebee34d Merge pull request #1 from umbraco/master-v7
merger umbraco/dev-v7  to my dev-v7
2017-06-02 22:43:44 +08:00
wanddy bc444847f4 Merge branch 'dev-v7.6' of https://github.com/umbraco/Umbraco-CMS into dev-v7.6-chnfix 2017-06-02 21:47:03 +08:00
Brian Powell 24d9c60bdf Update fonts and stylesheet to include table icons missing per U4-9977 2017-06-01 21:59:31 -04:00
Sam Sperling b5c2fc82bb U4-9973 Remove sealed modifier from ExternalSignInAutoLinkOptions class 2017-06-02 11:43:06 +10:00
Stephan a50256d381 Enable trying to convert urls to ascii 2017-06-01 17:58:22 +02:00
Stephan 290f34f034 FileSystemTreeController compatibility 2017-06-01 17:24:10 +02:00
Sebastiaan Janssen 92f609ff71 Merge pull request #1969 from umbraco/temp-U4-9974
U4-9974 EnablePropertyValueConverter does the opposite
2017-06-01 13:32:51 +02:00
Sebastiaan Janssen 7e6f7f8a2b Bumps version 2017-06-01 13:04:31 +02:00
Claus c5419e700b the legacy converter should not be associated to RelatedLinks2Alias and should only be enabled if EnablePropertyValueConverters is false, otherwise the other converter should be used. 2017-06-01 13:03:56 +02:00
Sebastiaan Janssen cb09094632 U4-9974 EnablePropertyValueConverter does the opposite 2017-06-01 10:57:15 +02:00
Sebastiaan Janssen 72404e68a0 Merge pull request #1968 from umbraco/temp-u4-9927
U4-9927 - fix migration
2017-05-31 16:36:42 +02:00
Sebastiaan Janssen 2c451c5cfe Remove debug tracing 2017-05-31 16:29:26 +02:00
Stephan af7f83f0f6 U4-9927 - fix migration 2017-05-31 15:49:15 +02:00
Shannon 5b3c2178a2 Revert "Merge pull request #1729 from marcemarc/marcemarc-U4-9480"
This reverts commit 145f789631, reversing
changes made to 78bc38fe1b.
2017-05-31 15:26:22 +02:00
Shannon Deminick 145f789631 Merge pull request #1729 from marcemarc/marcemarc-U4-9480
U4-9489 - dictonaryToQueryString only returns first dictionary item
2017-05-31 15:17:11 +02:00
Sebastiaan Janssen e27e95cb1a U4-9952 Can not save XSLT files in 7.6 2017-05-31 11:11:56 +02:00
Mikkel Holck Madsen cdbc3fa8cd Merge pull request #1967 from umbraco/temp-U4-9971
U4-9971 Special "square bracket" notation in Umbraco.Field not working
2017-05-31 10:55:17 +02:00
Sebastiaan Janssen 6feb7b222f U4-9971 Special "square bracket" notation in Umbraco.Field not working 2017-05-31 10:18:10 +02:00
Marc Stöcker 8b299a070f Update "Element hinzufügen" (Add grid element)
Key no longer used for first element exclusively for ages. New label just hints the (+) as button to add an element (being it the first one or not) -- very generic and thus hopefully future proof.
2017-05-24 12:16:46 +02:00
Poornima Nayar 782193b17a U4-9661 Remove "move" button in member section 2017-05-22 23:17:17 +01:00
Callum Whyte 4b945f355a Modifying Members list view to use key instead of Id 2017-05-18 22:54:44 +01:00
Callum Whyte 3cf8ef9513 Including key property in model when selecting items in list view 2017-05-18 22:54:19 +01:00
Jason Prothero 65654de06a Merge pull request #2 from protherj/fips-refactoring
Update Unit Tests to check for the correct version of Examine
2017-05-16 11:10:55 -07:00
Jason Prothero 2334596bf3 Update Unit Tests to check for the correct version of Examine 2017-05-16 11:06:00 -07:00
Jason Prothero 1d664bce52 Merge pull request #1 from protherj/fips-refactoring
Updated Examine Nuget to latest version 1.8.3
2017-05-16 09:14:02 -07:00
Jason Prothero 9a515de43f Updated Examine Nuget to latest version 1.8.3 2017-05-16 09:12:50 -07:00
Jason Prothero b55d065d45 Update to mark some methods as Obsolete and not seen by the VS editor 2017-05-11 09:17:56 -07:00
wanddy 83db63c5a8 Merge branch 'dev-v7.6-chnfix' of https://github.com/wanddy/Umbraco-CMS into dev-v7.6-chnfix 2017-05-11 16:29:10 +08:00
wanddy 1fb0b95428 Fix translation didn't work in some tree node. 2017-05-11 16:25:02 +08:00
wanddy 53e23f09dc Fix translation didn't work in some tree node. 2017-05-11 10:10:13 +08:00
wanddy 9e781173fc Merge branch 'dev-v7-chnfix' into dev-v7.6-chnfix 2017-05-11 09:25:02 +08:00
Jason Prothero fead30db38 Removed commented code for hash algorithm refactoring 2017-05-10 15:49:03 -07:00
Jason Prothero d8811d6b46 Refactored code for FIPS compliance support. Added/converted to using a more generic Hash() method instead of directly using MD5. 2017-05-10 13:35:28 -07:00
AndyButland dd40dd964c Ordered media types when returned for create dialog 2017-05-10 17:44:30 +02:00
wanddy bc51a98cfd Merge branch 'dev-v7-chnfix' into dev-v7.6-chnfix
# Conflicts:
#	src/Umbraco.Core/Services/MediaService.cs
#	src/Umbraco.Web/Trees/PartialViewMacrosTree.cs
#	src/Umbraco.Web/Trees/PartialViewsTree.cs
Fix some menu tree header won't be translated.
This may be caused by the explicit definition of tree node name.
Add missing translation item for en.xml and zh.xml
2017-05-10 23:25:03 +08:00
Chriztian Steinmeier 75e375ff54 Minor edits to the comments
Mainly "Id's" => "Ids" and "html" => "HTML" 👀
2017-05-05 23:55:23 +02:00
Chriztian Steinmeier 1a29a3237d Add files from Douglas Robar 2017-05-05 23:20:37 +02:00
Mike 8d8bb4e237 fix HasImage() 2017-03-31 17:24:18 +02:00
leekelleher 6772b1de35 MNTP Content Picker - when rendering using the DocumentType Editor, querying for the 'startNodeId' is unrequired and could throw exceptions.
This would patch would resolve the following issues...

- U4-7602 - "7.4 Data Types with xpath queries specified caused Document Type edit/creation issues."
- U4-8098 - "Content Type editor can fail while rendering"
- U4-8900 - "XPath: "$current" on Multinodetreepicker gives error in Document Type editor"
2017-03-25 13:45:57 +00:00
Bjarne Fyrstenborg ea13989b7e Allow leading whitespace in textstring prevalue editor 2017-03-02 23:19:45 +01:00
Marc Goodson 78bc38fe1b getUserLog and getLog don't have an id parameter
these methods blow up when the api doesn't return because they referenced an id variable that does not exist
2017-02-04 18:40:28 +00:00
Marc Goodson edb0a934a1 Fixes U4-9480
Allow more than one item from the dictionary object to be returned on the querystring
2017-02-04 18:35:47 +00:00
richarth f726dd59bf Spelling and Grammar changes
Spelling and Grammar changes
2017-01-20 11:47:10 +00:00
Pete Duncanson 9589500412 Fixed error label showing when you do a retry
Should be a nice and easy one, the bool for if the DB connection is valid or not is never cleared on when you do a retry.

http://issues.umbraco.org/issue/U4-9193
2017-01-06 20:40:09 +00:00
Michael Latouche 1c3b870ad2 Merge pull request #1 from umbraco/dev-v7
update my dev-v7 branch
2016-12-06 13:04:36 +01:00
Søren Gregersen 6a5002495c use already defined variable, instead of mapping the path twice
also fixed a slight indentation issue
2016-11-24 08:58:57 +01:00
bjarnef b3938cd7b2 Fix sorting of grid editor config 2016-11-22 20:39:18 +01:00
michael 3ce3a6f6ea Added files by mistake 2016-11-16 13:23:56 +01:00
michael b03e9f8fd5 issue U4-8967: updated labels as required and updated dialogs/linkpicker.html to be consistent with the structure overlay/linkpicker.html
I updated the labels in EN, FR, NL + other languages where I could figure out what was the update to perform.
2016-11-16 13:13:39 +01:00
gmargol 1e73bb12ac Fixing failing unit tests 2016-11-03 16:26:14 +00:00
Matthew Jones 662bf16a4f Fixed issue: U4-8664 TnyMCE RTE is not in the scope of UI localization.
The rich text editor previously had no knowledge of the current localisation region.

The complexity arrived from the $locale regions not having a direct mapping to TinyMce regions.  $locale regions are in the format of "de-de", "ru-ru", "en-gb", "en-us", etc.  The TinyMce locales are in the format of "de", "ru" and "en".  I've added some code in rte.controller.js to map from the former to the latter, but a fallback to "en" will need to be added if the current locale isn't supported by TinyMce, otherwise a runtime crash will occur.

The same is true of the codemirror plugin for TinyMce.  Language files don't exist for the plugin, but they are expected when different locales are provided.  I have therefore created placeholders that are equivalent to the TinyMce language files, but all are currently copied from english.
2016-11-03 16:13:03 +00:00
gmargol 26d450ad9a Adding optional parameters to tests 2016-11-03 11:31:33 +00:00
gmargol bab4c7715d Adding optional isApproved parameter instead of hardcoding 'true' value 2016-11-03 11:21:53 +00:00
AndyButland 27f121f25c Fixes debug setting health check to correctly indicate no issue if config setting is missing 2016-09-21 15:15:44 +02:00
rodyvansambeek b199f4072c Improved and added dutch translation
Added and changed some dutch translations, especially for members and subnodes (in a listview). The term "kinderen" only relates to children (persons), not items or nodes.
2016-02-17 09:46:49 +01:00
Mads Jørgensen 53928c02f8 Textarea made work 2014-04-16 22:20:55 +02:00
Mads Jørgensen 756d554b47 charlimit on textbox added 2014-04-16 20:55:45 +02:00
Mads Jørgensen fb4de621c0 Prevalue editor added to textbox 2014-04-16 20:10:53 +02:00
372 changed files with 9927 additions and 2995 deletions
-10
View File
@@ -125,22 +125,12 @@ IF NOT EXIST "%nuGetExecutable%" (
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')"
)
:: We need 7za.exe for BuildBelle.bat
IF NOT EXIST "%toolsFolder%7za.exe" (
ECHO 7zip not found - fetching now
"%nuGetExecutable%" install 7-Zip.CommandLine -OutputDirectory tools -Verbosity quiet
)
:: We need vswhere.exe for VS2017+
IF NOT EXIST "%toolsFolder%vswhere.exe" (
ECHO vswhere not found - fetching now
"%nuGetExecutable%" install vswhere -OutputDirectory tools -Verbosity quiet
)
:: Put 7za.exe and vswhere.exe in a predictable path (not version specific)
FOR /f "delims=" %%A in ('dir "%toolsFolder%7-Zip.CommandLine.*" /b') DO SET "sevenZipExePath=%toolsFolder%%%A\"
MOVE "%sevenZipExePath%tools\7za.exe" "%toolsFolder%7za.exe"
FOR /f "delims=" %%A in ('dir "%toolsFolder%vswhere.*" /b') DO SET "vswhereExePath=%toolsFolder%%%A\"
MOVE "%vswhereExePath%tools\vswhere.exe" "%toolsFolder%vswhere.exe"
+16 -7
View File
@@ -8,6 +8,22 @@ ECHO Current folder: %CD%
SET nodeFileName=node-v6.9.1-win-x86.7z
SET nodeExtractFolder=%toolsFolder%node.js.691
SET nuGetExecutable=%CD%\tools\nuget.exe
IF NOT EXIST "%nuGetExecutable%" (
ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable%
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')"
)
:: We need 7za.exe for BuildBelle.bat
IF NOT EXIST "%toolsFolder%7za.exe" (
ECHO 7zip not found - fetching now
"%nuGetExecutable%" install 7-Zip.CommandLine -OutputDirectory tools -Verbosity quiet
)
:: Put 7za.exe and vswhere.exe in a predictable path (not version specific)
FOR /f "delims=" %%A in ('dir "%toolsFolder%7-Zip.CommandLine.*" /b') DO SET "sevenZipExePath=%toolsFolder%%%A\"
MOVE "%sevenZipExePath%tools\7za.exe" "%toolsFolder%7za.exe"
IF NOT EXIST "%nodeExtractFolder%" (
ECHO Downloading http://nodejs.org/dist/v6.9.1/%nodeFileName% to %toolsFolder%%nodeFileName%
powershell -Command "(New-Object Net.WebClient).DownloadFile('http://nodejs.org/dist/v6.9.1/%nodeFileName%', '%toolsFolder%%nodeFileName%')"
@@ -16,13 +32,6 @@ IF NOT EXIST "%nodeExtractFolder%" (
)
FOR /f "delims=" %%A in ('dir "%nodeExtractFolder%\node*" /b') DO SET "nodePath=%nodeExtractFolder%\%%A"
SET nuGetExecutable=%CD%\tools\nuget.exe
IF NOT EXIST "%nuGetExecutable%" (
ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable%
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')"
)
SET drive=%CD:~0,2%
SET nuGetFolder=%drive%\packages\
FOR /f "delims=" %%A in ('dir "%nuGetFolder%npm.*" /b') DO SET "npmPath=%nuGetFolder%%%A\"
+1 -1
View File
@@ -34,7 +34,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="[10.0.2, 11.0.0)" />
<dependency id="Examine" version="[0.1.82, 1.0.0)" />
<dependency id="Examine" version="[0.1.83, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.5.3, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.8.3, 5.0.0)" />
<dependency id="semver" version="[1.1.2, 3.0.0)" />
+1 -1
View File
@@ -1,2 +1,2 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.6.2
7.6.6
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.6.2")]
[assembly: AssemblyInformationalVersion("7.6.2")]
[assembly: AssemblyFileVersion("7.6.6")]
[assembly: AssemblyInformationalVersion("7.6.6")]
+6 -6
View File
@@ -23,12 +23,12 @@ namespace Umbraco.Core
: base(serviceProvider, logger, packageActions)
{
}
/// <summary>
/// Gets the <see cref="IPackageAction"/> implementations.
/// </summary>
public IEnumerable<IAction> Actions
}
/// <summary>
/// Gets the <see cref="IAction"/> implementations.
/// </summary>
public IEnumerable<IAction> Actions
{
get
{
+22 -22
View File
@@ -48,7 +48,7 @@ namespace Umbraco.Core
/// <param name="cache"></param>
[Obsolete("Use the other constructor specifying a ProfilingLogger instead")]
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache)
: this(dbContext, serviceContext, cache,
: this(dbContext, serviceContext, cache,
new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler))
{
}
@@ -89,7 +89,7 @@ namespace Umbraco.Core
/// <param name="replaceContext">If set to true and the singleton is already set, it will be replaced</param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(ApplicationContext appContext, bool replaceContext)
{
@@ -107,14 +107,14 @@ namespace Umbraco.Core
/// </summary>
/// <param name="cache"></param>
/// <param name="replaceContext">
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// startup if for some reason the boot manager is not the umbraco boot manager.
/// </param>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// This is NOT thread safe
/// </remarks>
[Obsolete("Use the other method specifying an ProfilingLogger instead")]
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, bool replaceContext)
@@ -135,14 +135,14 @@ namespace Umbraco.Core
/// <param name="cache"></param>
/// <param name="logger"></param>
/// <param name="replaceContext">
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// startup if for some reason the boot manager is not the umbraco boot manager.
/// </param>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger, bool replaceContext)
{
@@ -175,7 +175,7 @@ namespace Umbraco.Core
public CacheHelper ApplicationCache { get; private set; }
/// <summary>
/// Exposes the global ProfilingLogger - this should generally not be accessed via the UmbracoContext and should normally just be exposed
/// Exposes the global ProfilingLogger - this should generally not be accessed via the UmbracoContext and should normally just be exposed
/// on most base classes or injected with IoC
/// </summary>
public ProfilingLogger ProfilingLogger { get; private set; }
@@ -213,7 +213,7 @@ namespace Umbraco.Core
// GlobalSettings.CurrentVersion returns the hard-coded "current version"
// the system is configured if they match
// if they don't, install runs, updates web.config (presumably) and updates GlobalSettings.ConfiguredStatus
public bool IsConfigured
{
get { return _configured.Value; }
@@ -226,8 +226,8 @@ namespace Umbraco.Core
{
get
{
if (IsConfigured == false
&& DatabaseContext != null
if (IsConfigured == false
&& DatabaseContext != null
&& DatabaseContext.IsDatabaseConfigured)
{
var schemaresult = DatabaseContext.ValidateDatabaseSchema();
@@ -274,12 +274,12 @@ namespace Umbraco.Core
private Lazy<bool> _configured;
internal MainDom MainDom { get; private set; }
private void Init()
{
MainDom = new MainDom(ProfilingLogger.Logger);
MainDom.Acquire();
//Create the lazy value to resolve whether or not the application is 'configured'
_configured = new Lazy<bool>(() =>
{
@@ -289,7 +289,7 @@ namespace Umbraco.Core
var currentVersion = UmbracoVersion.GetSemanticVersion();
var ok =
//we are not configured if this is null
//we are not configured if this is null
string.IsNullOrWhiteSpace(configStatus) == false
//they must match
&& configStatus == currentVersion;
@@ -303,7 +303,7 @@ namespace Umbraco.Core
var found = Services.MigrationEntryService.FindEntry(Constants.System.UmbracoMigrationName, UmbracoVersion.GetSemanticVersion());
if (found == null)
{
//we haven't executed this migration in this environment, so even though the config versions match,
//we haven't executed this migration in this environment, so even though the config versions match,
// this db has not been updated.
ProfilingLogger.Logger.Debug<ApplicationContext>(string.Format("The migration for version: '{0} has not been executed, there is no record in the database", currentVersion.ToSemanticString()));
ok = false;
@@ -323,7 +323,7 @@ namespace Umbraco.Core
return false;
}
});
});
}
private string ConfigurationStatus
@@ -338,7 +338,7 @@ namespace Umbraco.Core
{
return String.Empty;
}
}
}
}
private void AssertIsNotReady()
@@ -363,7 +363,7 @@ namespace Umbraco.Core
}
internal set { _databaseContext = value; }
}
/// <summary>
/// Gets the current ServiceContext
/// </summary>
@@ -417,7 +417,7 @@ namespace Umbraco.Core
ResolverCollection.ResetAll();
//reset resolution itself (though this should be taken care of by resetting any of the resolvers above)
Resolution.Reset();
//reset the instance objects
this.ApplicationCache = null;
if (_databaseContext != null) //need to check the internal field here
@@ -430,14 +430,14 @@ namespace Umbraco.Core
/*
if (DatabaseContext.IsDatabaseConfigured && DatabaseContext.Database != null)
{
DatabaseContext.Database.Dispose();
}
*/
DatabaseContext.Database.Dispose();
}
*/
}
this.DatabaseContext = null;
this.Services = null;
this._isReady = false; //set the internal field
// Indicate that the instance has been disposed.
_disposed = true;
}
+2 -2
View File
@@ -89,7 +89,7 @@ namespace Umbraco.Core.Cache
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
public const string IdToKeyCacheKey = "UI2K";
public const string KeyToIdCacheKey = "UK2I";
public const string IdToKeyCacheKey = "UI2K__";
public const string KeyToIdCacheKey = "UK2I__";
}
}
@@ -12,6 +12,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool ConvertUrlsToAscii { get; }
bool TryConvertUrlsToAscii { get; }
IEnumerable<IChar> CharCollection { get; }
}
}
@@ -111,7 +111,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool IRequestHandlerSection.ConvertUrlsToAscii
{
get { return UrlReplacing.ConvertUrlsToAscii; }
get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true"); }
}
bool IRequestHandlerSection.TryConvertUrlsToAscii
{
get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try"); }
}
IEnumerable<IChar> IRequestHandlerSection.CharCollection
@@ -11,10 +11,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return (bool) base["removeDoubleDashes"]; }
}
[ConfigurationProperty("toAscii", DefaultValue = false)]
internal bool ConvertUrlsToAscii
[ConfigurationProperty("toAscii", DefaultValue = "false")]
internal string ConvertUrlsToAscii
{
get { return (bool)base["toAscii"]; }
get { return (string) base["toAscii"]; }
}
[ConfigurationCollection(typeof(CharCollection), AddItemName = "char")]
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.6.2");
private static readonly Version Version = new Version("7.6.6");
/// <summary>
/// Gets the current version of Umbraco.
@@ -33,9 +33,9 @@ namespace Umbraco.Core.Configuration
public static SemVersion GetSemanticVersion()
{
return new SemVersion(
Current.Major,
Current.Major,
Current.Minor,
Current.Build,
Current.Build,
CurrentComment.IsNullOrWhiteSpace() ? null : CurrentComment,
Current.Revision > 0 ? Current.Revision.ToInvariantString() : null);
}
+10
View File
@@ -212,6 +212,16 @@ namespace Umbraco.Core
/// Guid for a Forms DataSource.
/// </summary>
public static readonly Guid FormsDataSourceGuid = new Guid(FormsDataSource);
/// <summary>
/// Guid for a Language.
/// </summary>
public const string Language = "6B05D05B-EC78-49BE-A4E4-79E274F07A77";
/// <summary>
/// Guid for a Forms DataSource.
/// </summary>
public static readonly Guid LanguageGuid = new Guid(Language);
}
}
}
+2
View File
@@ -14,6 +14,8 @@ namespace Umbraco.Core
public const string BackOfficeTokenAuthenticationType = "UmbracoBackOfficeToken";
public const string BackOfficeTwoFactorAuthenticationType = "UmbracoTwoFactorCookie";
internal const string EmptyPasswordPrefix = "___UIDEMPTYPWORD__";
/// <summary>
/// The prefix used for external identity providers for their authentication type
/// </summary>
+20 -11
View File
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Security.Permissions;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.Events
{
@@ -13,6 +12,9 @@ namespace Umbraco.Core.Events
public class CancellableEventArgs : EventArgs, IEquatable<CancellableEventArgs>
{
private bool _cancel;
private Dictionary<string, object> _eventState;
private static readonly ReadOnlyDictionary<string, object> EmptyAdditionalData = new ReadOnlyDictionary<string, object>(new Dictionary<string, object>());
public CancellableEventArgs(bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
{
@@ -26,7 +28,7 @@ namespace Umbraco.Core.Events
if (eventMessages == null) throw new ArgumentNullException("eventMessages");
CanCancel = canCancel;
Messages = eventMessages;
AdditionalData = new ReadOnlyDictionary<string, object>(new Dictionary<string, object>());
AdditionalData = EmptyAdditionalData;
}
public CancellableEventArgs(bool canCancel)
@@ -34,18 +36,16 @@ namespace Umbraco.Core.Events
CanCancel = canCancel;
//create a standalone messages
Messages = new EventMessages();
AdditionalData = new ReadOnlyDictionary<string, object>(new Dictionary<string, object>());
AdditionalData = EmptyAdditionalData;
}
public CancellableEventArgs(EventMessages eventMessages)
: this(true, eventMessages)
{
}
{ }
public CancellableEventArgs()
: this(true)
{
}
{ }
/// <summary>
/// Flag to determine if this instance will support being cancellable
@@ -95,10 +95,19 @@ namespace Umbraco.Core.Events
/// In some cases raised evens might need to contain additional arbitrary readonly data which can be read by event subscribers
/// </summary>
/// <remarks>
/// This allows for a bit of flexibility in our event raising - it's not pretty but we need to maintain backwards compatibility
/// This allows for a bit of flexibility in our event raising - it's not pretty but we need to maintain backwards compatibility
/// so we cannot change the strongly typed nature for some events.
/// </remarks>
public ReadOnlyDictionary<string, object> AdditionalData { get; private set; }
/// <summary>
/// This can be used by event subscribers to store state in the event args so they easily deal with custom state data between a starting ("ing")
/// event and an ending ("ed") event
/// </summary>
public IDictionary<string, object> EventState
{
get { return _eventState ?? (_eventState = new Dictionary<string, object>()); }
}
public bool Equals(CancellableEventArgs other)
{
@@ -111,13 +120,13 @@ namespace Umbraco.Core.Events
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
if (obj.GetType() != GetType()) return false;
return Equals((CancellableEventArgs) obj);
}
public override int GetHashCode()
{
return (AdditionalData != null ? AdditionalData.GetHashCode() : 0);
return AdditionalData != null ? AdditionalData.GetHashCode() : 0;
}
public static bool operator ==(CancellableEventArgs left, CancellableEventArgs right)
@@ -127,7 +136,7 @@ namespace Umbraco.Core.Events
public static bool operator !=(CancellableEventArgs left, CancellableEventArgs right)
{
return !Equals(left, right);
return Equals(left, right) == false;
}
}
}
+2 -1
View File
@@ -99,7 +99,8 @@ namespace Umbraco.Core.Events
/// </summary>
public IEnumerable<TEntity> DeletedEntities
{
get { return EventObject; }
get { return EventObject; }
internal set { EventObject = value; }
}
/// <summary>
@@ -4,7 +4,7 @@ using Umbraco.Core.Packaging.Models;
namespace Umbraco.Core.Events
{
internal class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
public class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
{
private readonly MetaData _packageMetaData;
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Events
public bool Equals(ImportPackageEventArgs<TEntity> other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (ReferenceEquals(this, other)) return true;
//TODO: MetaData for package metadata has no equality operators :/
return base.Equals(other) && _packageMetaData.Equals(other._packageMetaData);
}
+20 -1
View File
@@ -6,6 +6,8 @@ namespace Umbraco.Core.Events
{
public class MoveEventArgs<TEntity> : CancellableObjectEventArgs<TEntity>, IEquatable<MoveEventArgs<TEntity>>
{
private IEnumerable<MoveEventInfo<TEntity>> _moveInfoCollection;
/// <summary>
/// Constructor accepting a collection of MoveEventInfo objects
/// </summary>
@@ -107,7 +109,24 @@ namespace Umbraco.Core.Events
/// <summary>
/// Gets all MoveEventInfo objects used to create the object
/// </summary>
public IEnumerable<MoveEventInfo<TEntity>> MoveInfoCollection { get; private set; }
public IEnumerable<MoveEventInfo<TEntity>> MoveInfoCollection
{
get { return _moveInfoCollection; }
set
{
var first = value.FirstOrDefault();
if (first == null)
{
throw new InvalidOperationException("MoveInfoCollection must have at least one item");
}
_moveInfoCollection = value;
//assign the legacy props
EventObject = first.Entity;
ParentId = first.NewParentId;
}
}
/// <summary>
/// The entity being moved
@@ -107,7 +107,7 @@ namespace Umbraco.Core.Events
/// <summary>
/// Boolean indicating whether the Recycle Bin was emptied successfully
/// </summary>
public bool RecycleBinEmptiedSuccessfully { get; private set; }
public bool RecycleBinEmptiedSuccessfully { get; set; }
/// <summary>
/// Boolean indicating whether this event was fired for the Content's Recycle Bin.
@@ -3,7 +3,7 @@ using Umbraco.Core.Packaging.Models;
namespace Umbraco.Core.Events
{
internal class UninstallPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
public class UninstallPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
{
private readonly MetaData _packageMetaData;
+4 -2
View File
@@ -2,17 +2,19 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace Umbraco.Core
{
/// <summary>
/// Used to create a hash code from multiple objects.
/// Used to create a .NET HashCode from multiple objects.
/// </summary>
/// <remarks>
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
/// which we've not included here as we just need a quick easy class for this in order to create a unique
/// hash of directories/files to see if they have changed.
///
/// NOTE: It's probably best to not relying on the hashing result across AppDomains! If you need a constant/reliable hash value
/// between AppDomains use SHA1. This is perfect for hashing things in a very fast way for a single AppDomain.
/// </remarks>
internal class HashCodeCombiner
{
+154
View File
@@ -0,0 +1,154 @@
using System;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Umbraco.Core
{
/// <summary>
/// Used to generate a string hash using crypto libraries over multiple objects
/// </summary>
/// <remarks>
/// This should be used to generate a reliable hash that survives AppDomain restarts.
/// This will use the crypto libs to generate the hash and will try to ensure that
/// strings, etc... are not re-allocated so it's not consuming much memory.
/// </remarks>
internal class HashGenerator : DisposableObject
{
public HashGenerator()
{
_writer = new StreamWriter(_ms, Encoding.Unicode, 1024, leaveOpen: true);
}
private readonly MemoryStream _ms = new MemoryStream();
private StreamWriter _writer;
internal void AddInt(int i)
{
_writer.Write(i);
}
internal void AddLong(long i)
{
_writer.Write(i);
}
internal void AddObject(object o)
{
_writer.Write(o);
}
internal void AddDateTime(DateTime d)
{
_writer.Write(d.Ticks);;
}
internal void AddString(string s)
{
if (s != null)
_writer.Write(s);
}
internal void AddCaseInsensitiveString(string s)
{
//I've tried to no allocate a new string with this which can be done if we use the CompareInfo.GetSortKey method which will create a new
//byte array that we can use to write to the output, however this also allocates new objects so i really don't think the performance
//would be much different. In any case, i'll leave this here for reference. We could write the bytes out based on the sort key,
//this is how we could deal with case insensitivity without allocating another string
//for reference see: https://stackoverflow.com/a/10452967/694494
//we could go a step further and s.Normalize() but we're not really dealing with crazy unicode with this class so far.
if (s != null)
_writer.Write(s.ToUpperInvariant());
}
internal void AddFileSystemItem(FileSystemInfo f)
{
//if it doesn't exist, don't proceed.
if (f.Exists == false)
return;
AddCaseInsensitiveString(f.FullName);
AddDateTime(f.CreationTimeUtc);
AddDateTime(f.LastWriteTimeUtc);
//check if it is a file or folder
var fileInfo = f as FileInfo;
if (fileInfo != null)
{
AddLong(fileInfo.Length);
}
var dirInfo = f as DirectoryInfo;
if (dirInfo != null)
{
foreach (var d in dirInfo.GetFiles())
{
AddFile(d);
}
foreach (var s in dirInfo.GetDirectories())
{
AddFolder(s);
}
}
}
internal void AddFile(FileInfo f)
{
AddFileSystemItem(f);
}
internal void AddFolder(DirectoryInfo d)
{
AddFileSystemItem(d);
}
/// <summary>
/// Returns the generated hash output of all added objects
/// </summary>
/// <returns></returns>
internal string GenerateHash()
{
//flush,close,dispose the writer,then create a new one since it's possible to keep adding after GenerateHash is called.
_writer.Flush();
_writer.Close();
_writer.Dispose();
_writer = new StreamWriter(_ms, Encoding.UTF8, 1024, leaveOpen: true);
var hashType = CryptoConfig.AllowOnlyFipsAlgorithms ? "SHA1" : "MD5";
//create an instance of the correct hashing provider based on the type passed in
var hasher = HashAlgorithm.Create(hashType);
if (hasher == null) throw new InvalidOperationException("No hashing type found by name " + hashType);
using (hasher)
{
var buffer = _ms.GetBuffer();
//get the hashed values created by our selected provider
var hashedByteArray = hasher.ComputeHash(buffer);
//create a StringBuilder object
var stringBuilder = new StringBuilder();
//loop to each each byte
foreach (var b in hashedByteArray)
{
//append it to our StringBuilder
stringBuilder.Append(b.ToString("x2"));
}
//return the hashed value
return stringBuilder.ToString();
}
}
protected override void DisposeResources()
{
_writer.Close();
_writer.Dispose();
_ms.Close();
_ms.Dispose();
}
}
}
@@ -19,6 +19,8 @@ namespace Umbraco.Core.IO
private ShadowWrapper _macroPartialFileSystem;
private ShadowWrapper _partialViewsFileSystem;
private ShadowWrapper _macroScriptsFileSystem;
private ShadowWrapper _userControlsFileSystem;
private ShadowWrapper _stylesheetsFileSystem;
private ShadowWrapper _scriptsFileSystem;
private ShadowWrapper _xsltFileSystem;
@@ -61,6 +63,8 @@ namespace Umbraco.Core.IO
{
var macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
var macroScriptsFileSystem = new PhysicalFileSystem(SystemDirectories.MacroScripts);
var userControlsFileSystem = new PhysicalFileSystem(SystemDirectories.UserControls);
var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
var scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts);
var xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
@@ -69,6 +73,8 @@ namespace Umbraco.Core.IO
_macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", ScopeProvider);
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", ScopeProvider);
_macroScriptsFileSystem = new ShadowWrapper(macroScriptsFileSystem, "macroScripts", ScopeProvider);
_userControlsFileSystem = new ShadowWrapper(userControlsFileSystem, "usercontrols", ScopeProvider);
_stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", ScopeProvider);
_scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", ScopeProvider);
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", ScopeProvider);
@@ -85,6 +91,10 @@ namespace Umbraco.Core.IO
public IFileSystem2 MacroPartialsFileSystem { get { return _macroPartialFileSystem; } }
public IFileSystem2 PartialViewsFileSystem { get { return _partialViewsFileSystem; } }
// Legacy /macroScripts folder
public IFileSystem2 MacroScriptsFileSystem { get { return _macroScriptsFileSystem; } }
// Legacy /usercontrols folder
public IFileSystem2 UserControlsFileSystem { get { return _userControlsFileSystem; } }
public IFileSystem2 StylesheetsFileSystem { get { return _stylesheetsFileSystem; } }
public IFileSystem2 ScriptsFileSystem { get { return _scriptsFileSystem; } }
public IFileSystem2 XsltFileSystem { get { return _xsltFileSystem; } }
@@ -252,13 +262,15 @@ namespace Umbraco.Core.IO
internal ICompletable Shadow(Guid id)
{
var typed = _wrappers.ToArray();
var wrappers = new ShadowWrapper[typed.Length + 7];
var wrappers = new ShadowWrapper[typed.Length + 9];
var i = 0;
while (i < typed.Length) wrappers[i] = typed[i++];
wrappers[i++] = _macroPartialFileSystem;
wrappers[i++] = _macroScriptsFileSystem;
wrappers[i++] = _partialViewsFileSystem;
wrappers[i++] = _stylesheetsFileSystem;
wrappers[i++] = _scriptsFileSystem;
wrappers[i++] = _userControlsFileSystem;
wrappers[i++] = _xsltFileSystem;
wrappers[i++] = _masterPagesFileSystem;
wrappers[i] = _mvcViewsFileSystem;
+2
View File
@@ -97,6 +97,8 @@ namespace Umbraco.Core.IO
public static string MapPath(string path, bool useHttpContext)
{
if (path == null) throw new ArgumentNullException("path");
// Check if the path is already mapped
if ((path.Length >= 2 && path[1] == Path.VolumeSeparatorChar)
|| path.StartsWith(@"\\")) //UNC Paths start with "\\". If the site is running off a network drive mapped paths will look like "\\Whatever\Boo\Bar"
+7 -2
View File
@@ -264,7 +264,7 @@ namespace Umbraco.Core.Models
/// <returns><see cref="Property"/> Value as an <see cref="object"/></returns>
public virtual object GetValue(string propertyTypeAlias)
{
return Properties[propertyTypeAlias].Value;
return Properties.Contains(propertyTypeAlias) ? Properties[propertyTypeAlias].Value : null;
}
/// <summary>
@@ -275,8 +275,13 @@ namespace Umbraco.Core.Models
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
public virtual TPassType GetValue<TPassType>(string propertyTypeAlias)
{
if (Properties.Contains(propertyTypeAlias) == false)
{
return default(TPassType);
}
var convertAttempt = Properties[propertyTypeAlias].Value.TryConvertTo<TPassType>();
return convertAttempt.Success ? convertAttempt.Result : default(TPassType);
return convertAttempt.Success ? convertAttempt.Result : default(TPassType);
}
/// <summary>
+7
View File
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Models
{
public interface IUserControl : IFile
{
}
}
@@ -42,7 +42,7 @@ namespace Umbraco.Core.Models.Identity
private string GetPasswordHash(string storedPass)
{
return storedPass.StartsWith("___UIDEMPTYPWORD__") ? null : storedPass;
return storedPass.StartsWith(Constants.Security.EmptyPasswordPrefix) ? null : storedPass;
}
}
}
+24
View File
@@ -109,6 +109,30 @@ namespace Umbraco.Core.Models
IsApproved = true;
}
/// <summary>
/// Constructor for creating a Member object
/// </summary>
/// <param name="name"></param>
/// <param name="email"></param>
/// <param name="username"></param>
/// <param name="rawPasswordValue">
/// The password value passed in to this parameter should be the encoded/encrypted/hashed format of the member's password
/// </param>
/// <param name="contentType"></param>
/// <param name="isApproved"></param>
public Member(string name, string email, string username, string rawPasswordValue, IMemberType contentType, bool isApproved)
: base(name, -1, contentType, new PropertyCollection())
{
Mandate.ParameterNotNull(contentType, "contentType");
_contentTypeAlias = contentType.Alias;
_contentType = contentType;
_email = email;
_username = username;
_rawPasswordValue = rawPasswordValue;
IsApproved = isApproved;
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
+2 -1
View File
@@ -4,6 +4,7 @@
{
Unknown = 0, // default
PartialView = 1,
PartialViewMacro = 2
PartialViewMacro = 2,
MacroScript = 3
}
}
@@ -178,6 +178,13 @@ namespace Umbraco.Core.Models
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.FormsDataSource)]
[FriendlyName("DataSource")]
FormsDataSource
FormsDataSource,
/// <summary>
/// Language
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.Language)]
[FriendlyName("Language")]
Language
}
}
+32
View File
@@ -0,0 +1,32 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a UserControl file
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class UserControl : File, IUserControl
{
public UserControl(string path)
: this(path, (Func<File, string>)null)
{ }
internal UserControl(string path, Func<File, string> getFileContent)
: base(path, getFileContent)
{ }
/// <summary>
/// Indicates whether the current entity has an identity, which in this case is a path/name.
/// </summary>
/// <remarks>
/// Overrides the default Entity identity check.
/// </remarks>
public override bool HasIdentity
{
get { return string.IsNullOrEmpty(Path) == false; }
}
}
}
+3 -2
View File
@@ -1,5 +1,6 @@
using System;
using System.Globalization;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
@@ -12,7 +13,7 @@ namespace Umbraco.Core.Models
/// </summary>
/// <param name="user"></param>
/// <param name="textService"></param>
/// <returns></returns>
/// <returns></returns>
public static CultureInfo GetUserCulture(this IUser user, ILocalizedTextService textService)
{
if (user == null) throw new ArgumentNullException("user");
@@ -34,7 +35,7 @@ namespace Umbraco.Core.Models
catch (CultureNotFoundException)
{
//return the default one
return CultureInfo.GetCultureInfo("en");
return CultureInfo.GetCultureInfo(GlobalSettings.DefaultUILanguage);
}
}
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Packaging.Models
{
[Serializable]
[DataContract(IsReference = true)]
internal class InstallationSummary
public class InstallationSummary
{
public MetaData MetaData { get; set; }
public IEnumerable<IDataTypeDefinition> DataTypesInstalled { get; set; }
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Packaging.Models
{
[Serializable]
[DataContract(IsReference = true)]
internal class MetaData
public class MetaData
{
public string Name { get; set; }
public string Version { get; set; }
@@ -4,7 +4,7 @@ using System.Xml.Linq;
namespace Umbraco.Core.Packaging.Models
{
internal enum ActionRunAt
public enum ActionRunAt
{
Undefined = 0,
Install,
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Packaging.Models
[Serializable]
[DataContract(IsReference = true)]
internal class PackageAction
public class PackageAction
{
private ActionRunAt _runAt;
private bool? _undo;
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Packaging.Models
{
[Serializable]
[DataContract(IsReference = true)]
internal class UninstallationSummary
public class UninstallationSummary
{
public MetaData MetaData { get; set; }
public IEnumerable<IDataTypeDefinition> DataTypesUninstalled { get; set; }
@@ -2,6 +2,7 @@
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
@@ -16,7 +17,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
public override void Up()
{
var exists = Context.Database.FirstOrDefault<RelationTypeDto>("WHERE alias=@alias", new {alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias});
var exists = Context.Database.FirstOrDefault<RelationTypeDtoCapture>("WHERE alias=@alias", new {alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias});
if (exists == null)
{
Insert.IntoTable("umbracoRelationType").Row(new
@@ -28,13 +29,42 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias
});
}
}
public override void Down()
{ }
// need to capture the DTO as it is modified in later migrations
[TableName("umbracoRelationType")]
[PrimaryKey("id")]
[ExplicitColumns]
internal class RelationTypeDtoCapture
{
public const int NodeIdSeed = 3;
[Column("id")]
[PrimaryKeyColumn(IdentitySeed = NodeIdSeed)]
public int Id { get; set; }
[Column("dual")]
public bool Dual { get; set; }
[Column("parentObjectType")]
public Guid ParentObjectType { get; set; }
[Column("childObjectType")]
public Guid ChildObjectType { get; set; }
[Column("name")]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoRelationType_name")]
public string Name { get; set; }
[Column("alias")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(100)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoRelationType_alias")]
public string Alias { get; set; }
}
}
}
@@ -1,5 +1,4 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -11,15 +10,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
{
public UpdateUniqueIdToHaveCorrectIndexType(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
}
{ }
//see: http://issues.umbraco.org/issue/U4-6188, http://issues.umbraco.org/issue/U4-6187
public override void Up()
{
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
var indexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
@@ -28,24 +23,19 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
IsUnique = x.Item4
}).ToArray();
//must be non-nullable
// drop the index if it exists
if (indexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")))
Delete.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode");
// set uniqueID to be non-nullable
// the index *must* be dropped else 'one or more objects access this column' exception
Alter.Table("umbracoNode").AlterColumn("uniqueID").AsGuid().NotNullable();
//make sure it already exists
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")))
{
Delete.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode");
}
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNode_uniqueID")) == false)
{
//must be a uniqe index
Create.Index("IX_umbracoNode_uniqueID").OnTable("umbracoNode").OnColumn("uniqueID").Unique();
}
// create the index
Create.Index("IX_umbracoNode_uniqueID").OnTable("umbracoNode").OnColumn("uniqueID").Unique();
}
public override void Down()
{
}
{ }
}
}
@@ -1,46 +0,0 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
{
[Migration("7.2.0", 3, Constants.System.UmbracoMigrationName)]
public class AddIndexToUmbracoNodeTable : MigrationBase
{
private readonly bool _skipIndexCheck;
internal AddIndexToUmbracoNodeTable(ISqlSyntaxProvider sqlSyntax, ILogger logger, bool skipIndexCheck) : base(sqlSyntax, logger)
{
_skipIndexCheck = skipIndexCheck;
}
public AddIndexToUmbracoNodeTable(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
{
}
public override void Up()
{
var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[] { } : SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")) == false)
{
Create.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode").OnColumn("uniqueID").Ascending().WithOptions().NonClustered();
}
}
public override void Down()
{
Delete.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode");
}
}
}
@@ -81,7 +81,7 @@ namespace Umbraco.Core.Persistence.Repositories
s.Where<DocumentDto>(x => x.Newest, SqlSyntax);
return s;
};
var sqlBaseFull = GetBaseQuery(BaseQueryType.FullMultiple);
var sqlBaseIds = GetBaseQuery(BaseQueryType.Ids);
@@ -107,7 +107,7 @@ namespace Umbraco.Core.Persistence.Repositories
return ProcessQuery(translate(translatorFull), new PagingSqlQuery(translate(translatorIds)));
}
#endregion
#endregion
#region Overrides of PetaPocoRepositoryBase<IContent>
@@ -142,8 +142,8 @@ namespace Umbraco.Core.Persistence.Repositories
{
//The only reason we apply this left outer join is to be able to pull back the DocumentPublishedReadOnlyDto
//information with the entire data set, so basically this will get both the latest document and also it's published
//version if it has one. When performing a count or when retrieving Ids like in paging, this is unecessary
//and causes huge performance overhead for the SQL server, especially when sorting the result.
//version if it has one. When performing a count or when retrieving Ids like in paging, this is unecessary
//and causes huge performance overhead for the SQL server, especially when sorting the result.
//We also don't include this outer join when querying for multiple entities since it is much faster to fetch this information
//in a separate query. For a single entity this is ok.
@@ -234,7 +234,7 @@ namespace Umbraco.Core.Persistence.Repositories
};
var baseId = 0;
while (true)
{
// get the next group of nodes
@@ -284,7 +284,7 @@ namespace Umbraco.Core.Persistence.Repositories
}
xmlIdsQuery.Where<NodeDto>(dto => dto.NodeObjectType == docObjectType, SqlSyntax);
var allXmlIds = Database.Fetch<int>(xmlIdsQuery);
var toRemove = allXmlIds.Except(allContentIds).ToArray();
@@ -293,9 +293,9 @@ namespace Umbraco.Core.Persistence.Repositories
foreach (var idGroup in toRemove.InGroupsOf(2000))
{
Database.Execute("DELETE FROM cmsContentXml WHERE nodeId IN (@ids)", new { ids = idGroup });
}
}
}
}
public override IEnumerable<IContent> GetAllVersions(int id)
@@ -308,7 +308,7 @@ namespace Umbraco.Core.Persistence.Repositories
var sqlFull = translate(GetBaseQuery(BaseQueryType.FullMultiple));
var sqlIds = translate(GetBaseQuery(BaseQueryType.Ids));
return ProcessQuery(sqlFull, new PagingSqlQuery(sqlIds), true, includeAllVersions:true);
}
@@ -388,7 +388,7 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PersistDeletedItem(IContent entity)
{
//We need to clear out all access rules but we need to do this in a manual way since
//We need to clear out all access rules but we need to do this in a manual way since
// nothing in that table is joined to a content id
var subQuery = new Sql()
.Select("umbracoAccessRule.accessId")
@@ -449,7 +449,7 @@ namespace Umbraco.Core.Persistence.Repositories
entity.Level = level;
//Assign the same permissions to it as the parent node
// http://issues.umbraco.org/issue/U4-2161
// http://issues.umbraco.org/issue/U4-2161
var permissionsRepo = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper, SqlSyntax);
var parentPermissions = permissionsRepo.GetPermissionsForEntity(entity.ParentId).ToArray();
//if there are parent permissions then assign them, otherwise leave null and permissions will become the
@@ -516,7 +516,7 @@ namespace Umbraco.Core.Persistence.Repositories
VersionDate = dto.UpdateDate,
Newest = true,
NodeId = dto.NodeId,
Published = true
Published = true
};
((Content) entity).PublishedVersionGuid = dto.VersionId;
((Content) entity).PublishedDate = dto.UpdateDate;
@@ -636,9 +636,12 @@ namespace Umbraco.Core.Persistence.Repositories
{
//In order to update the ContentVersion we need to retrieve its primary key id
var contentVerDto = Database.SingleOrDefault<ContentVersionDto>("WHERE VersionId = @Version", new { Version = entity.Version });
contentVersionDto.Id = contentVerDto.Id;
Database.Update(contentVersionDto);
if (contentVerDto != null)
{
contentVersionDto.Id = contentVerDto.Id;
Database.Update(contentVersionDto);
}
Database.Update(dto);
}
@@ -742,7 +745,7 @@ namespace Umbraco.Core.Persistence.Repositories
return ProcessQuery(translate(translatorFull), new PagingSqlQuery(translate(translatorIds)), true);
}
/// <summary>
/// This builds the Xml document used for the XML cache
/// </summary>
@@ -841,7 +844,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
/// </summary>
/// <param name="entity"></param>
/// <param name="permission"></param>
/// <param name="userIds"></param>
/// <param name="userIds"></param>
public void AssignEntityPermission(IContent entity, char permission, IEnumerable<int> userIds)
{
var repo = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper, SqlSyntax);
@@ -899,9 +902,9 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
string orderBy, Direction orderDirection, bool orderBySystemField, IQuery<IContent> filter = null)
{
//NOTE: This uses the GetBaseQuery method but that does not take into account the required 'newest' field which is
//NOTE: This uses the GetBaseQuery method but that does not take into account the required 'newest' field which is
// what we always require for a paged result, so we'll ensure it's included in the filter
var filterSql = new Sql().Append("AND (cmsDocument.newest = 1)");
if (filter != null)
{
@@ -910,7 +913,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
filterSql.Append(string.Format("AND ({0})", filterClaus.Item1), filterClaus.Item2);
}
}
Func<Tuple<string, object[]>> filterCallback = () => new Tuple<string, object[]>(filterSql.SQL, filterSql.Arguments);
return GetPagedResultsByQuery<DocumentDto>(query, pageIndex, pageSize, out totalRecords,
@@ -957,7 +960,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
/// </param>
/// <param name="withCache"></param>
/// <param name="includeAllVersions">
/// Generally when querying for content we only want to return the most recent version of the content item, however in some cases like when
/// Generally when querying for content we only want to return the most recent version of the content item, however in some cases like when
/// we want to return all versions of a content item, we can't simply return the latest
/// </param>
/// <returns></returns>
@@ -966,7 +969,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
// fetch returns a list so it's ok to iterate it in this method
var dtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(sqlFull);
if (dtos.Count == 0) return Enumerable.Empty<IContent>();
//Go and get all of the published version data separately for this data, this is because when we are querying
//for multiple content items we don't include the outer join to fetch this data in the same query because
//it is insanely slow. Instead we just fetch the published version data separately in one query.
@@ -978,7 +981,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
if (parsedOriginalSql.InvariantContains("ORDER BY "))
{
parsedOriginalSql = parsedOriginalSql.Substring(0, parsedOriginalSql.LastIndexOf("ORDER BY ", StringComparison.Ordinal));
}
}
//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.updateDate, cmsDocument.newest
@@ -1004,12 +1007,12 @@ ORDER BY cmsContentVersion.id DESC
var content = new List<Tuple<IContent, bool>>();
var defs = new DocumentDefinitionCollection(includeAllVersions);
var templateIds = new List<int>();
//track the looked up content types, even though the content types are cached
// they still need to be deep cloned out of the cache and we don't want to add
// the overhead of deep cloning them on every item in this loop
var contentTypes = new Dictionary<int, IContentType>();
foreach (var dto in dtos)
{
DocumentPublishedReadOnlyDto publishedDto;
@@ -1119,33 +1122,12 @@ ORDER BY cmsContentVersion.id DESC
if (EnsureUniqueNaming == false)
return nodeName;
var sql = new Sql();
sql.Select("*")
.From<NodeDto>()
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId && x.ParentId == parentId && x.Text.StartsWith(nodeName));
var names = Database.Fetch<SimilarNodeName>("SELECT id, text AS name FROM umbracoNode WHERE nodeObjectType=@objectType AND parentId=@parentId",
new { objectType = NodeObjectTypeId, parentId });
int uniqueNumber = 1;
var currentName = nodeName;
var dtos = Database.Fetch<NodeDto>(sql);
if (dtos.Any())
{
var results = dtos.OrderBy(x => x.Text, new SimilarNodeNameComparer());
foreach (var dto in results)
{
if (id != 0 && id == dto.NodeId) continue;
if (dto.Text.ToLowerInvariant().Equals(currentName.ToLowerInvariant()))
{
currentName = nodeName + string.Format(" ({0})", uniqueNumber);
uniqueNumber++;
}
}
}
return currentName;
return SimilarNodeName.GetUniqueName(names, id, nodeName);
}
/// <summary>
/// Dispose disposable properties
/// </summary>
@@ -450,33 +450,10 @@ AND umbracoNode.id <> @id",
private string EnsureUniqueNodeName(string nodeName, int id = 0)
{
var names = Database.Fetch<SimilarNodeName>("SELECT id, text AS name FROM umbracoNode WHERE nodeObjectType=@objectType",
new { objectType = NodeObjectTypeId });
var sql = new Sql();
sql.Select("*")
.From<NodeDto>(SqlSyntax)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId && x.Text.StartsWith(nodeName));
int uniqueNumber = 1;
var currentName = nodeName;
var dtos = Database.Fetch<NodeDto>(sql);
if (dtos.Any())
{
var results = dtos.OrderBy(x => x.Text, new SimilarNodeNameComparer());
foreach (var dto in results)
{
if (id != 0 && id == dto.NodeId) continue;
if (dto.Text.ToLowerInvariant().Equals(currentName.ToLowerInvariant()))
{
currentName = nodeName + string.Format(" ({0})", uniqueNumber);
uniqueNumber++;
}
}
}
return currentName;
return SimilarNodeName.GetUniqueName(names, id, nodeName);
}
/// <summary>
@@ -260,6 +260,19 @@ namespace Umbraco.Core.Persistence.Repositories
return GetByQuery(query);
}
public Dictionary<string, Guid> GetDictionaryItemKeyMap()
{
var columns = new[] { "key", "id" }.Select(x => (object) SqlSyntax.GetQuotedColumnName(x)).ToArray();
var sql = new Sql().Select(columns).From<DictionaryDto>(SqlSyntax);
return Database.Fetch<DictionaryItemKeyIdDto>(sql).ToDictionary(x => x.Key, x => x.Id);
}
private class DictionaryItemKeyIdDto
{
public string Key { get; set; }
public Guid Id { get; set; }
}
public IEnumerable<IDictionaryItem> GetDictionaryItemDescendants(Guid? parentId)
{
//This methods will look up children at each level, since we do not store a path for dictionary (ATM), we need to do a recursive
@@ -9,5 +9,6 @@ namespace Umbraco.Core.Persistence.Repositories
IDictionaryItem Get(Guid uniqueId);
IDictionaryItem Get(string key);
IEnumerable<IDictionaryItem> GetDictionaryItemDescendants(Guid? parentId);
Dictionary<string, Guid> GetDictionaryItemKeyMap();
}
}
@@ -0,0 +1,13 @@
using System.IO;
using Umbraco.Core.Models;
namespace Umbraco.Core.Persistence.Repositories
{
public interface IUserControlRepository : IRepository<string, UserControl>
{
bool ValidateUserControl(UserControl userControl);
Stream GetFileContentStream(string filepath);
void SetFileContent(string filepath, Stream content);
long GetFileSize(string filepath);
}
}
@@ -0,0 +1,15 @@
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
{
internal class MacroScriptRepository : PartialViewRepository
{
public MacroScriptRepository(IUnitOfWork work, IFileSystem fileSystem)
: base(work, fileSystem)
{ }
protected override PartialViewType ViewType { get { return PartialViewType.MacroScript; } }
}
}
@@ -584,31 +584,10 @@ namespace Umbraco.Core.Persistence.Repositories
if (EnsureUniqueNaming == false)
return nodeName;
var sql = new Sql();
sql.Select("*")
.From<NodeDto>()
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId && x.ParentId == parentId && x.Text.StartsWith(nodeName));
var names = Database.Fetch<SimilarNodeName>("SELECT id, text AS name FROM umbracoNode WHERE nodeObjectType=@objectType AND parentId=@parentId",
new { objectType = NodeObjectTypeId, parentId });
int uniqueNumber = 1;
var currentName = nodeName;
var dtos = Database.Fetch<NodeDto>(sql);
if (dtos.Any())
{
var results = dtos.OrderBy(x => x.Text, new SimilarNodeNameComparer());
foreach (var dto in results)
{
if (id != 0 && id == dto.NodeId) continue;
if (dto.Text.ToLowerInvariant().Equals(currentName.ToLowerInvariant()))
{
currentName = nodeName + string.Format(" ({0})", uniqueNumber);
uniqueNumber++;
}
}
}
return currentName;
return SimilarNodeName.GetUniqueName(names, id, nodeName);
}
/// <summary>
@@ -184,30 +184,16 @@ namespace Umbraco.Core.Persistence.Repositories
public IEnumerable<IMemberGroup> GetMemberGroupsForMember(string username)
{
//find the member by username
var memberSql = new Sql();
var memberObjectType = new Guid(Constants.ObjectTypes.Member);
var sql = new Sql()
.Select("un.*")
.From("umbracoNode AS un")
.InnerJoin("cmsMember2MemberGroup")
.On("un.id = cmsMember2MemberGroup.MemberGroup")
.LeftJoin("(SELECT umbracoNode.id, cmsMember.LoginName FROM umbracoNode INNER JOIN cmsMember ON umbracoNode.id = cmsMember.nodeId) AS member")
.On("member.id = cmsMember2MemberGroup.Member")
.Where("un.nodeObjectType=@objectType", new {objectType = NodeObjectTypeId })
.Where("member.LoginName=@loginName", new {loginName = username});
memberSql.Select("umbracoNode.id")
.From<NodeDto>()
.InnerJoin<MemberDto>()
.On<NodeDto, MemberDto>(dto => dto.NodeId, dto => dto.NodeId)
.Where<NodeDto>(x => x.NodeObjectType == memberObjectType)
.Where<MemberDto>(x => x.LoginName == username);
var memberIdUsername = Database.Fetch<int?>(memberSql).FirstOrDefault();
if (memberIdUsername.HasValue == false)
{
return Enumerable.Empty<IMemberGroup>();
}
var sql = new Sql();
sql.Select("umbracoNode.*")
.From<NodeDto>()
.InnerJoin<Member2MemberGroupDto>()
.On<NodeDto, Member2MemberGroupDto>(dto => dto.NodeId, dto => dto.MemberGroup)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
.Where<Member2MemberGroupDto>(x => x.Member == memberIdUsername.Value);
return Database.Fetch<NodeDto>(sql)
.DistinctBy(dto => dto.NodeId)
.Select(x => _modelFactory.BuildEntity(x));
@@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.AspNet.Identity;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;
@@ -230,7 +231,19 @@ namespace Umbraco.Core.Persistence.Repositories
Database.Insert(dto.ContentVersionDto);
//Create the first entry in cmsMember
dto.NodeId = nodeDto.NodeId;
dto.NodeId = nodeDto.NodeId;
//if the password is empty, generate one with the special prefix
//this will hash the guid with a salt so should be nicely random
if (entity.RawPasswordValue.IsNullOrWhiteSpace())
{
var aspHasher = new PasswordHasher();
dto.Password = Constants.Security.EmptyPasswordPrefix +
aspHasher.HashPassword(Guid.NewGuid().ToString("N"));
//re-assign
entity.RawPasswordValue = dto.Password;
}
Database.Insert(dto);
//Create the PropertyData for this version - cmsPropertyData
@@ -42,6 +42,7 @@ namespace Umbraco.Core.Persistence.Repositories
//Construct and execute delete statements for all trashed items by 'nodeObjectType'
var deletes = new List<string>
{
FormatDeleteStatement("cmsTask", "nodeId"),
FormatDeleteStatement("umbracoUser2NodeNotify", "nodeId"),
FormatDeleteStatement("umbracoUser2NodePermission", "nodeId"),
@"DELETE FROM umbracoAccessRule WHERE umbracoAccessRule.accessId IN (
@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Persistence.Repositories
{
internal class SimilarNodeName
{
private int _numPos = -2;
public int Id { get; set; }
public string Name { get; set; }
// cached - reused
public int NumPos
{
get
{
if (_numPos != -2) return _numPos;
var name = Name;
if (name[name.Length - 1] != ')')
return _numPos = -1;
var pos = name.LastIndexOf('(');
if (pos < 2 || pos == name.Length - 2) // < 2 and not < 0, because we want at least "x ("
return _numPos = -1;
return _numPos = pos;
}
}
// not cached - used only once
public int NumVal
{
get
{
if (NumPos < 0)
throw new InvalidOperationException();
int num;
if (int.TryParse(Name.Substring(NumPos + 1, Name.Length - 2 - NumPos), out num))
return num;
return 0;
}
}
// compare without allocating, nor parsing integers
internal class Comparer : IComparer<SimilarNodeName>
{
public int Compare(SimilarNodeName x, SimilarNodeName y)
{
if (x == null) throw new ArgumentNullException("x");
if (y == null) throw new ArgumentNullException("y");
var xpos = x.NumPos;
var ypos = y.NumPos;
var xname = x.Name;
var yname = y.Name;
if (xpos < 0 || ypos < 0 || xpos != ypos)
return string.Compare(xname, yname, StringComparison.Ordinal);
// compare the part before (number)
var n = string.Compare(xname, 0, yname, 0, xpos, StringComparison.Ordinal);
if (n != 0)
return n;
// compare (number) lengths
var diff = xname.Length - yname.Length;
if (diff != 0) return diff < 0 ? -1 : +1;
// actually compare (number)
var i = xpos;
while (i < xname.Length - 1)
{
if (xname[i] != yname[i])
return xname[i] < yname[i] ? -1 : +1;
i++;
}
return 0;
}
}
// gets a unique name
public static string GetUniqueName(IEnumerable<SimilarNodeName> names, int nodeId, string nodeName)
{
var uniqueNumber = 1;
var uniqueing = false;
foreach (var name in names.OrderBy(x => x, new Comparer()))
{
// ignore self
if (nodeId != 0 && name.Id == nodeId) continue;
if (uniqueing)
{
if (name.NumPos > 0 && name.Name.StartsWith(nodeName) && name.NumVal == uniqueNumber)
uniqueNumber++;
else
break;
}
else if (name.Name.InvariantEquals(nodeName))
{
uniqueing = true;
}
}
return uniqueing ? string.Concat(nodeName, " (", uniqueNumber.ToString(), ")") : nodeName;
}
}
}
@@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Persistence.Repositories
{
/// <summary>
/// Comparer that takes into account the duplicate index of a node name
/// This is needed as a normal alphabetic sort would go Page (1), Page (10), Page (2) etc.
/// </summary>
internal class SimilarNodeNameComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (x.LastIndexOf('(') != -1 && x.LastIndexOf(')') == x.Length - 1 && y.LastIndexOf(')') == y.Length - 1)
{
if (x.ToLower().Substring(0, x.LastIndexOf('(')) == y.ToLower().Substring(0, y.LastIndexOf('(')))
{
int xDuplicateIndex = ExtractDuplicateIndex(x);
int yDuplicateIndex = ExtractDuplicateIndex(y);
if (xDuplicateIndex != 0 && yDuplicateIndex != 0)
{
return xDuplicateIndex.CompareTo(yDuplicateIndex);
}
}
}
return String.Compare(x.ToLower(), y.ToLower(), StringComparison.Ordinal);
}
private int ExtractDuplicateIndex(string text)
{
int index = 0;
if (text.LastIndexOf('(') != -1 && text.LastIndexOf('(') < text.Length - 2)
{
int startPos = text.LastIndexOf('(') + 1;
int length = text.Length - 1 - startPos;
int.TryParse(text.Substring(startPos, length), out index);
}
return index;
}
}
}
@@ -0,0 +1,135 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
{
/// <summary>
/// Represents the UserControl Repository
/// </summary>
internal class UserControlRepository : FileRepository<string, UserControl>, IUserControlRepository
{
public UserControlRepository(IUnitOfWork work, IFileSystem fileSystem)
: base(work, fileSystem)
{
}
public override UserControl Get(string id)
{
var path = FileSystem.GetRelativePath(id);
path = path.EnsureEndsWith(".ascx");
if (FileSystem.FileExists(path) == false)
return null;
var created = FileSystem.GetCreated(path).UtcDateTime;
var updated = FileSystem.GetLastModified(path).UtcDateTime;
var userControl = new UserControl(path, file => GetFileContent(file.OriginalPath))
{
Key = path.EncodeAsGuid(),
CreateDate = created,
UpdateDate = updated,
Id = path.GetHashCode(),
VirtualPath = FileSystem.GetUrl(path)
};
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
userControl.ResetDirtyProperties(false);
return userControl;
}
public override void AddOrUpdate(UserControl entity)
{
base.AddOrUpdate(entity);
// ensure that from now on, content is lazy-loaded
if (entity.GetFileContent == null)
entity.GetFileContent = file => GetFileContent(file.OriginalPath);
}
public override IEnumerable<UserControl> GetAll(params string[] ids)
{
ids = ids
.Select(x => StringExtensions.EnsureEndsWith(x, ".ascx"))
.Distinct()
.ToArray();
if (ids.Any())
{
foreach (var id in ids)
{
yield return Get(id);
}
}
else
{
var files = FindAllFiles("", "*.ascx");
foreach (var file in files)
{
yield return Get(file);
}
}
}
/// <summary>
/// Gets a list of all <see cref="UserControl"/> that exist at the relative path specified.
/// </summary>
/// <param name="rootPath">
/// If null or not specified, will return the UserControl files at the root path relative to the IFileSystem
/// </param>
/// <returns></returns>
public IEnumerable<UserControl> GetUserControlsAtPath(string rootPath = null)
{
return FileSystem.GetFiles(rootPath ?? string.Empty, "*.ascx").Select(Get);
}
private static readonly List<string> ValidExtensions = new List<string> { "ascx" };
public bool ValidateUserControl(UserControl userControl)
{
// get full path
string fullPath;
try
{
// may throw for security reasons
fullPath = FileSystem.GetFullPath(userControl.Path);
}
catch
{
return false;
}
// validate path and extension
var validDir = SystemDirectories.UserControls;
var isValidPath = IOHelper.VerifyEditPath(fullPath, validDir);
var isValidExtension = IOHelper.VerifyFileExtension(userControl.Path, ValidExtensions);
return isValidPath && isValidExtension;
}
public Stream GetFileContentStream(string filepath)
{
if (FileSystem.FileExists(filepath) == false) return null;
try
{
return FileSystem.OpenFile(filepath);
}
catch
{
return null; // deal with race conds
}
}
public void SetFileContent(string filepath, Stream content)
{
FileSystem.AddFile(filepath, content, true);
}
}
}
@@ -231,6 +231,18 @@ namespace Umbraco.Core.Persistence
return new PartialViewMacroRepository(uow, FileSystemProviderManager.Current.MacroPartialsFileSystem);
}
[Obsolete("MacroScripts are obsolete - this is for backwards compatibility with upgraded sites.")]
internal virtual IPartialViewRepository CreateMacroScriptRepository(IUnitOfWork uow)
{
return new MacroScriptRepository(uow, FileSystemProviderManager.Current.MacroScriptsFileSystem);
}
[Obsolete("UserControls are obsolete - this is for backwards compatibility with upgraded sites.")]
internal virtual IUserControlRepository CreateUserControlRepository(IUnitOfWork uow)
{
return new UserControlRepository(uow, FileSystemProviderManager.Current.UserControlsFileSystem);
}
public virtual IStylesheetRepository CreateStylesheetRepository(IUnitOfWork uow)
{
return new StylesheetRepository(uow, FileSystemProviderManager.Current.StylesheetsFileSystem);
+78 -67
View File
@@ -44,8 +44,8 @@ namespace Umbraco.Core
private readonly object _typesLock = new object();
private readonly Dictionary<TypeListKey, TypeList> _types = new Dictionary<TypeListKey, TypeList>();
private long _cachedAssembliesHash = -1;
private long _currentAssembliesHash = -1;
private string _cachedAssembliesHash = null;
private string _currentAssembliesHash = null;
private IEnumerable<Assembly> _assemblies;
private bool _reportedChange;
@@ -75,9 +75,9 @@ namespace Umbraco.Core
if (detectChanges)
{
//first check if the cached hash is 0, if it is then we ne
//first check if the cached hash is string.Empty, if it is then we need
//do the check if they've changed
RequiresRescanning = (CachedAssembliesHash != CurrentAssembliesHash) || CachedAssembliesHash == 0;
RequiresRescanning = (CachedAssembliesHash != CurrentAssembliesHash) || CachedAssembliesHash == string.Empty;
//if they have changed, we need to write the new file
if (RequiresRescanning)
{
@@ -180,23 +180,20 @@ namespace Umbraco.Core
/// <summary>
/// Gets the currently cached hash value of the scanned assemblies.
/// </summary>
/// <value>The cached hash value, or 0 if no cache is found.</value>
internal long CachedAssembliesHash
/// <value>The cached hash value, or string.Empty if no cache is found.</value>
internal string CachedAssembliesHash
{
get
{
if (_cachedAssembliesHash != -1)
if (_cachedAssembliesHash != null)
return _cachedAssembliesHash;
var filePath = GetPluginHashFilePath();
if (File.Exists(filePath) == false) return 0;
if (File.Exists(filePath) == false) return string.Empty;
var hash = File.ReadAllText(filePath, Encoding.UTF8);
long val;
if (long.TryParse(hash, out val) == false) return 0;
_cachedAssembliesHash = val;
_cachedAssembliesHash = hash;
return _cachedAssembliesHash;
}
}
@@ -205,11 +202,11 @@ namespace Umbraco.Core
/// Gets the current assemblies hash based on creating a hash from the assemblies in various places.
/// </summary>
/// <value>The current hash.</value>
internal long CurrentAssembliesHash
internal string CurrentAssembliesHash
{
get
{
if (_currentAssembliesHash != -1)
if (_currentAssembliesHash != null)
return _currentAssembliesHash;
_currentAssembliesHash = GetFileHash(new List<Tuple<FileSystemInfo, bool>>
@@ -245,41 +242,40 @@ namespace Umbraco.Core
/// <returns>The hash.</returns>
/// <remarks>Each file is a tuple containing the FileInfo object and a boolean which indicates whether to hash the
/// file properties (false) or the file contents (true).</remarks>
internal static long GetFileHash(IEnumerable<Tuple<FileSystemInfo, bool>> filesAndFolders, ProfilingLogger logger)
internal static string GetFileHash(IEnumerable<Tuple<FileSystemInfo, bool>> filesAndFolders, ProfilingLogger logger)
{
using (logger.TraceDuration<PluginManager>("Determining hash of code files on disk", "Hash determined"))
{
var hashCombiner = new HashCodeCombiner();
{
// get the distinct file infos to hash
var uniqInfos = new HashSet<string>();
var uniqContent = new HashSet<string>();
foreach (var fileOrFolder in filesAndFolders)
using (var generator = new HashGenerator())
{
var info = fileOrFolder.Item1;
if (fileOrFolder.Item2)
foreach (var fileOrFolder in filesAndFolders)
{
// add each unique file's contents to the hash
// normalize the content for cr/lf and case-sensitivity
if (uniqContent.Contains(info.FullName)) continue;
uniqContent.Add(info.FullName);
if (File.Exists(info.FullName) == false) continue;
var content = RemoveCrLf(File.ReadAllText(info.FullName));
hashCombiner.AddCaseInsensitiveString(content);
var info = fileOrFolder.Item1;
if (fileOrFolder.Item2)
{
// add each unique file's contents to the hash
// normalize the content for cr/lf and case-sensitivity
if (uniqContent.Add(info.FullName))
{
if (File.Exists(info.FullName) == false) continue;
var content = RemoveCrLf(File.ReadAllText(info.FullName));
generator.AddCaseInsensitiveString(content);
}
}
else
{
// add each unique folder/file to the hash
if (uniqInfos.Add(info.FullName))
{
generator.AddFileSystemItem(info);
}
}
}
else
{
// add each unique folder/file to the hash
if (uniqInfos.Contains(info.FullName)) continue;
uniqInfos.Add(info.FullName);
hashCombiner.AddFileSystemItem(info);
}
}
return ConvertHashToInt64(hashCombiner.GetCombinedHashCode());
return generator.GenerateHash();
}
}
}
@@ -303,39 +299,33 @@ namespace Umbraco.Core
/// <param name="filesAndFolders">A collection of files.</param>
/// <param name="logger">A profiling logger.</param>
/// <returns>The hash.</returns>
internal static long GetFileHash(IEnumerable<FileSystemInfo> filesAndFolders, ProfilingLogger logger)
internal static string GetFileHash(IEnumerable<FileSystemInfo> filesAndFolders, ProfilingLogger logger)
{
using (logger.TraceDuration<PluginManager>("Determining hash of code files on disk", "Hash determined"))
{
var hashCombiner = new HashCodeCombiner();
// get the distinct file infos to hash
var uniqInfos = new HashSet<string>();
foreach (var fileOrFolder in filesAndFolders)
using (var generator = new HashGenerator())
{
if (uniqInfos.Contains(fileOrFolder.FullName)) continue;
uniqInfos.Add(fileOrFolder.FullName);
hashCombiner.AddFileSystemItem(fileOrFolder);
}
// get the distinct file infos to hash
var uniqInfos = new HashSet<string>();
return ConvertHashToInt64(hashCombiner.GetCombinedHashCode());
foreach (var fileOrFolder in filesAndFolders)
{
if (uniqInfos.Contains(fileOrFolder.FullName)) continue;
uniqInfos.Add(fileOrFolder.FullName);
generator.AddFileSystemItem(fileOrFolder);
}
return generator.GenerateHash();
}
}
}
/// <summary>
/// Converts a string hash value into an Int64.
/// </summary>
internal static long ConvertHashToInt64(string val)
{
long outVal;
return long.TryParse(val, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out outVal) ? outVal : 0;
}
}
#endregion
#region Cache
private const int ListFileOpenReadTimeout = 4000; // milliseconds
private const int ListFileOpenWriteTimeout = 2000; // milliseconds
/// <summary>
/// Attemps to retrieve the list of types from the cache.
/// </summary>
@@ -381,7 +371,7 @@ namespace Umbraco.Core
if (File.Exists(filePath) == false)
return cache;
using (var stream = File.OpenRead(filePath))
using (var stream = GetFileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, ListFileOpenReadTimeout))
using (var reader = new StreamReader(stream))
{
while (true)
@@ -451,7 +441,7 @@ namespace Umbraco.Core
{
var filePath = GetPluginListFilePath();
using (var stream = File.Open(filePath, FileMode.Create, FileAccess.ReadWrite))
using (var stream = GetFileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, ListFileOpenWriteTimeout))
using (var writer = new StreamWriter(stream))
{
foreach (var typeList in _types.Values)
@@ -471,7 +461,28 @@ namespace Umbraco.Core
// at the moment we write the cache to disk every time we update it. ideally we defer the writing
// since all the updates are going to happen in a row when Umbraco starts. that being said, the
// file is small enough, so it is not a priority.
WriteCache();
WriteCache();
}
private static Stream GetFileStream(string path, FileMode fileMode, FileAccess fileAccess, FileShare fileShare, int timeoutMilliseconds)
{
const int pauseMilliseconds = 250;
var attempts = timeoutMilliseconds / pauseMilliseconds;
while (true)
{
try
{
return new FileStream(path, fileMode, fileAccess, fileShare);
}
catch
{
if (--attempts == 0)
throw;
LogHelper.Debug<PluginManager>(string.Format("Attempted to get filestream for file {0} failed, {1} attempts left, pausing for {2} milliseconds", path, attempts, pauseMilliseconds));
Thread.Sleep(pauseMilliseconds);
}
}
}
#endregion
+5 -2
View File
@@ -39,7 +39,6 @@ using System.Security.Permissions;
[assembly: InternalsVisibleTo("UmbracoExamine")]
[assembly: InternalsVisibleTo("Concorde.Sync")]
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")]
[assembly: InternalsVisibleTo("Umbraco.Courier.Core")]
[assembly: InternalsVisibleTo("Umbraco.Courier.Persistence")]
@@ -52,4 +51,8 @@ using System.Security.Permissions;
[assembly: InternalsVisibleTo("Umbraco.Forms.Web")]
//allow this to be mocked in our unit tests
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
//allow custom unit-testing code to access internals through custom adapters
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")] // backwards compat.
[assembly: InternalsVisibleTo("Umbraco.UnitTesting.Adapter")] // new, more imperative name
@@ -26,7 +26,7 @@ namespace Umbraco.Core.PropertyEditors
public PropertyEditorAttribute(string alias, string name)
{
Mandate.ParameterNotNullOrEmpty(alias, "id");
Mandate.ParameterNotNullOrEmpty(alias, "alias");
Mandate.ParameterNotNullOrEmpty(name, "name");
Alias = alias;
@@ -82,4 +82,4 @@ namespace Umbraco.Core.PropertyEditors
/// </summary>
public string Group { get; set; }
}
}
}
@@ -293,7 +293,7 @@ namespace Umbraco.Core.PropertyEditors
//swallow this exception, we thought it was json but it really isn't so continue returning a string
}
}
return property.Value.ToString();
return asString;
case DataTypeDatabaseType.Integer:
case DataTypeDatabaseType.Decimal:
//Decimals need to be formatted with invariant culture (dots, not commas)
@@ -22,7 +22,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
if (sourceString != null)
{
decimal d;
return (decimal.TryParse(sourceString, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out d)) ? d : 0M;
return (decimal.TryParse(sourceString, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out d)) ? d : 0M;
}
// in the database an a decimal is an a decimal
@@ -93,7 +93,7 @@ namespace Umbraco.Core.Security
{
//this will hash the guid with a salt so should be nicely random
var aspHasher = new PasswordHasher();
member.RawPasswordValue = "___UIDEMPTYPWORD__" +
member.RawPasswordValue = Constants.Security.EmptyPasswordPrefix +
aspHasher.HashPassword(Guid.NewGuid().ToString("N"));
}
@@ -494,7 +494,7 @@ namespace Umbraco.Core.Security
//the stamp cannot be null, so if it is currently null then we'll just return a hash of the password
return Task.FromResult(user.SecurityStamp.IsNullOrWhiteSpace()
? user.PasswordHash.ToMd5()
? user.PasswordHash.GenerateHash()
: user.SecurityStamp);
}
@@ -64,6 +64,19 @@ namespace Umbraco.Core.Security
{
get { return false; }
}
/// <summary>
/// Returns the raw password value for a given user
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
/// <remarks>
/// By default this will return an invalid attempt, inheritors will need to override this to support it
/// </remarks>
protected virtual Attempt<string> GetRawPassword(string username)
{
return Attempt<string>.Fail();
}
private string _applicationName;
private bool _enablePasswordReset;
@@ -299,7 +312,7 @@ namespace Umbraco.Core.Security
/// Processes a request to update the password for a membership user.
/// </summary>
/// <param name="username">The user to update the password for.</param>
/// <param name="oldPassword">This property is ignore for this provider</param>
/// <param name="oldPassword">Required to change a user password if the user is not new and AllowManuallyChangingPassword is false</param>
/// <param name="newPassword">The new password for the specified user.</param>
/// <returns>
/// true if the password was updated successfully; otherwise, false.
@@ -309,10 +322,17 @@ namespace Umbraco.Core.Security
/// </remarks>
public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
string rawPasswordValue = string.Empty;
if (oldPassword.IsNullOrWhiteSpace() && AllowManuallyChangingPassword == false)
{
//If the old password is empty and AllowManuallyChangingPassword is false, than this provider cannot just arbitrarily change the password
throw new NotSupportedException("This provider does not support manually changing the password");
{
//we need to lookup the member since this could be a brand new member without a password set
var rawPassword = GetRawPassword(username);
rawPasswordValue = rawPassword.Success ? rawPassword.Result : string.Empty;
if (rawPassword.Success == false || rawPasswordValue.StartsWith(Constants.Security.EmptyPasswordPrefix) == false)
{
//If the old password is empty and AllowManuallyChangingPassword is false, than this provider cannot just arbitrarily change the password
throw new NotSupportedException("This provider does not support manually changing the password");
}
}
var args = new ValidatePasswordEventArgs(username, newPassword, false);
@@ -325,10 +345,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")
//Special cases to allow changing password without validating existing credentials
// * the member is new and doesn't have a password set
// * during installation to set the admin password
if (AllowManuallyChangingPassword == false
&& (rawPasswordValue.StartsWith(Constants.Security.EmptyPasswordPrefix)
|| (ApplicationContext.Current != null
&& ApplicationContext.Current.IsConfigured == false
&& oldPassword == "default")))
{
return PerformChangePassword(username, oldPassword, newPassword);
}
+98 -55
View File
@@ -32,6 +32,7 @@ namespace Umbraco.Core.Services
private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer();
private readonly IDataTypeService _dataTypeService;
private readonly IUserService _userService;
private readonly IdkMap _idkMap;
//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.
@@ -43,7 +44,8 @@ namespace Umbraco.Core.Services
ILogger logger,
IEventMessagesFactory eventMessagesFactory,
IDataTypeService dataTypeService,
IUserService userService)
IUserService userService,
IdkMap idkMap)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
@@ -51,6 +53,7 @@ namespace Umbraco.Core.Services
_publishingStrategy = new PublishingStrategy(UowProvider.ScopeProvider, eventMessagesFactory, logger);
_dataTypeService = dataTypeService;
_userService = userService;
_idkMap = idkMap;
}
#region Static Queries
@@ -163,7 +166,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Creating, this, new NewEventArgs<IContent>(content, contentTypeAlias, parentId)))
var newEventArgs = new NewEventArgs<IContent>(content, contentTypeAlias, parentId);
if (uow.Events.DispatchCancelable(Creating, this, newEventArgs))
{
uow.Commit();
content.WasCancelled = true;
@@ -172,8 +176,8 @@ namespace Umbraco.Core.Services
content.CreatorId = userId;
content.WriterId = userId;
uow.Events.Dispatch(Created, this, new NewEventArgs<IContent>(content, false, contentTypeAlias, parentId));
newEventArgs.CanCancel = false;
uow.Events.Dispatch(Created, this, newEventArgs);
Audit(uow, AuditType.New, string.Format("Content '{0}' was created", name), content.CreatorId, content.Id);
uow.Commit();
@@ -206,7 +210,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Creating, this, new NewEventArgs<IContent>(content, contentTypeAlias, parent)))
var newEventArgs = new NewEventArgs<IContent>(content, contentTypeAlias, parent);
if (uow.Events.DispatchCancelable(Creating, this, newEventArgs))
{
uow.Commit();
content.WasCancelled = true;
@@ -215,8 +220,8 @@ namespace Umbraco.Core.Services
content.CreatorId = userId;
content.WriterId = userId;
uow.Events.Dispatch(Created, this, new NewEventArgs<IContent>(content, false, contentTypeAlias, parent));
newEventArgs.CanCancel = false;
uow.Events.Dispatch(Created, this, newEventArgs);
Audit(uow, AuditType.New, string.Format("Content '{0}' was created", name), content.CreatorId, content.Id);
uow.Commit();
@@ -247,14 +252,16 @@ namespace Umbraco.Core.Services
{
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
// 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<IContent>(content, contentTypeAlias, parentId)))
var newEventArgs = new NewEventArgs<IContent>(content, contentTypeAlias, parentId);
if (uow.Events.DispatchCancelable(Creating, this, newEventArgs))
{
uow.Commit();
content.WasCancelled = true;
return content;
}
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content)))
var saveEventArgs = new SaveEventArgs<IContent>(content);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
content.WasCancelled = true;
@@ -267,9 +274,10 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(content);
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false));
uow.Events.Dispatch(Created, this, new NewEventArgs<IContent>(content, false, contentTypeAlias, parentId));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
newEventArgs.CanCancel = false;
uow.Events.Dispatch(Created, this, newEventArgs);
Audit(uow, AuditType.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id);
uow.Commit();
@@ -302,14 +310,16 @@ namespace Umbraco.Core.Services
{
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
// 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<IContent>(content, contentTypeAlias, parent)))
var newEventArgs = new NewEventArgs<IContent>(content, contentTypeAlias, parent);
if (uow.Events.DispatchCancelable(Creating, this, newEventArgs))
{
uow.Commit();
content.WasCancelled = true;
return content;
}
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content)))
var saveEventArgs = new SaveEventArgs<IContent>(content);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
content.WasCancelled = true;
@@ -322,9 +332,10 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(content);
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false));
uow.Events.Dispatch(Created, this, new NewEventArgs<IContent>(content, false, contentTypeAlias, parent));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
newEventArgs.CanCancel = false;
uow.Events.Dispatch(Created, this, newEventArgs);
Audit(uow, AuditType.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id);
uow.Commit();
@@ -382,13 +393,13 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IContent"/></returns>
public IContent GetById(Guid key)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentRepository(uow);
var query = Query<IContent>.Builder.Where(x => x.Key == key);
var contents = repository.GetByQuery(query);
return contents.SingleOrDefault();
}
// the repository implements a cache policy on int identifiers, not guids,
// and we are not changing it now, but we still would like to rely on caching
// instead of running a full query against the database, so relying on the
// id-key map, which is fast.
var a = _idkMap.GetIdForKey(key, UmbracoObjectTypes.Document);
return a.Success ? GetById(a.Result) : null;
}
/// <summary>
@@ -1015,14 +1026,16 @@ namespace Umbraco.Core.Services
//see: http://issues.umbraco.org/issue/U4-9336
content.EnsureValidPath(Logger, entity => GetById(entity.ParentId), QuickUpdate);
var originalPath = content.Path;
if (uow.Events.DispatchCancelable(Trashing, this, new MoveEventArgs<IContent>(evtMsgs, new MoveEventInfo<IContent>(content, originalPath, Constants.System.RecycleBinContent)), "Trashing"))
var moveEventInfo = new MoveEventInfo<IContent>(content, originalPath, Constants.System.RecycleBinContent);
var moveEventArgs = new MoveEventArgs<IContent>(evtMsgs, moveEventInfo);
if (uow.Events.DispatchCancelable(Trashing, this, moveEventArgs, "Trashing"))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
var moveInfo = new List<MoveEventInfo<IContent>>
{
new MoveEventInfo<IContent>(content, originalPath, Constants.System.RecycleBinContent)
moveEventInfo
};
//get descendents to process of the content item that is being moved to trash - must be done before changing the state below
@@ -1049,11 +1062,13 @@ namespace Umbraco.Core.Services
descendant.WriterId = userId;
descendant.ChangeTrashedState(true, descendant.ParentId);
repository.AddOrUpdate(descendant);
moveInfo.Add(new MoveEventInfo<IContent>(descendant, descendant.Path, descendant.ParentId));
}
uow.Events.Dispatch(Trashed, this, new MoveEventArgs<IContent>(false, evtMsgs, moveInfo.ToArray()), "Trashed");
moveEventArgs.CanCancel = false;
moveEventArgs.MoveInfoCollection = moveInfo;
uow.Events.Dispatch(Trashed, this, moveEventArgs, "Trashed");
Audit(uow, AuditType.Move, "Move Content to Recycle Bin performed by user", userId, content.Id);
uow.Commit();
@@ -1180,7 +1195,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(asArray, evtMsgs)))
var saveEventArgs = new SaveEventArgs<IContent>(asArray, evtMsgs);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -1221,7 +1237,10 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(asArray, false, evtMsgs));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
Audit(uow, AuditType.Save, "Bulk Save content performed by user", userId == -1 ? 0 : userId, Constants.System.Root);
uow.Commit();
@@ -1247,7 +1266,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IContent>(content, evtMsgs), "Deleting"))
var deleteEventArgs = new DeleteEventArgs<IContent>(content, evtMsgs);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs, "Deleting"))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -1270,8 +1290,8 @@ namespace Umbraco.Core.Services
repository.Delete(content);
var args = new DeleteEventArgs<IContent>(content, false, evtMsgs);
uow.Events.Dispatch(Deleted, this, args, "Deleted");
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs, "Deleted");
Audit(uow, AuditType.Delete, "Delete Content performed by user", userId, content.Id);
uow.Commit();
@@ -1399,7 +1419,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingVersions, this, new DeleteRevisionsEventArgs(id, dateToRetain: versionDate), "DeletingVersions"))
var deleteRevisionsEventArgs = new DeleteRevisionsEventArgs(id, dateToRetain: versionDate);
if (uow.Events.DispatchCancelable(DeletingVersions, this, deleteRevisionsEventArgs, "DeletingVersions"))
{
uow.Commit();
return;
@@ -1407,8 +1428,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateContentRepository(uow);
repository.DeleteVersions(id, versionDate);
uow.Events.Dispatch(DeletedVersions, this, new DeleteRevisionsEventArgs(id, false, dateToRetain: versionDate), "DeletedVersions");
deleteRevisionsEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedVersions, this, deleteRevisionsEventArgs, "DeletedVersions");
Audit(uow, AuditType.Delete, "Delete Content by version date performed by user", userId, Constants.System.Root);
uow.Commit();
@@ -1487,7 +1508,9 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Moving, this, new MoveEventArgs<IContent>(new MoveEventInfo<IContent>(content, content.Path, parentId)), "Moving"))
var moveEventInfo = new MoveEventInfo<IContent>(content, content.Path, parentId);
var moveEventArgs = new MoveEventArgs<IContent>(moveEventInfo);
if (uow.Events.DispatchCancelable(Moving, this, moveEventArgs, "Moving"))
{
uow.Commit();
return;
@@ -1499,7 +1522,9 @@ namespace Umbraco.Core.Services
//call private method that does the recursive moving
PerformMove(content, parentId, userId, moveInfo);
uow.Events.Dispatch(Moved, this, new MoveEventArgs<IContent>(false, moveInfo.ToArray()), "Moved");
moveEventArgs.MoveInfoCollection = moveInfo;
moveEventArgs.CanCancel = false;
uow.Events.Dispatch(Moved, this, moveEventArgs, "Moved");
Audit(uow, AuditType.Move, "Move Content performed by user", userId, content.Id);
uow.Commit();
@@ -1528,15 +1553,17 @@ namespace Umbraco.Core.Services
var files = ((ContentRepository)repository).GetFilesInRecycleBinForUploadField();
if (uow.Events.DispatchCancelable(EmptyingRecycleBin, this, new RecycleBinEventArgs(nodeObjectType, entities, files)))
var recycleBinEventArgs = new RecycleBinEventArgs(nodeObjectType, entities, files);
if (uow.Events.DispatchCancelable(EmptyingRecycleBin, this, recycleBinEventArgs))
{
uow.Commit();
return;
}
var success = repository.EmptyRecycleBin();
uow.Events.Dispatch(EmptiedRecycleBin, this, new RecycleBinEventArgs(nodeObjectType, entities, files, success));
recycleBinEventArgs.CanCancel = false;
recycleBinEventArgs.RecycleBinEmptiedSuccessfully = success;
uow.Events.Dispatch(EmptiedRecycleBin, this, recycleBinEventArgs);
Audit(uow, AuditType.Delete, "Empty Content Recycle Bin performed by user", 0, Constants.System.RecycleBinContent);
uow.Commit();
@@ -1583,7 +1610,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Copying, this, new CopyEventArgs<IContent>(content, copy, parentId)))
var copyEventArgs = new CopyEventArgs<IContent>(content, copy, true, parentId, relateToOriginal);
if (uow.Events.DispatchCancelable(Copying, this, copyEventArgs))
{
uow.Commit();
return null;
@@ -1624,7 +1652,8 @@ namespace Umbraco.Core.Services
Copy(child, copy.Id, relateToOriginal, true, userId);
}
}
uow.Events.Dispatch(Copied, this, new CopyEventArgs<IContent>(content, copy, false, parentId, relateToOriginal));
copyEventArgs.CanCancel = false;
uow.Events.Dispatch(Copied, this, copyEventArgs);
Audit(uow, AuditType.Copy, "Copy Content performed by user", content.WriterId, content.Id);
uow.Commit();
}
@@ -1644,7 +1673,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SendingToPublish, this, new SendToPublishEventArgs<IContent>(content)))
var sendToPublishEventArgs = new SendToPublishEventArgs<IContent>(content);
if (uow.Events.DispatchCancelable(SendingToPublish, this, sendToPublishEventArgs))
{
uow.Commit();
return false;
@@ -1652,8 +1682,8 @@ namespace Umbraco.Core.Services
//Save before raising event
Save(content, userId);
uow.Events.Dispatch(SentToPublish, this, new SendToPublishEventArgs<IContent>(content, false));
sendToPublishEventArgs.CanCancel = false;
uow.Events.Dispatch(SentToPublish, this, sendToPublishEventArgs);
Audit(uow, AuditType.SendToPublish, "Send to Publish performed by user", content.WriterId, content.Id);
uow.Commit();
@@ -1680,7 +1710,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(RollingBack, this, new RollbackEventArgs<IContent>(content)))
var rollbackEventArgs = new RollbackEventArgs<IContent>(content);
if (uow.Events.DispatchCancelable(RollingBack, this, rollbackEventArgs))
{
uow.Commit();
return content;
@@ -1694,8 +1725,8 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(content);
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
uow.Events.Dispatch(RolledBack, this, new RollbackEventArgs<IContent>(content, false));
rollbackEventArgs.CanCancel = false;
uow.Events.Dispatch(RolledBack, this, rollbackEventArgs);
Audit(uow, AuditType.RollBack, "Content rollback performed by user", content.WriterId, content.Id);
uow.Commit();
@@ -1726,7 +1757,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
var asArray = items.ToArray();
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(asArray)))
var saveEventArgs = new SaveEventArgs<IContent>(asArray);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return false;
@@ -1771,7 +1803,10 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(asArray, false));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
if (shouldBePublished.Any())
{
@@ -2135,7 +2170,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content, evtMsgs)))
var saveEventArgs = new SaveEventArgs<IContent>(content, evtMsgs);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent, evtMsgs));
@@ -2190,7 +2226,10 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false, evtMsgs));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
//Save xml to db and call following method to fire event through PublishingStrategy to update cache
if (published)
@@ -2229,7 +2268,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content, evtMsgs)))
var saveEventArgs = new SaveEventArgs<IContent>(content, evtMsgs);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -2258,7 +2298,10 @@ namespace Umbraco.Core.Services
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false, evtMsgs));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
Audit(uow, AuditType.Save, "Save Content performed by user", userId, content.Id);
uow.Commit();
+64 -36
View File
@@ -54,7 +54,8 @@ namespace Umbraco.Core.Services
CreatorId = userId
};
if (uow.Events.DispatchCancelable(SavingContentTypeContainer, this, new SaveEventArgs<EntityContainer>(container, evtMsgs)))
var saveEventArgs = new SaveEventArgs<EntityContainer>(container, evtMsgs);
if (uow.Events.DispatchCancelable(SavingContentTypeContainer, this, saveEventArgs))
{
uow.Commit();
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.FailedCancelledByEvent, evtMsgs));
@@ -62,8 +63,8 @@ namespace Umbraco.Core.Services
repo.AddOrUpdate(container);
uow.Commit();
uow.Events.Dispatch(SavedContentTypeContainer, this, new SaveEventArgs<EntityContainer>(container, evtMsgs), "SavedContentTypeContainer");
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedContentTypeContainer, this, saveEventArgs, "SavedContentTypeContainer");
//TODO: Audit trail ?
return Attempt.Succeed(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.Success, evtMsgs));
@@ -92,7 +93,8 @@ namespace Umbraco.Core.Services
CreatorId = userId
};
if (uow.Events.DispatchCancelable(SavingMediaTypeContainer, this, new SaveEventArgs<EntityContainer>(container, evtMsgs)))
var saveEventArgs = new SaveEventArgs<EntityContainer>(container, evtMsgs);
if (uow.Events.DispatchCancelable(SavingMediaTypeContainer, this, saveEventArgs))
{
uow.Commit();
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.FailedCancelledByEvent, evtMsgs));
@@ -100,8 +102,8 @@ namespace Umbraco.Core.Services
repo.AddOrUpdate(container);
uow.Commit();
uow.Events.Dispatch(SavedMediaTypeContainer, this, new SaveEventArgs<EntityContainer>(container, evtMsgs), "SavedMediaTypeContainer");
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedMediaTypeContainer, this, saveEventArgs, "SavedMediaTypeContainer");
//TODO: Audit trail ?
return Attempt.Succeed(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.Success, evtMsgs));
@@ -289,7 +291,8 @@ namespace Umbraco.Core.Services
return OperationStatus.NoOperation(evtMsgs);
}
if (uow.Events.DispatchCancelable(DeletingContentTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs)))
var deleteEventArgs = new DeleteEventArgs<EntityContainer>(container, evtMsgs);
if (uow.Events.DispatchCancelable(DeletingContentTypeContainer, this, deleteEventArgs))
{
uow.Commit();
return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, evtMsgs));
@@ -297,8 +300,8 @@ namespace Umbraco.Core.Services
repo.Delete(container);
uow.Commit();
uow.Events.Dispatch(DeletedContentTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs), "DeletedContentTypeContainer");
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedContentTypeContainer, this, deleteEventArgs, "DeletedContentTypeContainer");
return OperationStatus.Success(evtMsgs);
//TODO: Audit trail ?
@@ -319,7 +322,8 @@ namespace Umbraco.Core.Services
return OperationStatus.NoOperation(evtMsgs);
}
if (uow.Events.DispatchCancelable(DeletingMediaTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs)))
var deleteEventArgs = new DeleteEventArgs<EntityContainer>(container, evtMsgs);
if (uow.Events.DispatchCancelable(DeletingMediaTypeContainer, this, deleteEventArgs))
{
uow.Commit();
return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, evtMsgs));
@@ -327,8 +331,8 @@ namespace Umbraco.Core.Services
repo.Delete(container);
uow.Commit();
uow.Events.Dispatch(DeletedMediaTypeContainer, this, new DeleteEventArgs<EntityContainer>(container, evtMsgs));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedMediaTypeContainer, this, deleteEventArgs);
return OperationStatus.Success(evtMsgs);
//TODO: Audit trail ?
@@ -756,7 +760,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingContentType, this, new SaveEventArgs<IContentType>(contentType)))
var saveEventArgs = new SaveEventArgs<IContentType>(contentType);
if (uow.Events.DispatchCancelable(SavingContentType, this, saveEventArgs))
{
uow.Commit();
return;
@@ -779,7 +784,8 @@ namespace Umbraco.Core.Services
UpdateContentXmlStructure(contentType);
uow.Events.Dispatch(SavedContentType, this, new SaveEventArgs<IContentType>(contentType, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedContentType, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save ContentType performed by user", userId, contentType.Id);
uow.Commit();
@@ -800,7 +806,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingContentType, this, new SaveEventArgs<IContentType>(asArray)))
var saveEventArgs = new SaveEventArgs<IContentType>(asArray);
if (uow.Events.DispatchCancelable(SavingContentType, this, saveEventArgs))
{
uow.Commit();
return;
@@ -825,7 +832,8 @@ namespace Umbraco.Core.Services
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray());
uow.Events.Dispatch(SavedContentType, this, new SaveEventArgs<IContentType>(asArray, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedContentType, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save ContentTypes performed by user", userId, -1);
uow.Commit();
@@ -845,7 +853,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingContentType, this, new DeleteEventArgs<IContentType>(contentType)))
var deleteEventArgs = new DeleteEventArgs<IContentType>(contentType);
if (uow.Events.DispatchCancelable(DeletingContentType, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -860,8 +869,9 @@ namespace Umbraco.Core.Services
_contentService.DeleteContentOfTypes(deletedContentTypes.Select(x => x.Id), userId);
repository.Delete(contentType);
uow.Events.Dispatch(DeletedContentType, this, new DeleteEventArgs<IContentType>(deletedContentTypes.DistinctBy(x => x.Id), false));
deleteEventArgs.DeletedEntities = deletedContentTypes.DistinctBy(x => x.Id);
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedContentType, this, deleteEventArgs);
Audit(uow, AuditType.Delete, string.Format("Delete ContentType performed by user"), userId, contentType.Id);
uow.Commit();
@@ -885,7 +895,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingContentType, this, new DeleteEventArgs<IContentType>(asArray)))
var deleteEventArgs = new DeleteEventArgs<IContentType>(asArray);
if (uow.Events.DispatchCancelable(DeletingContentType, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -906,8 +917,9 @@ namespace Umbraco.Core.Services
{
repository.Delete(contentType);
}
uow.Events.Dispatch(DeletedContentType, this, new DeleteEventArgs<IContentType>(deletedContentTypes.DistinctBy(x => x.Id), false));
deleteEventArgs.DeletedEntities = deletedContentTypes.DistinctBy(x => x.Id);
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedContentType, this, deleteEventArgs);
Audit(uow, AuditType.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1);
uow.Commit();
@@ -1056,7 +1068,9 @@ namespace Umbraco.Core.Services
var moveInfo = new List<MoveEventInfo<IMediaType>>();
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(MovingMediaType, this, new MoveEventArgs<IMediaType>(evtMsgs, new MoveEventInfo<IMediaType>(toMove, toMove.Path, containerId))))
var moveEventInfo = new MoveEventInfo<IMediaType>(toMove, toMove.Path, containerId);
var moveEventArgs = new MoveEventArgs<IMediaType>(evtMsgs, moveEventInfo);
if (uow.Events.DispatchCancelable(MovingMediaType, this, moveEventArgs))
{
uow.Commit();
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs));
@@ -1081,7 +1095,9 @@ namespace Umbraco.Core.Services
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(ex.Operation, evtMsgs));
}
uow.Commit();
uow.Events.Dispatch(MovedMediaType, this, new MoveEventArgs<IMediaType>(false, evtMsgs, moveInfo.ToArray()));
moveEventArgs.MoveInfoCollection = moveInfo;
moveEventArgs.CanCancel = false;
uow.Events.Dispatch(MovedMediaType, this, moveEventArgs);
}
return Attempt.Succeed(
@@ -1095,7 +1111,9 @@ namespace Umbraco.Core.Services
var moveInfo = new List<MoveEventInfo<IContentType>>();
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(MovingContentType, this, new MoveEventArgs<IContentType>(evtMsgs, new MoveEventInfo<IContentType>(toMove, toMove.Path, containerId))))
var moveEventInfo = new MoveEventInfo<IContentType>(toMove, toMove.Path, containerId);
var moveEventArgs = new MoveEventArgs<IContentType>(evtMsgs, moveEventInfo);
if (uow.Events.DispatchCancelable(MovingContentType, this, moveEventArgs))
{
uow.Commit();
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs));
@@ -1119,8 +1137,10 @@ namespace Umbraco.Core.Services
uow.Commit();
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(ex.Operation, evtMsgs));
}
moveEventArgs.MoveInfoCollection = moveInfo;
moveEventArgs.CanCancel = false;
uow.Commit();
uow.Events.Dispatch(MovedContentType, this, new MoveEventArgs<IContentType>(false, evtMsgs, moveInfo.ToArray()));
uow.Events.Dispatch(MovedContentType, this, moveEventArgs);
}
return Attempt.Succeed(
@@ -1228,7 +1248,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingMediaType, this, new SaveEventArgs<IMediaType>(mediaType)))
var saveEventArgs = new SaveEventArgs<IMediaType>(mediaType);
if (uow.Events.DispatchCancelable(SavingMediaType, this, saveEventArgs))
{
uow.Commit();
return;
@@ -1244,8 +1265,8 @@ namespace Umbraco.Core.Services
uow.Commit();
UpdateContentXmlStructure(mediaType);
uow.Events.Dispatch(SavedMediaType, this, new SaveEventArgs<IMediaType>(mediaType, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedMediaType, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save MediaType performed by user", userId, mediaType.Id);
uow.Commit();
@@ -1266,7 +1287,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingMediaType, this, new SaveEventArgs<IMediaType>(asArray)))
var saveEventArgs = new SaveEventArgs<IMediaType>(asArray);
if (uow.Events.DispatchCancelable(SavingMediaType, this, saveEventArgs))
{
uow.Commit();
return;
@@ -1290,8 +1312,8 @@ namespace Umbraco.Core.Services
uow.Commit();
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray());
uow.Events.Dispatch(SavedMediaType, this, new SaveEventArgs<IMediaType>(asArray, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedMediaType, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save MediaTypes performed by user", userId, -1);
uow.Commit();
@@ -1313,7 +1335,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingMediaType, this, new DeleteEventArgs<IMediaType>(mediaType)))
var deleteEventArgs = new DeleteEventArgs<IMediaType>(mediaType);
if (uow.Events.DispatchCancelable(DeletingMediaType, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -1329,7 +1352,9 @@ namespace Umbraco.Core.Services
repository.Delete(mediaType);
uow.Events.Dispatch(DeletedMediaType, this, new DeleteEventArgs<IMediaType>(deletedMediaTypes.DistinctBy(x => x.Id), false));
deleteEventArgs.CanCancel = false;
deleteEventArgs.DeletedEntities = deletedMediaTypes.DistinctBy(x => x.Id);
uow.Events.Dispatch(DeletedMediaType, this, deleteEventArgs);
Audit(uow, AuditType.Delete, "Delete MediaType performed by user", userId, mediaType.Id);
uow.Commit();
@@ -1353,7 +1378,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingMediaType, this, new DeleteEventArgs<IMediaType>(asArray)))
var deleteEventArgs = new DeleteEventArgs<IMediaType>(asArray);
if (uow.Events.DispatchCancelable(DeletingMediaType, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -1375,7 +1401,9 @@ namespace Umbraco.Core.Services
repository.Delete(mediaType);
}
uow.Events.Dispatch(DeletedMediaType, this, new DeleteEventArgs<IMediaType>(deletedMediaTypes.DistinctBy(x => x.Id), false));
deleteEventArgs.DeletedEntities = deletedMediaTypes.DistinctBy(x => x.Id);
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedMediaType, this, deleteEventArgs);
Audit(uow, AuditType.Delete, "Delete MediaTypes performed by user", userId, -1);
uow.Commit();
+25 -14
View File
@@ -312,7 +312,9 @@ namespace Umbraco.Core.Services
var moveInfo = new List<MoveEventInfo<IDataTypeDefinition>>();
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Moving, this, new MoveEventArgs<IDataTypeDefinition>(evtMsgs, new MoveEventInfo<IDataTypeDefinition>(toMove, toMove.Path, parentId))))
var moveEventInfo = new MoveEventInfo<IDataTypeDefinition>(toMove, toMove.Path, parentId);
var moveEventArgs = new MoveEventArgs<IDataTypeDefinition>(evtMsgs, moveEventInfo);
if (uow.Events.DispatchCancelable(Moving, this, moveEventArgs))
{
uow.Commit();
return Attempt.Fail(new OperationStatus<MoveOperationStatusType>(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs));
@@ -338,7 +340,9 @@ namespace Umbraco.Core.Services
new OperationStatus<MoveOperationStatusType>(ex.Operation, evtMsgs));
}
uow.Commit();
uow.Events.Dispatch(Moved, this, new MoveEventArgs<IDataTypeDefinition>(false, evtMsgs, moveInfo.ToArray()));
moveEventArgs.MoveInfoCollection = moveInfo;
moveEventArgs.CanCancel = false;
uow.Events.Dispatch(Moved, this, moveEventArgs);
}
return Attempt.Succeed(
@@ -354,7 +358,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition)))
var saveEventArgs = new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return;
@@ -369,8 +374,8 @@ namespace Umbraco.Core.Services
dataTypeDefinition.CreatorId = userId;
repository.AddOrUpdate(dataTypeDefinition);
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save DataTypeDefinition performed by user", userId, dataTypeDefinition.Id);
uow.Commit();
@@ -397,9 +402,10 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
var saveEventArgs = new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions);
if (raiseEvents)
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions)))
{
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return;
@@ -415,7 +421,10 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions, false));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
Audit(uow, AuditType.Save, string.Format("Save DataTypeDefinition performed by user"), userId, -1);
uow.Commit();
@@ -504,7 +513,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition)))
var saveEventArgs = new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return;
@@ -526,8 +536,8 @@ namespace Umbraco.Core.Services
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));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
}
@@ -544,7 +554,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IDataTypeDefinition>(dataTypeDefinition)))
var deleteEventArgs = new DeleteEventArgs<IDataTypeDefinition>(dataTypeDefinition);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -556,8 +567,8 @@ namespace Umbraco.Core.Services
Audit(uow, AuditType.Delete, "Delete DataTypeDefinition performed by user", userId, dataTypeDefinition.Id);
uow.Commit();
uow.Events.Dispatch(Deleted, this, new DeleteEventArgs<IDataTypeDefinition>(dataTypeDefinition, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
}
}
+8 -5
View File
@@ -32,7 +32,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IDomain>(domain, evtMsgs)))
var deleteEventArgs = new DeleteEventArgs<IDomain>(domain, evtMsgs);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -42,8 +43,8 @@ namespace Umbraco.Core.Services
repository.Delete(domain);
uow.Commit();
var args = new DeleteEventArgs<IDomain>(domain, false, evtMsgs);
uow.Events.Dispatch(Deleted, this, args);
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
return OperationStatus.Success(evtMsgs);
}
@@ -92,7 +93,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IDomain>(domainEntity, evtMsgs)))
var saveEventArgs = new SaveEventArgs<IDomain>(domainEntity, evtMsgs);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -101,7 +103,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateDomainRepository(uow);
repository.AddOrUpdate(domainEntity);
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IDomain>(domainEntity, false, evtMsgs));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
return OperationStatus.Success(evtMsgs);
}
+12 -80
View File
@@ -16,50 +16,26 @@ namespace Umbraco.Core.Services
{
public class EntityService : ScopeRepositoryService, IEntityService
{
private readonly IRuntimeCacheProvider _runtimeCache;
private readonly Dictionary<string, Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>> _supportedObjectTypes;
private readonly IdkMap _idkMap;
public EntityService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory,
IContentService contentService, IContentTypeService contentTypeService, IMediaService mediaService, IDataTypeService dataTypeService,
IMemberService memberService, IMemberTypeService memberTypeService, IRuntimeCacheProvider runtimeCache)
IMemberService memberService, IMemberTypeService memberTypeService, IdkMap idkMap)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
_runtimeCache = runtimeCache;
IContentTypeService contentTypeService1 = contentTypeService;
_idkMap = idkMap;
_supportedObjectTypes = new Dictionary<string, Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>>
{
{typeof (IDataTypeDefinition).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.DataType, dataTypeService.GetDataTypeDefinitionById)},
{typeof (IContent).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.Document, contentService.GetById)},
{typeof (IContentType).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.DocumentType, contentTypeService1.GetContentType)},
{typeof (IContentType).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.DocumentType, contentTypeService.GetContentType)},
{typeof (IMedia).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.Media, mediaService.GetById)},
{typeof (IMediaType).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.MediaType, contentTypeService1.GetMediaType)},
{typeof (IMediaType).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.MediaType, contentTypeService.GetMediaType)},
{typeof (IMember).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.Member, memberService.GetById)},
{typeof (IMemberType).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.MemberType, memberTypeService.Get)},
//{typeof (IUmbracoEntity).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.EntityContainer, id =>
//{
// using (var uow = UowProvider.GetUnitOfWork())
// {
// var found = uow.Database.FirstOrDefault<NodeDto>("SELECT * FROM umbracoNode WHERE id=@id", new { id = id });
// return found == null ? null : new UmbracoEntity(found.Trashed)
// {
// Id = found.NodeId,
// Name = found.Text,
// Key = found.UniqueId,
// SortOrder = found.SortOrder,
// Path = found.Path,
// NodeObjectTypeId = found.NodeObjectType.Value,
// CreateDate = found.CreateDate,
// CreatorId = found.UserId.Value,
// Level = found.Level,
// ParentId = found.ParentId
// };
// }
//})}
};
}
#region Static Queries
@@ -68,6 +44,8 @@ namespace Umbraco.Core.Services
#endregion
internal IdkMap IdkMap { get { return _idkMap; } }
/// <summary>
/// Returns the integer id for a given GUID
/// </summary>
@@ -76,33 +54,12 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public Attempt<int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType)
{
var result = _runtimeCache.GetCacheItem<int?>(CacheKeys.IdToKeyCacheKey + key, () =>
{
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType);
var sql = new Sql()
.Select("id")
.From<NodeDto>()
.Where<NodeDto>(
dto =>
dto.UniqueId == key &&
dto.NodeObjectType == nodeObjectType);
return uow.Database.ExecuteScalar<int?>(sql);
}
});
return result.HasValue ? Attempt.Succeed(result.Value) : Attempt<int>.Fail();
return _idkMap.GetIdForKey(key, umbracoObjectType);
}
public Attempt<int> GetIdForUdi(Udi udi)
{
var guidUdi = udi as GuidUdi;
if (guidUdi == null)
return Attempt<int>.Fail();
var umbracoType = Constants.UdiEntityType.ToUmbracoObjectType(guidUdi.EntityType);
return GetIdForKey(guidUdi.Guid, umbracoType);
return _idkMap.GetIdForUdi(udi);
}
/// <summary>
@@ -113,32 +70,7 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public Attempt<Guid> GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType)
{
var result = _runtimeCache.GetCacheItem<Guid?>(CacheKeys.KeyToIdCacheKey + id, () =>
{
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
{
var nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType);
var sql = new Sql()
.Select("uniqueID")
.From<NodeDto>()
.Where<NodeDto>(
dto =>
dto.NodeId == id &&
dto.NodeObjectType == nodeObjectType);
return uow.Database.ExecuteScalar<Guid?>(sql);
}
});
return result.HasValue ? Attempt.Succeed(result.Value) : Attempt<Guid>.Fail();
}
private static Guid GetNodeObjectTypeGuid(UmbracoObjectTypes umbracoObjectType)
{
var guid = umbracoObjectType.GetGuid();
if (guid == Guid.Empty)
throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ").");
return guid;
return _idkMap.GetKeyForId(id, umbracoObjectType);
}
public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true)
@@ -404,7 +336,7 @@ namespace Umbraco.Core.Services
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="filter"></param>
/// <param name="filter"></param>
/// <returns></returns>
public IEnumerable<IUmbracoEntity> GetPagedDescendants(int id, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "")
@@ -417,7 +349,7 @@ namespace Umbraco.Core.Services
var query = Query<IUmbracoEntity>.Builder;
//if the id is System Root, then just get all
if (id != Constants.System.Root)
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
IQuery<IUmbracoEntity> filterQuery = null;
if (filter.IsNullOrWhiteSpace() == false)
+118 -31
View File
@@ -70,7 +70,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingStylesheet, this, new SaveEventArgs<Stylesheet>(stylesheet)))
var saveEventArgs = new SaveEventArgs<Stylesheet>(stylesheet);
if (uow.Events.DispatchCancelable(SavingStylesheet, this, saveEventArgs))
{
uow.Commit();
return;
@@ -78,8 +79,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateStylesheetRepository(uow);
repository.AddOrUpdate(stylesheet);
uow.Events.Dispatch(SavedStylesheet, this, new SaveEventArgs<Stylesheet>(stylesheet, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedStylesheet, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save Stylesheet performed by user", userId, -1);
uow.Commit();
@@ -103,15 +104,16 @@ namespace Umbraco.Core.Services
return;
}
if (uow.Events.DispatchCancelable(DeletingStylesheet, this, new DeleteEventArgs<Stylesheet>(stylesheet)))
var deleteEventArgs = new DeleteEventArgs<Stylesheet>(stylesheet);
if (uow.Events.DispatchCancelable(DeletingStylesheet, this, deleteEventArgs))
{
uow.Commit();
return;
}
repository.Delete(stylesheet);
uow.Events.Dispatch(DeletedStylesheet, this, new DeleteEventArgs<Stylesheet>(stylesheet, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedStylesheet, this, deleteEventArgs);
Audit(uow, AuditType.Delete, string.Format("Delete Stylesheet performed by user"), userId, -1);
uow.Commit();
@@ -171,7 +173,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingScript, this, new SaveEventArgs<Script>(script)))
var saveEventArgs = new SaveEventArgs<Script>(script);
if (uow.Events.DispatchCancelable(SavingScript, this, saveEventArgs))
{
uow.Commit();
return;
@@ -179,8 +182,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateScriptRepository(uow);
repository.AddOrUpdate(script);
uow.Events.Dispatch(SavedScript, this, new SaveEventArgs<Script>(script, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedScript, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save Script performed by user", userId, -1);
uow.Commit();
@@ -204,15 +207,16 @@ namespace Umbraco.Core.Services
return;
}
if (uow.Events.DispatchCancelable(DeletingScript, this, new DeleteEventArgs<Script>(script)))
var deleteEventArgs = new DeleteEventArgs<Script>(script);
if (uow.Events.DispatchCancelable(DeletingScript, this, deleteEventArgs))
{
uow.Commit();
return;
}
repository.Delete(script);
uow.Events.Dispatch(DeletedScript, this, new DeleteEventArgs<Script>(script, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedScript, this, deleteEventArgs);
Audit(uow, AuditType.Delete, string.Format("Delete Script performed by user"), userId, -1);
uow.Commit();
@@ -289,7 +293,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingTemplate, this, new SaveEventArgs<ITemplate>(template, true, evtMsgs, additionalData)))
var saveEventArgs = new SaveEventArgs<ITemplate>(template, true, evtMsgs, additionalData);
if (uow.Events.DispatchCancelable(SavingTemplate, this, saveEventArgs))
{
uow.Commit();
return Attempt.Fail(new OperationStatus<ITemplate, OperationStatusType>(template, OperationStatusType.FailedCancelledByEvent, evtMsgs));
@@ -297,8 +302,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateTemplateRepository(uow);
repository.AddOrUpdate(template);
uow.Events.Dispatch(SavedTemplate, this, new SaveEventArgs<ITemplate>(template, false, evtMsgs));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedTemplate, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save Template performed by user", userId, template.Id);
uow.Commit();
@@ -562,18 +567,21 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateTemplateRepository(uow);
if (uow.Events.DispatchCancelable(DeletingTemplate, this, new DeleteEventArgs<ITemplate>(template)))
var repository = RepositoryFactory.CreateTemplateRepository(uow);
var args = new DeleteEventArgs<ITemplate>(template);
if (uow.Events.DispatchCancelable(DeletingTemplate, this, args))
{
uow.Commit();
return;
}
repository.Delete(template);
uow.Events.Dispatch(DeletedTemplate, this, new DeleteEventArgs<ITemplate>(template, false));
args.CanCancel = false;
uow.Events.Dispatch(DeletedTemplate, this, args);
Audit(uow, AuditType.Delete, "Delete Template performed by user", userId, template.Id);
uow.Commit();
}
@@ -621,6 +629,34 @@ namespace Umbraco.Core.Services
}
}
public Stream GetMacroScriptFileContentStream(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMacroScriptRepository(uow);
return repository.GetFileContentStream(filepath);
}
}
public void SetMacroScriptFileContent(string filepath, Stream content)
{
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateMacroScriptRepository(uow);
repository.SetFileContent(filepath, content);
uow.Commit();
}
}
public long GetMacroScriptFileSize(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMacroScriptRepository(uow);
return repository.GetFileSize(filepath);
}
}
#endregion
public Stream GetStylesheetFileContentStream(string filepath)
@@ -679,6 +715,34 @@ namespace Umbraco.Core.Services
}
}
public Stream GetUserControlFileContentStream(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserControlRepository(uow);
return repository.GetFileContentStream(filepath);
}
}
public void SetUserControlFileContent(string filepath, Stream content)
{
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateUserControlRepository(uow);
repository.SetFileContent(filepath, content);
uow.Commit();
}
}
public long GetUserControlFileSize(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserControlRepository(uow);
return repository.GetFileSize(filepath);
}
}
public Stream GetXsltFileContentStream(string filepath)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
@@ -783,6 +847,26 @@ namespace Umbraco.Core.Services
}
}
[Obsolete("MacroScripts are obsolete - this is for backwards compatibility with upgraded sites.")]
public IPartialView GetMacroScript(string path)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMacroScriptRepository(uow);
return repository.Get(path);
}
}
[Obsolete("UserControls are obsolete - this is for backwards compatibility with upgraded sites.")]
public IUserControl GetUserControl(string path)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserControlRepository(uow);
return repository.Get(path);
}
}
public IEnumerable<IPartialView> GetPartialViewMacros(params string[] names)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
@@ -822,10 +906,11 @@ namespace Umbraco.Core.Services
private Attempt<IPartialView> CreatePartialViewMacro(IPartialView partialView, PartialViewType partialViewType, string snippetName = null, int userId = 0)
{
var newEventArgs = new NewEventArgs<IPartialView>(partialView, true, partialView.Alias, -1);
using (var scope = UowProvider.ScopeProvider.CreateScope())
{
scope.Complete(); // always
if (scope.Events.DispatchCancelable(CreatingPartialView, this, new NewEventArgs<IPartialView>(partialView, true, partialView.Alias, -1)))
scope.Complete(); // always
if (scope.Events.DispatchCancelable(CreatingPartialView, this, newEventArgs))
return Attempt<IPartialView>.Fail();
}
@@ -839,8 +924,8 @@ namespace Umbraco.Core.Services
{
var repository = GetPartialViewRepository(partialViewType, uow);
repository.AddOrUpdate(partialView);
uow.Events.Dispatch(CreatedPartialView, this, new NewEventArgs<IPartialView>(partialView, false, partialView.Alias, -1));
newEventArgs.CanCancel = false;
uow.Events.Dispatch(CreatedPartialView, this, newEventArgs);
Audit(uow, AuditType.Save, string.Format("Save {0} performed by user", partialViewType), userId, -1);
uow.Commit();
@@ -871,15 +956,16 @@ namespace Umbraco.Core.Services
return false;
}
if (uow.Events.DispatchCancelable(DeletingPartialView, this, new DeleteEventArgs<IPartialView>(partialView)))
var deleteEventArgs = new DeleteEventArgs<IPartialView>(partialView);
if (uow.Events.DispatchCancelable(DeletingPartialView, this, deleteEventArgs))
{
uow.Commit();
return false;
}
repository.Delete(partialView);
uow.Events.Dispatch(DeletedPartialView, this, new DeleteEventArgs<IPartialView>(partialView, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedPartialView, this, deleteEventArgs);
Audit(uow, AuditType.Delete, string.Format("Delete {0} performed by user", partialViewType), userId, -1);
uow.Commit();
@@ -903,7 +989,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingPartialView, this, new SaveEventArgs<IPartialView>(partialView)))
var saveEventArgs = new SaveEventArgs<IPartialView>(partialView);
if (uow.Events.DispatchCancelable(SavingPartialView, this, saveEventArgs))
{
uow.Commit();
return Attempt<IPartialView>.Fail();
@@ -911,8 +998,8 @@ namespace Umbraco.Core.Services
var repository = GetPartialViewRepository(partialViewType, uow);
repository.AddOrUpdate(partialView);
uow.Events.Dispatch(SavedPartialView, this, new SaveEventArgs<IPartialView>(partialView, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedPartialView, this, saveEventArgs);
Audit(uow, AuditType.Save, string.Format("Save {0} performed by user", partialViewType), userId, -1);
uow.Commit();
+46
View File
@@ -17,6 +17,10 @@ namespace Umbraco.Core.Services
void DeletePartialViewMacroFolder(string folderPath);
IPartialView GetPartialView(string path);
IPartialView GetPartialViewMacro(string path);
[Obsolete("MacroScripts are obsolete - this is for backwards compatibility with upgraded sites.")]
IPartialView GetMacroScript(string path);
[Obsolete("UserControls are obsolete - this is for backwards compatibility with upgraded sites.")]
IUserControl GetUserControl(string path);
IEnumerable<IPartialView> GetPartialViewMacros(params string[] names);
IXsltFile GetXsltFile(string path);
IEnumerable<IXsltFile> GetXsltFiles(params string[] names);
@@ -263,6 +267,27 @@ namespace Umbraco.Core.Services
/// <returns>The size of the template.</returns>
long GetTemplateFileSize(string filepath);
/// <summary>
/// Gets the content of a macroscript as a stream.
/// </summary>
/// <param name="filepath">The filesystem path to the macroscript.</param>
/// <returns>The content of the macroscript.</returns>
Stream GetMacroScriptFileContentStream(string filepath);
/// <summary>
/// Sets the content of a macroscript.
/// </summary>
/// <param name="filepath">The filesystem path to the macroscript.</param>
/// <param name="content">The content of the macroscript.</param>
void SetMacroScriptFileContent(string filepath, Stream content);
/// <summary>
/// Gets the size of a macroscript.
/// </summary>
/// <param name="filepath">The filesystem path to the macroscript.</param>
/// <returns>The size of the macroscript.</returns>
long GetMacroScriptFileSize(string filepath);
/// <summary>
/// Gets the content of a stylesheet as a stream.
/// </summary>
@@ -305,6 +330,27 @@ namespace Umbraco.Core.Services
/// <returns>The size of the script file.</returns>
long GetScriptFileSize(string filepath);
/// <summary>
/// Gets the content of a usercontrol as a stream.
/// </summary>
/// <param name="filepath">The filesystem path to the usercontrol.</param>
/// <returns>The content of the usercontrol.</returns>
Stream GetUserControlFileContentStream(string filepath);
/// <summary>
/// Sets the content of a usercontrol.
/// </summary>
/// <param name="filepath">The filesystem path to the usercontrol.</param>
/// <param name="content">The content of the usercontrol.</param>
void SetUserControlFileContent(string filepath, Stream content);
/// <summary>
/// Gets the size of a usercontrol.
/// </summary>
/// <param name="filepath">The filesystem path to the usercontrol.</param>
/// <returns>The size of the usercontrol.</returns>
long GetUserControlFileSize(string filepath);
/// <summary>
/// Gets the content of a XSLT file as a stream.
/// </summary>
@@ -136,5 +136,11 @@ namespace Umbraco.Core.Services
/// <param name="language"><see cref="ILanguage"/> to delete</param>
/// <param name="userId">Optional id of the user deleting the language</param>
void Delete(ILanguage language, int userId = 0);
/// <summary>
/// Gets the full dictionary key map.
/// </summary>
/// <returns>The full dictionary key map.</returns>
Dictionary<string, Guid> GetDictionaryItemKeyMap();
}
}
+9 -3
View File
@@ -119,10 +119,16 @@ namespace Umbraco.Core.Services
IMember CreateMemberWithIdentity(string username, string email, string name, IMemberType memberType);
/// <summary>
/// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method
/// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method which can be
/// used during Member creation.
/// </summary>
/// <remarks>This method exists so that Umbraco developers can use one entry point to create/update
/// Members if they choose to. </remarks>
/// <remarks>
/// This method exists so that Umbraco developers can use this entry point to set a password when Creating members ...
/// this will not work for updating members in most cases (depends on your membership provider settings)
///
/// It is preferred to use the membership APIs for working with passwords, in the near future this method will be obsoleted
/// and the ASP.NET Identity APIs should be used instead.
/// </remarks>
/// <param name="member">The Member to save the password for</param>
/// <param name="password">The password to encrypt and save</param>
void SavePassword(IMember member, string password);
@@ -72,6 +72,18 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMembershipUser"/></returns>
T CreateWithIdentity(string username, string email, string passwordValue, string memberTypeAlias);
/// <summary>
/// Creates and persists a new <see cref="IMembershipUser"/>
/// </summary>
/// <remarks>An <see cref="IMembershipUser"/> can be of type <see cref="IMember"/> or <see cref="IUser"/></remarks>
/// <param name="username">Username of the <see cref="IMembershipUser"/> to create</param>
/// <param name="email">Email of the <see cref="IMembershipUser"/> to create</param>
/// <param name="passwordValue">This value should be the encoded/encrypted/hashed value for the password that will be stored in the database</param>
/// <param name="memberTypeAlias">Alias of the Type</param>
/// <param name="isApproved">IsApproved of the <see cref="IMembershipUser"/> to create</param>
/// <returns><see cref="IMembershipUser"/></returns>
T CreateWithIdentity(string username, string email, string passwordValue, string memberTypeAlias, bool isApproved);
/// <summary>
/// Gets an <see cref="IMembershipUser"/> by its provider key
/// </summary>
+192
View File
@@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
{
public class IdkMap
{
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim();
private readonly Dictionary<int, TypedId<Guid>> _id2Key = new Dictionary<int, TypedId<Guid>>();
private readonly Dictionary<Guid, TypedId<int>> _key2Id = new Dictionary<Guid, TypedId<int>>();
public IdkMap(IDatabaseUnitOfWorkProvider uowProvider)
{
_uowProvider = uowProvider;
}
// note - no need for uow, scope would be enough, but a pain to wire
// note - for pure read-only we might want to *not* enforce a transaction?
public Attempt<int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType)
{
TypedId<int> id;
try
{
_locker.EnterReadLock();
if (_key2Id.TryGetValue(key, out id) && id.UmbracoObjectType == umbracoObjectType) return Attempt.Succeed(id.Id);
}
finally
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
int? val;
using (var uow = _uowProvider.GetUnitOfWork())
{
val = uow.Database.ExecuteScalar<int?>("SELECT id FROM umbracoNode WHERE uniqueId=@id AND nodeObjectType=@nodeObjectType",
new { id = key, nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType) });
uow.Commit();
}
if (val == null) return Attempt<int>.Fail();
try
{
_locker.EnterWriteLock();
_id2Key[val.Value] = new TypedId<Guid>(key, umbracoObjectType);
_key2Id[key] = new TypedId<int>(val.Value, umbracoObjectType);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
return Attempt.Succeed(val.Value);
}
public Attempt<int> GetIdForUdi(Udi udi)
{
var guidUdi = udi as GuidUdi;
if (guidUdi == null)
return Attempt<int>.Fail();
var umbracoType = Constants.UdiEntityType.ToUmbracoObjectType(guidUdi.EntityType);
return GetIdForKey(guidUdi.Guid, umbracoType);
}
public Attempt<Guid> GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType)
{
TypedId<Guid> key;
try
{
_locker.EnterReadLock();
if (_id2Key.TryGetValue(id, out key) && key.UmbracoObjectType == umbracoObjectType) return Attempt.Succeed(key.Id);
}
finally
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
Guid? val;
using (var uow = _uowProvider.GetUnitOfWork())
{
val = uow.Database.ExecuteScalar<Guid?>("SELECT uniqueId FROM umbracoNode WHERE id=@id AND nodeObjectType=@nodeObjectType",
new { id, nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType) });
uow.Commit();
}
if (val == null) return Attempt<Guid>.Fail();
try
{
_locker.EnterWriteLock();
_id2Key[id] = new TypedId<Guid>(val.Value, umbracoObjectType); ;
_key2Id[val.Value] = new TypedId<int>();
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
return Attempt.Succeed(val.Value);
}
private static Guid GetNodeObjectTypeGuid(UmbracoObjectTypes umbracoObjectType)
{
var guid = umbracoObjectType.GetGuid();
if (guid == Guid.Empty)
throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ").");
return guid;
}
public void ClearCache()
{
try
{
_locker.EnterWriteLock();
_id2Key.Clear();
_key2Id.Clear();
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
public void ClearCache(int id)
{
try
{
_locker.EnterWriteLock();
TypedId<Guid> key;
if (_id2Key.TryGetValue(id, out key) == false) return;
_id2Key.Remove(id);
_key2Id.Remove(key.Id);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
public void ClearCache(Guid key)
{
try
{
_locker.EnterWriteLock();
TypedId<int> id;
if (_key2Id.TryGetValue(key, out id) == false) return;
_id2Key.Remove(id.Id);
_key2Id.Remove(key);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
private struct TypedId<T>
{
private readonly T _id;
private readonly UmbracoObjectTypes _umbracoObjectType;
public T Id
{
get { return _id; }
}
public UmbracoObjectTypes UmbracoObjectType
{
get { return _umbracoObjectType; }
}
public TypedId(T id, UmbracoObjectTypes umbracoObjectType)
{
_umbracoObjectType = umbracoObjectType;
_id = id;
}
}
}
}
@@ -79,7 +79,8 @@ namespace Umbraco.Core.Services
item.Translations = translations;
}
if (uow.Events.DispatchCancelable(SavingDictionaryItem, this, new SaveEventArgs<IDictionaryItem>(item)))
var saveEventArgs = new SaveEventArgs<IDictionaryItem>(item);
if (uow.Events.DispatchCancelable(SavingDictionaryItem, this, saveEventArgs))
{
uow.Commit();
return item;
@@ -90,8 +91,8 @@ namespace Umbraco.Core.Services
//ensure the lazy Language callback is assigned
EnsureDictionaryItemLanguageCallback(item);
uow.Events.Dispatch(SavedDictionaryItem, this, new SaveEventArgs<IDictionaryItem>(item));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedDictionaryItem, this, saveEventArgs);
return item;
}
@@ -256,7 +257,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingDictionaryItem, this, new DeleteEventArgs<IDictionaryItem>(dictionaryItem)))
var deleteEventArgs = new DeleteEventArgs<IDictionaryItem>(dictionaryItem);
if (uow.Events.DispatchCancelable(DeletingDictionaryItem, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -264,8 +266,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
repository.Delete(dictionaryItem);
uow.Events.Dispatch(DeletedDictionaryItem, this, new DeleteEventArgs<IDictionaryItem>(dictionaryItem, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedDictionaryItem, this, deleteEventArgs);
Audit(uow, AuditType.Delete, "Delete DictionaryItem performed by user", userId, dictionaryItem.Id);
uow.Commit();
@@ -336,15 +338,16 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingLanguage, this, new SaveEventArgs<ILanguage>(language)))
var saveEventArgs = new SaveEventArgs<ILanguage>(language);
if (uow.Events.DispatchCancelable(SavingLanguage, this, saveEventArgs))
{
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateLanguageRepository(uow);
repository.AddOrUpdate(language);
uow.Events.Dispatch(SavedLanguage, this, new SaveEventArgs<ILanguage>(language, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedLanguage, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save Language performed by user", userId, language.Id);
uow.Commit();
@@ -360,7 +363,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingLanguage, this, new DeleteEventArgs<ILanguage>(language)))
var deleteEventArgs = new DeleteEventArgs<ILanguage>(language);
if (uow.Events.DispatchCancelable(DeletingLanguage, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -369,7 +373,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateLanguageRepository(uow);
repository.Delete(language);
uow.Events.Dispatch(DeletedLanguage, this, new DeleteEventArgs<ILanguage>(language, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedLanguage, this, deleteEventArgs);
Audit(uow, AuditType.Delete, "Delete Language performed by user", userId, language.Id);
uow.Commit();
@@ -400,6 +405,15 @@ namespace Umbraco.Core.Services
}
}
public Dictionary<string, Guid> GetDictionaryItemKeyMap()
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateDictionaryRepository(uow);
return repository.GetDictionaryItemKeyMap();
}
}
#region Event Handlers
/// <summary>
/// Occurs before Delete
+8 -6
View File
@@ -144,15 +144,16 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMacro>(macro)))
var deleteEventArgs = new DeleteEventArgs<IMacro>(macro);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
{
uow.Commit();
return;
}
var repository = RepositoryFactory.CreateMacroRepository(uow);
repository.Delete(macro);
uow.Events.Dispatch(Deleted, this, new DeleteEventArgs<IMacro>(macro, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
Audit(uow, AuditType.Delete, "Delete Macro performed by user", userId, -1);
uow.Commit();
@@ -168,7 +169,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMacro>(macro)))
var saveEventArgs = new SaveEventArgs<IMacro>(macro);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return;
@@ -181,8 +183,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateMacroRepository(uow);
repository.AddOrUpdate(macro);
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMacro>(macro, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
Audit(uow, AuditType.Save, "Save Macro performed by user", userId, -1);
uow.Commit();
+90 -48
View File
@@ -35,14 +35,16 @@ namespace Umbraco.Core.Services
private readonly IDataTypeService _dataTypeService;
private readonly IUserService _userService;
private readonly MediaFileSystem _mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem;
private readonly IdkMap _idkMap;
public MediaService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IDataTypeService dataTypeService, IUserService userService)
public MediaService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IDataTypeService dataTypeService, IUserService userService, IdkMap idkMap)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
if (userService == null) throw new ArgumentNullException("userService");
_dataTypeService = dataTypeService;
_userService = userService;
_idkMap = idkMap;
}
/// <summary>
@@ -68,7 +70,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Creating, this, new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId)))
var newEventArgs = new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId);
if (uow.Events.DispatchCancelable(Creating, this, newEventArgs))
{
uow.Commit();
media.WasCancelled = true;
@@ -76,7 +79,8 @@ namespace Umbraco.Core.Services
}
media.CreatorId = userId;
uow.Events.Dispatch(Created, this, new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId));
newEventArgs.CanCancel = false;
uow.Events.Dispatch(Created, this, newEventArgs);
Audit(uow, AuditType.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
uow.Commit();
@@ -108,7 +112,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Creating, this, new NewEventArgs<IMedia>(media, mediaTypeAlias, parent)))
var newEventArgs = new NewEventArgs<IMedia>(media, mediaTypeAlias, parent);
if (uow.Events.DispatchCancelable(Creating, this, newEventArgs))
{
uow.Commit();
media.WasCancelled = true;
@@ -116,8 +121,8 @@ namespace Umbraco.Core.Services
}
media.CreatorId = userId;
uow.Events.Dispatch(Created, this, new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parent));
newEventArgs.CanCancel = false;
uow.Events.Dispatch(Created, this, newEventArgs);
Audit(uow, AuditType.New, string.Format("Media '{0}' was created", name), media.CreatorId, media.Id);
uow.Commit();
@@ -148,14 +153,16 @@ namespace Umbraco.Core.Services
{
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
// 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)))
var newEventArgs = new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId);
if (uow.Events.DispatchCancelable(Creating, this, newEventArgs))
{
uow.Commit();
media.WasCancelled = true;
return media;
}
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(media)))
var saveEventArgs = new SaveEventArgs<IMedia>(media);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
media.WasCancelled = true;
@@ -172,8 +179,10 @@ namespace Umbraco.Core.Services
repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, m));
}
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(media, false));
uow.Events.Dispatch(Created, this, new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
newEventArgs.CanCancel = false;
uow.Events.Dispatch(Created, this, newEventArgs);
Audit(uow, AuditType.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
uow.Commit();
@@ -206,14 +215,16 @@ namespace Umbraco.Core.Services
{
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
// 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)))
var newEventArgs = new NewEventArgs<IMedia>(media, mediaTypeAlias, parent);
if (uow.Events.DispatchCancelable(Creating, this, newEventArgs))
{
uow.Commit();
media.WasCancelled = true;
return media;
}
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(media)))
var saveEventArgs = new SaveEventArgs<IMedia>(media);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
media.WasCancelled = true;
@@ -230,8 +241,10 @@ namespace Umbraco.Core.Services
repository.AddOrUpdatePreviewXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, m));
}
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(media, false));
uow.Events.Dispatch(Created, this, new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parent));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
newEventArgs.CanCancel = false;
uow.Events.Dispatch(Created, this, newEventArgs);
Audit(uow, AuditType.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
uow.Commit();
@@ -327,12 +340,15 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IMedia"/></returns>
public IMedia GetById(Guid key)
{
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateMediaRepository(uow);
var query = Query<IMedia>.Builder.Where(x => x.Key == key);
return repository.GetByQuery(query).SingleOrDefault();
}
// the repository implements a cache policy on int identifiers, not guids,
// and we are not changing it now, but we still would like to rely on caching
// instead of running a full query against the database, so relying on the
// id-key map, which is fast.
//
// we should inject the id-key map but ... breaking changes ... yada
var a = _idkMap.GetIdForKey(key, UmbracoObjectTypes.Media);
return a.Success ? GetById(a.Result) : null;
}
/// <summary>
@@ -781,7 +797,9 @@ namespace Umbraco.Core.Services
{
var originalPath = media.Path;
if (uow.Events.DispatchCancelable(Moving, this, new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(media, originalPath, parentId)), "Moving"))
var moveEventInfo = new MoveEventInfo<IMedia>(media, originalPath, parentId);
var moveEventArgs = new MoveEventArgs<IMedia>(moveEventInfo);
if (uow.Events.DispatchCancelable(Moving, this, moveEventArgs, "Moving"))
{
uow.Commit();
return;
@@ -797,7 +815,7 @@ namespace Umbraco.Core.Services
//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)
moveEventInfo
};
//Ensure that relevant properties are updated on children
@@ -811,7 +829,9 @@ namespace Umbraco.Core.Services
Save(updatedDescendants, userId, false); //no events!
}
uow.Events.Dispatch(Moved, this, new MoveEventArgs<IMedia>(false, moveInfo.ToArray()), "Moved");
moveEventArgs.MoveInfoCollection = moveInfo;
moveEventArgs.CanCancel = false;
uow.Events.Dispatch(Moved, this, moveEventArgs, "Moved");
Audit(uow, AuditType.Move, "Move Media performed by user", userId, media.Id);
uow.Commit();
@@ -853,7 +873,8 @@ namespace Umbraco.Core.Services
private Attempt<OperationStatus> DeleteUow(IScopeUnitOfWork uow, IMedia media, int userId, EventMessages evtMsgs)
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMedia>(media, evtMsgs)))
var deleteEventArgs = new DeleteEventArgs<IMedia>(media, evtMsgs);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
{
return OperationStatus.Cancelled(evtMsgs);
}
@@ -867,9 +888,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.Delete(media);
var args = new DeleteEventArgs<IMedia>(media, false, evtMsgs);
uow.Events.Dispatch(Deleted, this, args);
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
Audit(uow, AuditType.Delete, "Delete Media performed by user", userId, media.Id);
@@ -888,7 +908,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(media, evtMsgs)))
var saveEventArgs = new SaveEventArgs<IMedia>(media, evtMsgs);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -899,13 +920,13 @@ namespace Umbraco.Core.Services
throw new ArgumentException("Cannot save media with empty name.");
}
var repository = RepositoryFactory.CreateMediaRepository(uow);
var repository = RepositoryFactory.CreateMediaRepository(uow);
//set the creator id if it's new
if (media.HasIdentity == false)
{
media.CreatorId = userId;
}
}
repository.AddOrUpdate(media);
repository.AddOrUpdateContentXml(media, m => _entitySerializer.Serialize(this, _dataTypeService, _userService, m));
@@ -916,7 +937,10 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(media, false, evtMsgs));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
Audit(uow, AuditType.Save, "Save Media performed by user", userId, media.Id);
uow.Commit();
@@ -938,7 +962,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(asArray, evtMsgs)))
var saveEventArgs = new SaveEventArgs<IMedia>(asArray, evtMsgs);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -958,7 +983,10 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(asArray, false, evtMsgs));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
Audit(uow, AuditType.Save, "Save Media items performed by user", userId, -1);
uow.Commit();
@@ -983,15 +1011,17 @@ namespace Umbraco.Core.Services
var files = ((MediaRepository)repository).GetFilesInRecycleBinForUploadField();
if (uow.Events.DispatchCancelable(EmptyingRecycleBin, this, new RecycleBinEventArgs(nodeObjectType, entities, files)))
var recycleBinEventArgs = new RecycleBinEventArgs(nodeObjectType, entities, files);
if (uow.Events.DispatchCancelable(EmptyingRecycleBin, this, recycleBinEventArgs))
{
uow.Commit();
return;
}
var success = repository.EmptyRecycleBin();
uow.Events.Dispatch(EmptiedRecycleBin, this, new RecycleBinEventArgs(nodeObjectType, entities, files, success));
recycleBinEventArgs.CanCancel = false;
recycleBinEventArgs.RecycleBinEmptiedSuccessfully = success;
uow.Events.Dispatch(EmptiedRecycleBin, this, recycleBinEventArgs);
Audit(uow, AuditType.Delete, "Empty Media Recycle Bin performed by user", 0, -21);
uow.Commit();
@@ -1017,7 +1047,8 @@ namespace Umbraco.Core.Services
IDictionary<string, IMedia> rootItems;
var mediaToDelete = this.TrackDeletionsForDeleteContentOfTypes(mediaTypeIds, repository, out rootItems).ToArray();
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMedia>(mediaToDelete), "Deleting"))
var deleteEventArgs = new DeleteEventArgs<IMedia>(mediaToDelete);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs, "Deleting"))
{
uow.Commit();
return;
@@ -1089,14 +1120,16 @@ namespace Umbraco.Core.Services
//see: http://issues.umbraco.org/issue/U4-9336
media.EnsureValidPath(Logger, entity => GetById(entity.ParentId), QuickUpdate);
var originalPath = media.Path;
if (uow.Events.DispatchCancelable(Trashing, this, new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(media, originalPath, Constants.System.RecycleBinMedia)), "Trashing"))
var moveEventInfo = new MoveEventInfo<IMedia>(media, originalPath, Constants.System.RecycleBinMedia);
var moveEventArgs = new MoveEventArgs<IMedia>(moveEventInfo);
if (uow.Events.DispatchCancelable(Trashing, this, moveEventArgs, "Trashing"))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
}
var moveInfo = new List<MoveEventInfo<IMedia>>
{
new MoveEventInfo<IMedia>(media, originalPath, Constants.System.RecycleBinMedia)
moveEventInfo
};
//get descendents to process of the content item that is being moved to trash - must be done before changing the state below,
@@ -1119,7 +1152,9 @@ namespace Umbraco.Core.Services
moveInfo.Add(new MoveEventInfo<IMedia>(descendant, descendant.Path, descendant.ParentId));
}
uow.Events.Dispatch(Trashed, this, new MoveEventArgs<IMedia>(false, evtMsgs, moveInfo.ToArray()), "Trashed");
moveEventArgs.MoveInfoCollection = moveInfo;
moveEventArgs.CanCancel = false;
uow.Events.Dispatch(Trashed, this, moveEventArgs, "Trashed");
Audit(uow, AuditType.Move, "Move Media to Recycle Bin performed by user", userId, media.Id);
uow.Commit();
@@ -1162,12 +1197,14 @@ namespace Umbraco.Core.Services
private void DeleteVersions(IScopeUnitOfWork uow, int id, DateTime versionDate, int userId = 0)
{
if (uow.Events.DispatchCancelable(DeletingVersions, this, new DeleteRevisionsEventArgs(id, dateToRetain: versionDate)))
var deleteRevisionsEventArgs = new DeleteRevisionsEventArgs(id, dateToRetain: versionDate);
if (uow.Events.DispatchCancelable(DeletingVersions, this, deleteRevisionsEventArgs))
return;
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.DeleteVersions(id, versionDate);
uow.Events.Dispatch(DeletedVersions, this, new DeleteRevisionsEventArgs(id, false, dateToRetain: versionDate));
deleteRevisionsEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedVersions, this, deleteRevisionsEventArgs);
Audit(uow, AuditType.Delete, "Delete Media by version date performed by user", userId, -1);
}
@@ -1183,7 +1220,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingVersions, this, new DeleteRevisionsEventArgs(id, specificVersion: versionId)))
var deleteRevisionsEventArgs = new DeleteRevisionsEventArgs(id, specificVersion: versionId);
if (uow.Events.DispatchCancelable(DeletingVersions, this, deleteRevisionsEventArgs))
{
uow.Commit();
return;
@@ -1197,8 +1235,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.DeleteVersion(versionId);
uow.Events.Dispatch(DeletedVersions, this, new DeleteRevisionsEventArgs(id, false, specificVersion: versionId));
deleteRevisionsEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedVersions, this, deleteRevisionsEventArgs);
Audit(uow, AuditType.Delete, "Delete Media by version performed by user", userId, -1);
uow.Commit();
@@ -1241,7 +1279,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMedia>(asArray)))
var saveEventArgs = new SaveEventArgs<IMedia>(asArray);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return false;
@@ -1273,7 +1312,10 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMedia>(asArray, false));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
Audit(uow, AuditType.Sort, "Sorting Media performed by user", userId, 0);
uow.Commit();
@@ -71,7 +71,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMemberGroup>(memberGroup)))
var saveEventArgs = new SaveEventArgs<IMemberGroup>(memberGroup);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return;
@@ -81,17 +82,19 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(memberGroup);
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMemberGroup>(memberGroup, false));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
}
}
public void Delete(IMemberGroup memberGroup)
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMemberGroup>(memberGroup)))
var deleteEventArgs = new DeleteEventArgs<IMemberGroup>(memberGroup);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -99,7 +102,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateMemberGroupRepository(uow);
repository.Delete(memberGroup);
uow.Commit();
uow.Events.Dispatch(Deleted, this, new DeleteEventArgs<IMemberGroup>(memberGroup, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
}
}
+48 -16
View File
@@ -25,8 +25,11 @@ namespace Umbraco.Core.Services
{
private readonly IMemberGroupService _memberGroupService;
private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer();
private readonly IDataTypeService _dataTypeService;
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
private readonly IDataTypeService _dataTypeService;
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
//only for unit tests!
internal MembershipProviderBase MembershipProvider { get; set; }
public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IMemberGroupService memberGroupService, IDataTypeService dataTypeService)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
@@ -35,7 +38,7 @@ namespace Umbraco.Core.Services
if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
_memberGroupService = memberGroupService;
_dataTypeService = dataTypeService;
}
}
#region IMemberService Implementation
@@ -91,7 +94,7 @@ namespace Umbraco.Core.Services
{
if (member == null) throw new ArgumentNullException("member");
var provider = MembershipProviderExtensions.GetMembersMembershipProvider();
var provider = MembershipProvider ?? MembershipProviderExtensions.GetMembersMembershipProvider();
if (provider.IsUmbracoMembershipProvider())
{
provider.ChangePassword(member.Username, "", password);
@@ -234,7 +237,8 @@ namespace Umbraco.Core.Services
var query = Query<IMember>.Builder.Where(x => x.ContentTypeId == memberTypeId);
var members = repository.GetByQuery(query).ToArray();
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMember>(members)))
var deleteEventArgs = new DeleteEventArgs<IMember>(members);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -826,6 +830,22 @@ namespace Umbraco.Core.Services
return CreateMemberWithIdentity(username, email, username, passwordValue, memberType);
}
/// <summary>
/// Creates and persists a new <see cref="IMember"/>
/// </summary>
/// <remarks>An <see cref="IMembershipUser"/> can be of type <see cref="IMember"/> or <see cref="IUser"/></remarks>
/// <param name="username">Username of the <see cref="IMembershipUser"/> to create</param>
/// <param name="email">Email of the <see cref="IMembershipUser"/> to create</param>
/// <param name="passwordValue">This value should be the encoded/encrypted/hashed value for the password that will be stored in the database</param>
/// <param name="memberTypeAlias">Alias of the Type</param>
/// <param name="isApproved">Is the member approved</param>
/// <returns><see cref="IMember"/></returns>
IMember IMembershipMemberService<IMember>.CreateWithIdentity(string username, string email, string passwordValue, string memberTypeAlias, bool isApproved)
{
var memberType = FindMemberTypeByAlias(memberTypeAlias);
return CreateMemberWithIdentity(username, email, username, passwordValue, memberType, isApproved);
}
/// <summary>
/// Creates and persists a Member
/// </summary>
@@ -836,16 +856,18 @@ namespace Umbraco.Core.Services
/// <param name="name">Name of the Member to create</param>
/// <param name="passwordValue">This value should be the encoded/encrypted/hashed value for the password that will be stored in the database</param>
/// <param name="memberType">MemberType the Member should be based on</param>
/// <param name="isApproved">Optional IsApproved of the Member to create</param>
/// <returns><see cref="IMember"/></returns>
private IMember CreateMemberWithIdentity(string username, string email, string name, string passwordValue, IMemberType memberType)
private IMember CreateMemberWithIdentity(string username, string email, string name, string passwordValue, IMemberType memberType, bool isApproved = true)
{
if (memberType == null) throw new ArgumentNullException("memberType");
var member = new Member(name, email.ToLower().Trim(), username, passwordValue, memberType);
var member = new Member(name, email.ToLower().Trim(), username, passwordValue, memberType, isApproved);
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMember>(member)))
var saveEventArgs = new SaveEventArgs<IMember>(member);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
member.WasCancelled = true;
@@ -864,7 +886,8 @@ namespace Umbraco.Core.Services
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMember>(member, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
uow.Events.Dispatch(Created, this, new NewEventArgs<IMember>(member, false, memberType.Alias, -1));
}
@@ -941,7 +964,8 @@ namespace Umbraco.Core.Services
private void Delete(IScopeUnitOfWork uow, IMember member)
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMember>(member)))
var deleteEventArgs = new DeleteEventArgs<IMember>(member);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -951,8 +975,8 @@ namespace Umbraco.Core.Services
repository.Delete(member);
uow.Commit();
var args = new DeleteEventArgs<IMember>(member, false);
uow.Events.Dispatch(Deleted, this, args);
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
}
/// <summary>
@@ -965,9 +989,10 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
var saveEventArgs = new SaveEventArgs<IMember>(entity);
if (raiseEvents)
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMember>(entity)))
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return;
@@ -991,7 +1016,10 @@ namespace Umbraco.Core.Services
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMember>(entity, false));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
}
}
@@ -1010,7 +1038,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMember>(asArray)))
var saveEventArgs = new SaveEventArgs<IMember>(asArray);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return;
@@ -1032,7 +1061,10 @@ namespace Umbraco.Core.Services
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMember>(asArray, false));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
}
+18 -12
View File
@@ -80,7 +80,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMemberType>(memberType)))
var saveEventArgs = new SaveEventArgs<IMemberType>(memberType);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return;
@@ -101,7 +102,8 @@ namespace Umbraco.Core.Services
UpdateContentXmlStructure(memberType);
uow.Commit(); // actually commit uow
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMemberType>(memberType, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
}
}
@@ -114,7 +116,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IMemberType>(asArray)))
var saveEventArgs = new SaveEventArgs<IMemberType>(asArray);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return;
@@ -131,8 +134,8 @@ namespace Umbraco.Core.Services
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray());
uow.Commit(); // actually commit uow
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IMemberType>(asArray, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
}
@@ -142,10 +145,11 @@ namespace Umbraco.Core.Services
{
using (new WriteLock(Locker))
{
var deleteEventArgs = new DeleteEventArgs<IMemberType>(memberType);
using (var scope = UowProvider.ScopeProvider.CreateScope())
{
scope.Complete(); // always
if (scope.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMemberType>(memberType)))
scope.Complete(); // always
if (scope.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
return;
}
@@ -157,7 +161,8 @@ namespace Umbraco.Core.Services
repository.Delete(memberType);
uow.Commit();
uow.Events.Dispatch(Deleted, this, new DeleteEventArgs<IMemberType>(memberType, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
}
}
}
@@ -168,10 +173,11 @@ namespace Umbraco.Core.Services
using (new WriteLock(Locker))
{
var deleteEventArgs = new DeleteEventArgs<IMemberType>(asArray);
using (var scope = UowProvider.ScopeProvider.CreateScope())
{
scope.Complete(); // always
if (scope.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<IMemberType>(asArray)))
scope.Complete(); // always
if (scope.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
return;
}
@@ -189,8 +195,8 @@ namespace Umbraco.Core.Services
}
uow.Commit();
uow.Events.Dispatch(Deleted, this, new DeleteEventArgs<IMemberType>(asArray, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
}
}
}
+25 -18
View File
@@ -89,18 +89,18 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId)
{
var packageRepo = UmbracoConfig.For.UmbracoSettings().PackageRepositories.GetDefault();
var packageRepo = UmbracoConfig.For.UmbracoSettings().PackageRepositories.GetDefault();
using (var httpClient = new HttpClient())
using (var uow = _uowProvider.GetUnitOfWork())
{
{
//includeHidden = true because we don't care if it's hidden we want to get the file regardless
var url = string.Format("{0}/{1}?version={2}&includeHidden=true&asFile=true", packageRepo.RestApiUrl, packageId, umbracoVersion.ToString(3));
byte[] bytes;
try
{
bytes = httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult();
}
try
{
bytes = httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult();
}
catch (HttpRequestException ex)
{
throw new ConnectionException("An error occuring downloading the package from " + url, ex);
@@ -109,20 +109,20 @@ namespace Umbraco.Core.Services
//successfull
if (bytes.Length > 0)
{
var packagePath = IOHelper.MapPath(SystemDirectories.Packages);
var packagePath = IOHelper.MapPath(SystemDirectories.Packages);
// Check for package directory
if (Directory.Exists(packagePath) == false)
Directory.CreateDirectory(packagePath);
var packageFilePath = Path.Combine(packagePath, packageId + ".umb");
var packageFilePath = Path.Combine(packagePath, packageId + ".umb");
using (var fs1 = new FileStream(packageFilePath, FileMode.Create))
{
fs1.Write(bytes, 0, bytes.Length);
return "packages\\" + packageId + ".umb";
}
}
}
Audit(uow, AuditType.PackagerInstall, string.Format("Package {0} fetched from {1}", packageId, packageRepo.Id), userId, -1);
return null;
@@ -133,7 +133,7 @@ namespace Umbraco.Core.Services
{
var auditRepo = _repositoryFactory.CreateAuditRepository(uow);
auditRepo.AddOrUpdate(new AuditItem(objectId, message, type, userId));
}
}
#region Content
@@ -285,6 +285,7 @@ namespace Umbraco.Core.Services
var nodeName = element.Attribute("nodeName").Value;
var path = element.Attribute("path").Value;
var template = element.Attribute("template").Value;
var key = Guid.Empty;
var properties = from property in element.Elements()
where property.Attribute("isDoc") == null
@@ -302,6 +303,12 @@ namespace Umbraco.Core.Services
SortOrder = int.Parse(sortOrder)
};
if (element.Attribute("key") != null && Guid.TryParse(element.Attribute("key").Value, out key))
{
// update the Guid (for UDI support)
content.Key = key;
}
foreach (var property in properties)
{
string propertyTypeAlias = isLegacySchema ? property.Attribute("alias").Value : property.Name.LocalName;
@@ -520,7 +527,7 @@ namespace Umbraco.Core.Services
{
var foldersAttribute = documentType.Attribute("Folders");
var infoElement = documentType.Element("Info");
if (foldersAttribute != null && infoElement != null
if (foldersAttribute != null && infoElement != null
//don't import any folder if this is a child doc type - the parent doc type will need to
//exist which contains it's folders
&& ((string)infoElement.Element("Master")).IsNullOrWhiteSpace())
@@ -1041,7 +1048,7 @@ namespace Umbraco.Core.Services
{
_logger.Error<PackagingService>("Could not create folder: " + rootFolder, tryCreateFolder.Exception);
throw tryCreateFolder.Exception;
}
}
current = _dataTypeService.GetContainer(tryCreateFolder.Result.Entity.Id);
}
@@ -1091,14 +1098,14 @@ namespace Umbraco.Core.Services
if (dataTypeDefinition != null)
{
var valuesWithoutKeys = prevaluesElement.Elements("PreValue")
.Where(x => ((string) x.Attribute("Alias")).IsNullOrWhiteSpace())
.Where(x => ((string)x.Attribute("Alias")).IsNullOrWhiteSpace())
.Select(x => x.Attribute("Value").Value);
var valuesWithKeys = prevaluesElement.Elements("PreValue")
.Where(x => ((string) x.Attribute("Alias")).IsNullOrWhiteSpace() == false)
.Where(x => ((string)x.Attribute("Alias")).IsNullOrWhiteSpace() == false)
.ToDictionary(
key => (string) key.Attribute("Alias"),
val => new PreValue((string) val.Attribute("Value")));
key => (string)key.Attribute("Alias"),
val => new PreValue((string)val.Attribute("Value")));
//save the values with keys
_dataTypeService.SavePreValues(dataTypeDefinition, valuesWithKeys);
@@ -1956,12 +1963,12 @@ namespace Umbraco.Core.Services
/// <summary>
/// Occurs after a package is imported
/// </summary>
internal static event TypedEventHandler<IPackagingService, ImportPackageEventArgs<InstallationSummary>> ImportedPackage;
public static event TypedEventHandler<IPackagingService, ImportPackageEventArgs<InstallationSummary>> ImportedPackage;
/// <summary>
/// Occurs after a package is uninstalled
/// </summary>
internal static event TypedEventHandler<IPackagingService, UninstallPackageEventArgs<UninstallationSummary>> UninstalledPackage;
public static event TypedEventHandler<IPackagingService, UninstallPackageEventArgs<UninstallationSummary>> UninstalledPackage;
#endregion
}
@@ -148,7 +148,8 @@ namespace Umbraco.Core.Services
return Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>>.Succeed(new OperationStatus<PublicAccessEntry, OperationStatusType>(entry, OperationStatusType.Success, evtMsgs));
}
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<PublicAccessEntry>(entry, evtMsgs)))
var saveEventArgs = new SaveEventArgs<PublicAccessEntry>(entry, evtMsgs);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>>.Fail(
@@ -158,8 +159,8 @@ namespace Umbraco.Core.Services
repo.AddOrUpdate(entry);
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<PublicAccessEntry>(entry, false, evtMsgs));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
return Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>>.Succeed(
new OperationStatus<PublicAccessEntry, OperationStatusType>(entry, OperationStatusType.Success, evtMsgs));
}
@@ -193,7 +194,8 @@ namespace Umbraco.Core.Services
entry.RemoveRule(existingRule);
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<PublicAccessEntry>(entry, evtMsgs)))
var saveEventArgs = new SaveEventArgs<PublicAccessEntry>(entry, evtMsgs);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -202,8 +204,8 @@ namespace Umbraco.Core.Services
repo.AddOrUpdate(entry);
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<PublicAccessEntry>(entry, false, evtMsgs));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
return OperationStatus.Success(evtMsgs);
}
@@ -219,7 +221,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<PublicAccessEntry>(entry, evtMsgs)))
var saveEventArgs = new SaveEventArgs<PublicAccessEntry>(entry, evtMsgs);
if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -228,7 +231,8 @@ namespace Umbraco.Core.Services
var repo = RepositoryFactory.CreatePublicAccessRepository(uow);
repo.AddOrUpdate(entry);
uow.Commit();
uow.Events.Dispatch(Saved, this, new SaveEventArgs<PublicAccessEntry>(entry, false, evtMsgs));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
return OperationStatus.Success(evtMsgs);
}
@@ -245,7 +249,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs<PublicAccessEntry>(entry, evtMsgs)))
var deleteEventArgs = new DeleteEventArgs<PublicAccessEntry>(entry, evtMsgs);
if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs))
{
uow.Commit();
return OperationStatus.Cancelled(evtMsgs);
@@ -254,7 +259,8 @@ namespace Umbraco.Core.Services
var repo = RepositoryFactory.CreatePublicAccessRepository(uow);
repo.Delete(entry);
uow.Commit();
uow.Events.Dispatch(Deleted, this, new DeleteEventArgs<PublicAccessEntry>(entry, false, evtMsgs));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
return OperationStatus.Success(evtMsgs);
}
@@ -72,10 +72,28 @@ namespace Umbraco.Core.Services
public static bool HasAccess(this IPublicAccessService publicAccessService, string path, MembershipUser member, RoleProvider roleProvider)
{
return publicAccessService.HasAccess(path, member.UserName, roleProvider.GetRolesForUser);
}
/// <summary>
/// Checks if the member with the specified username has access to the path which is also based on the passed in roles for the member
/// </summary>
/// <param name="publicAccessService"></param>
/// <param name="path"></param>
/// <param name="username"></param>
/// <param name="rolesCallback">A callback to retrieve the roles for this member</param>
/// <returns></returns>
public static bool HasAccess(this IPublicAccessService publicAccessService, string path, string username, Func<string, IEnumerable<string>> rolesCallback)
{
if (rolesCallback == null) throw new ArgumentNullException("roles");
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", "username");
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value cannot be null or whitespace.", "path");
var entry = publicAccessService.GetEntryForContent(path.EnsureEndsWith(path));
if (entry == null) return true;
var roles = roleProvider.GetRolesForUser(member.UserName);
var roles = rolesCallback(username);
return entry.Rules.Any(x => x.RuleType == Constants.Conventions.PublicAccess.MemberRoleRuleType
&& roles.Contains(x.RuleValue));
}
+24 -13
View File
@@ -412,7 +412,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateRelationRepository(uow);
if (uow.Events.DispatchCancelable(SavingRelation, this, new SaveEventArgs<IRelation>(relation)))
var saveEventArgs = new SaveEventArgs<IRelation>(relation);
if (uow.Events.DispatchCancelable(SavingRelation, this, saveEventArgs))
{
uow.Commit();
return relation;
@@ -420,7 +421,8 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(relation);
uow.Commit();
uow.Events.Dispatch(SavedRelation, this, new SaveEventArgs<IRelation>(relation, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedRelation, this, saveEventArgs);
return relation;
}
}
@@ -442,7 +444,8 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingRelation, this, new SaveEventArgs<IRelation>(relation)))
var saveEventArgs = new SaveEventArgs<IRelation>(relation);
if (uow.Events.DispatchCancelable(SavingRelation, this, saveEventArgs))
{
uow.Commit();
return relation;
@@ -450,8 +453,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateRelationRepository(uow);
repository.AddOrUpdate(relation);
uow.Commit();
uow.Events.Dispatch(SavedRelation, this, new SaveEventArgs<IRelation>(relation, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedRelation, this, saveEventArgs);
return relation;
}
}
@@ -568,7 +571,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingRelation, this, new SaveEventArgs<IRelation>(relation)))
var saveEventArgs = new SaveEventArgs<IRelation>(relation);
if (uow.Events.DispatchCancelable(SavingRelation, this, saveEventArgs))
{
uow.Commit();
return;
@@ -576,7 +580,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateRelationRepository(uow);
repository.AddOrUpdate(relation);
uow.Commit();
uow.Events.Dispatch(SavedRelation, this, new SaveEventArgs<IRelation>(relation, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedRelation, this, saveEventArgs);
}
}
@@ -588,7 +593,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(SavingRelationType, this, new SaveEventArgs<IRelationType>(relationType)))
var saveEventArgs = new SaveEventArgs<IRelationType>(relationType);
if (uow.Events.DispatchCancelable(SavingRelationType, this, saveEventArgs))
{
uow.Commit();
return;
@@ -596,7 +602,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateRelationTypeRepository(uow);
repository.AddOrUpdate(relationType);
uow.Commit();
uow.Events.Dispatch(SavedRelationType, this, new SaveEventArgs<IRelationType>(relationType, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedRelationType, this, saveEventArgs);
}
}
@@ -608,7 +615,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingRelation, this, new DeleteEventArgs<IRelation>(relation)))
var deleteEventArgs = new DeleteEventArgs<IRelation>(relation);
if (uow.Events.DispatchCancelable(DeletingRelation, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -616,7 +624,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateRelationRepository(uow);
repository.Delete(relation);
uow.Commit();
uow.Events.Dispatch(DeletedRelation, this, new DeleteEventArgs<IRelation>(relation, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedRelation, this, deleteEventArgs);
}
}
@@ -628,7 +637,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingRelationType, this, new DeleteEventArgs<IRelationType>(relationType)))
var deleteEventArgs = new DeleteEventArgs<IRelationType>(relationType);
if (uow.Events.DispatchCancelable(DeletingRelationType, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -636,7 +646,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateRelationTypeRepository(uow);
repository.Delete(relationType);
uow.Commit();
uow.Events.Dispatch(DeletedRelationType, this, new DeleteEventArgs<IRelationType>(relationType, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedRelationType, this, deleteEventArgs);
}
}
+10 -6
View File
@@ -63,6 +63,8 @@ namespace Umbraco.Core.Services
private Lazy<IExternalLoginService> _externalLoginService;
private Lazy<IRedirectUrlService> _redirectUrlService;
internal IdkMap IdkMap { get; private set; }
/// <summary>
/// public ctor - will generally just be used for unit testing all items are optional and if not specified, the defaults will be used
/// </summary>
@@ -171,9 +173,11 @@ namespace Umbraco.Core.Services
EventMessagesFactory = eventMessagesFactory;
IdkMap = new IdkMap(provider);
BuildServiceCache(provider, cache,
repositoryFactory,
logger, eventMessagesFactory);
logger, eventMessagesFactory, IdkMap);
}
/// <summary>
@@ -184,7 +188,8 @@ namespace Umbraco.Core.Services
CacheHelper cache,
RepositoryFactory repositoryFactory,
ILogger logger,
IEventMessagesFactory eventMessagesFactory)
IEventMessagesFactory eventMessagesFactory,
IdkMap idkMap)
{
EventMessagesFactory = eventMessagesFactory;
@@ -256,10 +261,10 @@ namespace Umbraco.Core.Services
_memberService = new Lazy<IMemberService>(() => new MemberService(provider, repositoryFactory, logger, eventMessagesFactory, _memberGroupService.Value, _dataTypeService.Value));
if (_contentService == null)
_contentService = new Lazy<IContentService>(() => new ContentService(provider, repositoryFactory, logger, eventMessagesFactory, _dataTypeService.Value, _userService.Value));
_contentService = new Lazy<IContentService>(() => new ContentService(provider, repositoryFactory, logger, eventMessagesFactory, _dataTypeService.Value, _userService.Value, idkMap));
if (_mediaService == null)
_mediaService = new Lazy<IMediaService>(() => new MediaService(provider, repositoryFactory, logger, eventMessagesFactory, _dataTypeService.Value, _userService.Value));
_mediaService = new Lazy<IMediaService>(() => new MediaService(provider, repositoryFactory, logger, eventMessagesFactory, _dataTypeService.Value, _userService.Value, idkMap));
if (_contentTypeService == null)
_contentTypeService = new Lazy<IContentTypeService>(() => new ContentTypeService(provider, repositoryFactory, logger, eventMessagesFactory, _contentService.Value, _mediaService.Value));
@@ -277,8 +282,7 @@ namespace Umbraco.Core.Services
_entityService = new Lazy<IEntityService>(() => new EntityService(
provider, repositoryFactory, logger, eventMessagesFactory,
_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));
idkMap));
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));
+53 -16
View File
@@ -19,7 +19,6 @@ namespace Umbraco.Core.Services
/// </summary>
public class UserService : ScopeRepositoryService, IUserService
{
//TODO: We need to change the isUpgrading flag to use an app state enum as described here: http://issues.umbraco.org/issue/U4-6816
// in the meantime, we will use a boolean which we are currently using during upgrades to ensure that a user object is not persisted during this phase, otherwise
// exceptions can occur if the db is not in it's correct state.
@@ -113,6 +112,26 @@ namespace Umbraco.Core.Services
return CreateUserWithIdentity(username, email, passwordValue, userType);
}
/// <summary>
/// Creates and persists a new <see cref="IUser"/>
/// </summary>
/// <param name="username">Username of the <see cref="IUser"/> to create</param>
/// <param name="email">Email of the <see cref="IUser"/> to create</param>
/// <param name="passwordValue">This value should be the encoded/encrypted/hashed value for the password that will be stored in the database</param>
/// <param name="memberTypeAlias">Alias of the Type</param>
/// <param name="isApproved">Is the member approved</param>
/// <returns><see cref="IUser"/></returns>
IUser IMembershipMemberService<IUser>.CreateWithIdentity(string username, string email, string passwordValue, string memberTypeAlias, bool isApproved)
{
var userType = GetUserTypeByAlias(memberTypeAlias);
if (userType == null)
{
throw new EntityNotFoundException("The user type " + memberTypeAlias + " could not be resolved");
}
return CreateUserWithIdentity(username, email, passwordValue, userType, isApproved);
}
/// <summary>
/// Creates and persists a Member
/// </summary>
@@ -122,8 +141,9 @@ namespace Umbraco.Core.Services
/// <param name="email">Email of the Member to create</param>
/// <param name="passwordValue">This value should be the encoded/encrypted/hashed value for the password that will be stored in the database</param>
/// <param name="userType">MemberType the Member should be based on</param>
/// <param name="isApproved">Is the user approved</param>
/// <returns><see cref="IUser"/></returns>
private IUser CreateUserWithIdentity(string username, string email, string passwordValue, IUserType userType)
private IUser CreateUserWithIdentity(string username, string email, string passwordValue, IUserType userType, bool isApproved = true)
{
if (userType == null) throw new ArgumentNullException("userType");
@@ -152,13 +172,14 @@ namespace Umbraco.Core.Services
StartContentId = -1,
StartMediaId = -1,
IsLockedOut = false,
IsApproved = true
IsApproved = isApproved
};
//adding default sections content and media
user.AddAllowedSection("content");
user.AddAllowedSection("media");
if (uow.Events.DispatchCancelable(SavingUser, this, new SaveEventArgs<IUser>(user)))
var saveEventArgs = new SaveEventArgs<IUser>(user);
if (uow.Events.DispatchCancelable(SavingUser, this, saveEventArgs))
{
uow.Commit();
return user;
@@ -166,8 +187,8 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(user);
uow.Commit();
uow.Events.Dispatch(SavedUser, this, new SaveEventArgs<IUser>(user, false));
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedUser, this, saveEventArgs);
return user;
}
@@ -294,7 +315,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingUser, this, new DeleteEventArgs<IUser>(user)))
var deleteEventArgs = new DeleteEventArgs<IUser>(user);
if (uow.Events.DispatchCancelable(DeletingUser, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -302,7 +324,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateUserRepository(uow);
repository.Delete(user);
uow.Commit();
uow.Events.Dispatch(DeletedUser, this, new DeleteEventArgs<IUser>(user, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedUser, this, deleteEventArgs);
}
}
}
@@ -317,7 +340,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(SavingUser, this, new SaveEventArgs<IUser>(entity)))
var saveEventArgs = new SaveEventArgs<IUser>(entity);
if (raiseEvents && uow.Events.DispatchCancelable(SavingUser, this, saveEventArgs))
{
uow.Commit();
return;
@@ -343,7 +367,10 @@ namespace Umbraco.Core.Services
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(SavedUser, this, new SaveEventArgs<IUser>(entity, false));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedUser, this, saveEventArgs);
}
}
catch (DbException ex)
{
@@ -371,9 +398,10 @@ namespace Umbraco.Core.Services
var asArray = entities.ToArray();
using (var uow = UowProvider.GetUnitOfWork())
{
var saveEventArgs = new SaveEventArgs<IUser>(asArray);
if (raiseEvents)
{
if (uow.Events.DispatchCancelable(SavingUser, this, new SaveEventArgs<IUser>(asArray)))
if (uow.Events.DispatchCancelable(SavingUser, this, saveEventArgs))
{
uow.Commit();
return;
@@ -396,7 +424,10 @@ namespace Umbraco.Core.Services
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(SavedUser, this, new SaveEventArgs<IUser>(asArray, false));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedUser, this, saveEventArgs);
}
}
@@ -699,7 +730,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (raiseEvents && uow.Events.DispatchCancelable(SavingUserType, this, new SaveEventArgs<IUserType>(userType)))
var saveEventArgs = new SaveEventArgs<IUserType>(userType);
if (raiseEvents && uow.Events.DispatchCancelable(SavingUserType, this, saveEventArgs))
{
uow.Commit();
return;
@@ -709,7 +741,10 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(userType);
uow.Commit();
if (raiseEvents)
uow.Events.Dispatch(SavedUserType, this, new SaveEventArgs<IUserType>(userType, false));
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(SavedUserType, this, saveEventArgs);
}
}
}
@@ -721,7 +756,8 @@ namespace Umbraco.Core.Services
{
using (var uow = UowProvider.GetUnitOfWork())
{
if (uow.Events.DispatchCancelable(DeletingUserType, this, new DeleteEventArgs<IUserType>(userType)))
var deleteEventArgs = new DeleteEventArgs<IUserType>(userType);
if (uow.Events.DispatchCancelable(DeletingUserType, this, deleteEventArgs))
{
uow.Commit();
return;
@@ -729,7 +765,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateUserTypeRepository(uow);
repository.Delete(userType);
uow.Commit();
uow.Events.Dispatch(DeletedUserType, this, new DeleteEventArgs<IUserType>(userType, false));
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedUserType, this, deleteEventArgs);
}
}
+129 -50
View File
@@ -701,67 +701,72 @@ namespace Umbraco.Core
return val;
}
/// <summary>
/// Generates a hash of a string based on the FIPS compliance setting.
/// </summary>
/// <param name="str">Referrs to itself</param>
/// <returns>The hashed string</returns>
public static string GenerateHash(this string str)
{
return CryptoConfig.AllowOnlyFipsAlgorithms
? str.ToSHA1()
: str.ToMd5();
}
/// <summary>
/// Converts the string to MD5
/// </summary>
/// <param name="stringToConvert">referrs to itself</param>
/// <returns>the md5 hashed string</returns>
/// <param name="stringToConvert">Referrs to itself</param>
/// <returns>The MD5 hashed string</returns>
public static string ToMd5(this string stringToConvert)
{
//create an instance of the MD5CryptoServiceProvider
var md5Provider = new MD5CryptoServiceProvider();
//convert our string into byte array
var byteArray = Encoding.UTF8.GetBytes(stringToConvert);
//get the hashed values created by our MD5CryptoServiceProvider
var hashedByteArray = md5Provider.ComputeHash(byteArray);
//create a StringBuilder object
var stringBuilder = new StringBuilder();
//loop to each each byte
foreach (var b in hashedByteArray)
{
//append it to our StringBuilder
stringBuilder.Append(b.ToString("x2").ToLower());
}
//return the hashed value
return stringBuilder.ToString();
return stringToConvert.GenerateHash("MD5");
}
/// <summary>
/// Converts the string to SHA1
/// </summary>
/// <param name="stringToConvert">referrs to itself</param>
/// <returns>the md5 hashed string</returns>
/// <returns>The SHA1 hashed string</returns>
public static string ToSHA1(this string stringToConvert)
{
//create an instance of the SHA1CryptoServiceProvider
var md5Provider = new SHA1CryptoServiceProvider();
//convert our string into byte array
var byteArray = Encoding.UTF8.GetBytes(stringToConvert);
//get the hashed values created by our SHA1CryptoServiceProvider
var hashedByteArray = md5Provider.ComputeHash(byteArray);
//create a StringBuilder object
var stringBuilder = new StringBuilder();
//loop to each each byte
foreach (var b in hashedByteArray)
{
//append it to our StringBuilder
stringBuilder.Append(b.ToString("x2").ToLower());
}
//return the hashed value
return stringBuilder.ToString();
return stringToConvert.GenerateHash("SHA1");
}
/// <summary>Generate a hash of a string based on the hashType passed in
/// </summary>
/// <param name="str">Referrs to itself</param>
/// <param name="hashType">String with the hash type. See remarks section of the CryptoConfig Class in MSDN docs for a list of possible values.</param>
/// <returns>The hashed string</returns>
private static string GenerateHash(this string str, string hashType)
{
//create an instance of the correct hashing provider based on the type passed in
var hasher = HashAlgorithm.Create(hashType);
if (hasher == null) throw new InvalidOperationException("No hashing type found by name " + hashType);
using (hasher)
{
//convert our string into byte array
var byteArray = Encoding.UTF8.GetBytes(str);
//get the hashed values created by our selected provider
var hashedByteArray = hasher.ComputeHash(byteArray);
//create a StringBuilder object
var stringBuilder = new StringBuilder();
//loop to each each byte
foreach (var b in hashedByteArray)
{
//append it to our StringBuilder
stringBuilder.Append(b.ToString("x2"));
}
//return the hashed value
return stringBuilder.ToString();
}
}
/// <summary>
/// Decodes a string that was encoded with UrlTokenEncode
/// </summary>
@@ -869,7 +874,7 @@ namespace Umbraco.Core
}
/// <summary>
/// Ensures that the folder path endds with a DirectorySeperatorChar
/// Ensures that the folder path ends with a DirectorySeperatorChar
/// </summary>
/// <param name="currentFolder"></param>
/// <returns></returns>
@@ -1465,10 +1470,84 @@ namespace Umbraco.Core
/// <returns></returns>
internal static Guid ToGuid(this string text)
{
var md5 = MD5.Create();
byte[] myStringBytes = Encoding.ASCII.GetBytes(text);
byte[] hash = md5.ComputeHash(myStringBytes);
return new Guid(hash);
return CreateGuidFromHash(UrlNamespace,
text,
CryptoConfig.AllowOnlyFipsAlgorithms
? 5 // SHA1
: 3); // MD5
}
/// <summary>
/// The namespace for URLs (from RFC 4122, Appendix C).
///
/// See <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>
/// </summary>
internal static readonly Guid UrlNamespace = new Guid("6ba7b811-9dad-11d1-80b4-00c04fd430c8");
/// <summary>
/// Creates a name-based UUID using the algorithm from RFC 4122 §4.3.
///
/// See <a href="https://github.com/LogosBible/Logos.Utility/blob/master/src/Logos.Utility/GuidUtility.cs#L34">GuidUtility.cs</a> for original implementation.
/// </summary>
/// <param name="namespaceId">The ID of the namespace.</param>
/// <param name="name">The name (within that namespace).</param>
/// <param name="version">The version number of the UUID to create; this value must be either
/// 3 (for MD5 hashing) or 5 (for SHA-1 hashing).</param>
/// <returns>A UUID derived from the namespace and name.</returns>
/// <remarks>See <a href="http://code.logos.com/blog/2011/04/generating_a_deterministic_guid.html">Generating a deterministic GUID</a>.</remarks>
internal static Guid CreateGuidFromHash(Guid namespaceId, string name, int version)
{
if (name == null)
throw new ArgumentNullException("name");
if (version != 3 && version != 5)
throw new ArgumentOutOfRangeException("version", "version must be either 3 or 5.");
// convert the name to a sequence of octets (as defined by the standard or conventions of its namespace) (step 3)
// ASSUME: UTF-8 encoding is always appropriate
byte[] nameBytes = Encoding.UTF8.GetBytes(name);
// convert the namespace UUID to network order (step 3)
byte[] namespaceBytes = namespaceId.ToByteArray();
SwapByteOrder(namespaceBytes);
// comput the hash of the name space ID concatenated with the name (step 4)
byte[] hash;
using (HashAlgorithm algorithm = version == 3 ? (HashAlgorithm)MD5.Create() : SHA1.Create())
{
algorithm.TransformBlock(namespaceBytes, 0, namespaceBytes.Length, null, 0);
algorithm.TransformFinalBlock(nameBytes, 0, nameBytes.Length);
hash = algorithm.Hash;
}
// most bytes from the hash are copied straight to the bytes of the new GUID (steps 5-7, 9, 11-12)
byte[] newGuid = new byte[16];
Array.Copy(hash, 0, newGuid, 0, 16);
// set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the appropriate 4-bit version number from Section 4.1.3 (step 8)
newGuid[6] = (byte)((newGuid[6] & 0x0F) | (version << 4));
// set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively (step 10)
newGuid[8] = (byte)((newGuid[8] & 0x3F) | 0x80);
// convert the resulting UUID to local byte order (step 13)
SwapByteOrder(newGuid);
return new Guid(newGuid);
}
// Converts a GUID (expressed as a byte array) to/from network order (MSB-first).
internal static void SwapByteOrder(byte[] guid)
{
SwapBytes(guid, 0, 3);
SwapBytes(guid, 1, 2);
SwapBytes(guid, 4, 5);
SwapBytes(guid, 6, 7);
}
private static void SwapBytes(byte[] guid, int left, int right)
{
byte temp = guid[left];
guid[left] = guid[right];
guid[right] = temp;
}
}
}
+5 -1
View File
@@ -68,7 +68,7 @@ namespace Umbraco.Core.Strings
/// <summary>
/// Flag mask for encoding.
/// </summary>
CodeMask = Unicode | Utf8 | Ascii,
CodeMask = Unicode | Utf8 | Ascii | TryAscii,
/// <summary>
/// Unicode encoding.
@@ -86,6 +86,10 @@ namespace Umbraco.Core.Strings
/// </summary>
Ascii = 0x0400,
/// <summary>
/// Ascii encoding, if possible.
/// </summary>
TryAscii = 0x0800,
// role values
@@ -152,12 +152,18 @@ namespace Umbraco.Core.Strings
/// <returns>The short string helper.</returns>
public DefaultShortStringHelper WithDefaultConfig()
{
var urlSegmentConvertTo = CleanStringType.Utf8;
if (_umbracoSettings.RequestHandler.ConvertUrlsToAscii)
urlSegmentConvertTo = CleanStringType.Ascii;
if (_umbracoSettings.RequestHandler.TryConvertUrlsToAscii)
urlSegmentConvertTo = CleanStringType.TryAscii;
return WithConfig(CleanStringType.UrlSegment, new Config
{
PreFilter = ApplyUrlReplaceCharacters,
PostFilter = x => CutMaxLength(x, 240),
IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', // letter, digit or underscore
StringType = (_umbracoSettings.RequestHandler.ConvertUrlsToAscii ? CleanStringType.Ascii : CleanStringType.Utf8) | CleanStringType.LowerCase,
StringType = urlSegmentConvertTo | CleanStringType.LowerCase,
BreakTermsOnUpper = false,
Separator = '-'
}).WithConfig(CleanStringType.FileName, new Config
@@ -542,9 +548,20 @@ function validateSafeAlias(input, value, immediate, callback) {{
// recode
var codeType = stringType & CleanStringType.CodeMask;
text = codeType == CleanStringType.Ascii
? Utf8ToAsciiConverter.ToAsciiString(text)
: RemoveSurrogatePairs(text);
switch (codeType)
{
case CleanStringType.Ascii:
text = Utf8ToAsciiConverter.ToAsciiString(text);
break;
case CleanStringType.TryAscii:
const char ESC = (char) 27;
var ctext = Utf8ToAsciiConverter.ToAsciiString(text, ESC);
if (ctext.Contains(ESC) == false) text = ctext;
break;
default:
text = RemoveSurrogatePairs(text);
break;
}
// clean
text = CleanCodeString(text, stringType, separator.Value, culture, config);
@@ -17,8 +17,9 @@ namespace Umbraco.Core.Strings
/// Converts an Utf8 string into an Ascii string.
/// </summary>
/// <param name="text">The text to convert.</param>
/// <param name="fail">The character to used to replace characters that cannot properly be converted.</param>
/// <returns>The converted text.</returns>
public static string ToAsciiString(string text)
public static string ToAsciiString(string text, char fail = '?')
{
var input = text.ToCharArray();
@@ -26,7 +27,7 @@ namespace Umbraco.Core.Strings
// but... we should be filtering short strings only...
var output = new char[input.Length * 3]; // *3 because of things such as OE
var len = ToAscii(input, output);
var len = ToAscii(input, output, fail);
return new string(output, 0, len);
//var output = new StringBuilder(input.Length + 16); // default is 16, start with at least input length + little extra
@@ -38,8 +39,9 @@ namespace Umbraco.Core.Strings
/// Converts an Utf8 string into an array of Ascii characters.
/// </summary>
/// <param name="text">The text to convert.</param>
/// <param name="fail">The character to used to replace characters that cannot properly be converted.</param>
/// <returns>The converted text.</returns>
public static char[] ToAsciiCharArray(string text)
public static char[] ToAsciiCharArray(string text, char fail = '?')
{
var input = text.ToCharArray();
@@ -47,7 +49,7 @@ namespace Umbraco.Core.Strings
// but... we should be filtering short strings only...
var output = new char[input.Length * 3]; // *3 because of things such as OE
var len = ToAscii(input, output);
var len = ToAscii(input, output, fail);
var array = new char[len];
Array.Copy(output, array, len);
return array;
@@ -64,10 +66,11 @@ namespace Umbraco.Core.Strings
/// </summary>
/// <param name="input">The input array.</param>
/// <param name="output">The output array.</param>
/// <param name="fail">The character to used to replace characters that cannot properly be converted.</param>
/// <returns>The number of characters in the output array.</returns>
/// <remarks>The caller must ensure that the output array is big enough.</remarks>
/// <exception cref="OverflowException">The output array is not big enough.</exception>
private static int ToAscii(char[] input, char[] output)
private static int ToAscii(char[] input, char[] output, char fail = '?')
{
var opos = 0;
@@ -75,10 +78,10 @@ namespace Umbraco.Core.Strings
if (char.IsSurrogate(input[ipos])) // ignore high surrogate
{
ipos++; // and skip low surrogate
output[opos++] = '?';
output[opos++] = fail;
}
else
ToAscii(input, ipos, output, ref opos);
ToAscii(input, ipos, output, ref opos, fail);
return opos;
}
@@ -109,12 +112,13 @@ namespace Umbraco.Core.Strings
/// <param name="ipos">The input position.</param>
/// <param name="output">The output array.</param>
/// <param name="opos">The output position.</param>
/// <param name="fail">The character to used to replace characters that cannot properly be converted.</param>
/// <remarks>
/// <para>Adapted from various sources on the 'net including <c>Lucene.Net.Analysis.ASCIIFoldingFilter</c>.</para>
/// <para>Input should contain Utf8 characters exclusively and NOT Unicode.</para>
/// <para>Removes controls, normalizes whitespaces, replaces symbols by '?'.</para>
/// </remarks>
private static void ToAscii(char[] input, int ipos, char[] output, ref int opos)
private static void ToAscii(char[] input, int ipos, char[] output, ref int opos, char fail = '?')
{
var c = input[ipos];
@@ -3583,7 +3587,7 @@ namespace Umbraco.Core.Strings
// output[opos++] = c;
// strict ASCII
output[opos++] = '?';
output[opos++] = fail;
break;
}
@@ -126,10 +126,12 @@ namespace Umbraco.Core.Sync
public static string GetServerHash(string machineName, string appDomainAppId)
{
var hasher = new HashCodeCombiner();
hasher.AddCaseInsensitiveString(appDomainAppId);
hasher.AddCaseInsensitiveString(machineName);
return hasher.GetCombinedHashCode();
using (var generator = new HashGenerator())
{
generator.AddString(machineName);
generator.AddString(appDomainAppId);
return generator.GenerateHash();
}
}
protected override bool RequiresDistributed(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, MessageType messageType)
+10 -1
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Core
@@ -70,6 +69,10 @@ namespace Umbraco.Core
[UdiType(UdiType.StringUdi)]
public const string AnyString = "any-string"; // that one is for tests
[UdiType(UdiType.StringUdi)]
public const string Language = "language";
[UdiType(UdiType.StringUdi)]
public const string MacroScript = "macroscript";
[UdiType(UdiType.StringUdi)]
public const string MediaFile = "media-file";
[UdiType(UdiType.StringUdi)]
@@ -83,6 +86,8 @@ namespace Umbraco.Core
[UdiType(UdiType.StringUdi)]
public const string PartialViewMacro = "partial-view-macro";
[UdiType(UdiType.StringUdi)]
public const string UserControl = "usercontrol";
[UdiType(UdiType.StringUdi)]
public const string Xslt = "xslt";
public static string FromUmbracoObjectType(UmbracoObjectTypes umbracoObjectType)
@@ -123,6 +128,8 @@ namespace Umbraco.Core
return FormsPreValue;
case UmbracoObjectTypes.FormsDataSource:
return FormsDataSource;
case UmbracoObjectTypes.Language:
return Language;
}
throw new NotSupportedException(string.Format("UmbracoObjectType \"{0}\" does not have a matching EntityType.", umbracoObjectType));
}
@@ -165,6 +172,8 @@ namespace Umbraco.Core
return UmbracoObjectTypes.FormsPreValue;
case FormsDataSource:
return UmbracoObjectTypes.FormsDataSource;
case Language:
return UmbracoObjectTypes.Language;
}
throw new NotSupportedException(
string.Format("EntityType \"{0}\" does not have a matching UmbracoObjectType.", entityType));
+27 -2
View File
@@ -97,7 +97,7 @@ namespace Umbraco.Core
/// </summary>
/// <param name="entity">The entity.</param>
/// <returns>The entity identifier of the entity.</returns>
public static GuidUdi GetUdi(this Umbraco.Core.Models.EntityContainer entity)
public static GuidUdi GetUdi(this EntityContainer entity)
{
if (entity == null) throw new ArgumentNullException("entity");
@@ -190,6 +190,17 @@ namespace Umbraco.Core
return new GuidUdi(Constants.UdiEntityType.Macro, entity.Key).EnsureClosed();
}
/// <summary>
/// Gets the entity identifier of the entity.
/// </summary>
/// <param name="entity">The entity.</param>
/// <returns>The entity identifier of the entity.</returns>
public static StringUdi GetUdi(this IUserControl entity)
{
if (entity == null) throw new ArgumentNullException("entity");
return new StringUdi(Constants.UdiEntityType.UserControl, entity.Path.TrimStart('/')).EnsureClosed();
}
/// <summary>
/// Gets the entity identifier of the entity.
/// </summary>
@@ -246,6 +257,17 @@ namespace Umbraco.Core
return new GuidUdi(Constants.UdiEntityType.RelationType, entity.Key).EnsureClosed();
}
/// <summary>
/// Gets the entity identifier of the entity.
/// </summary>
/// <param name="entity">The entity.</param>
/// <returns>The entity identifier of the entity.</returns>
public static StringUdi GetUdi(this ILanguage entity)
{
if (entity == null) throw new ArgumentNullException("entity");
return new StringUdi(Constants.UdiEntityType.Language, entity.IsoCode).EnsureClosed();
}
/// <summary>
/// Gets the entity identifier of the entity.
/// </summary>
@@ -279,7 +301,7 @@ namespace Umbraco.Core
var dataTypeComposition = entity as IDataTypeDefinition;
if (dataTypeComposition != null) return dataTypeComposition.GetUdi();
var container = entity as Umbraco.Core.Models.EntityContainer;
var container = entity as EntityContainer;
if (container != null) return container.GetUdi();
var media = entity as IMedia;
@@ -315,6 +337,9 @@ namespace Umbraco.Core
var relationType = entity as IRelationType;
if (relationType != null) return relationType.GetUdi();
var language = entity as ILanguage;
if (language != null) return language.GetUdi();
throw new NotSupportedException(string.Format("Entity type {0} is not supported.", entity.GetType().FullName));
}
}
+8 -2
View File
@@ -342,9 +342,12 @@
<Compile Include="Events\SupersedeEventAttribute.cs" />
<Compile Include="Exceptions\ConnectionException.cs" />
<Compile Include="HashCodeHelper.cs" />
<Compile Include="HashGenerator.cs" />
<Compile Include="IHttpContextAccessor.cs" />
<Compile Include="Models\EntityBase\IDeletableEntity.cs" />
<Compile Include="Models\IUserControl.cs" />
<Compile Include="Models\PublishedContent\PublishedContentTypeConverter.cs" />
<Compile Include="Models\UserControl.cs" />
<Compile Include="OrderedHashSet.cs" />
<Compile Include="Events\UninstallPackageEventArgs.cs" />
<Compile Include="Models\GridValue.cs" />
@@ -576,12 +579,16 @@
<Compile Include="Persistence\Repositories\Interfaces\IRedirectUrlRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IServerRegistrationRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IDeleteMediaFilesRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IUserControlRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IXsltFileRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\ITaskRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\ITaskTypeRepository.cs" />
<Compile Include="Persistence\Repositories\MacroScriptRepository.cs" />
<Compile Include="Persistence\Repositories\MigrationEntryRepository.cs" />
<Compile Include="Persistence\Repositories\PublicAccessRepository.cs" />
<Compile Include="Persistence\Repositories\RedirectUrlRepository.cs" />
<Compile Include="Persistence\Repositories\SimilarNodeName.cs" />
<Compile Include="Persistence\Repositories\UserControlRepository.cs" />
<Compile Include="Persistence\Repositories\XsltFileRepository.cs" />
<Compile Include="Persistence\Repositories\TaskRepository.cs" />
<Compile Include="Persistence\Repositories\TaskTypeRepository.cs" />
@@ -650,6 +657,7 @@
<Compile Include="Services\ContentTypeServiceExtensions.cs" />
<Compile Include="Models\RedirectUrl.cs" />
<Compile Include="Services\IContentServiceBase.cs" />
<Compile Include="Services\IdkMap.cs" />
<Compile Include="Services\RedirectUrlService.cs" />
<Compile Include="Services\DomainService.cs" />
<Compile Include="Services\ExternalLoginService.cs" />
@@ -758,7 +766,6 @@
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwoZero\AddMissingForeignKeyForContentType.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwoZero\AlterDataTypePreValueTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenOneZero\AssignMissingPrimaryForMySqlKeys.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwoZero\AddIndexToUmbracoNodeTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwoZero\RemoveCmsDocumentAliasColumn.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSeven\AssignMissingKeysAndIndexes.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSixTwoZero\AssignMissingPrimaryForMySqlKeys.cs" />
@@ -1182,7 +1189,6 @@
<Compile Include="Persistence\Repositories\RepositoryBase.cs" />
<Compile Include="Persistence\Repositories\ScriptRepository.cs" />
<Compile Include="Persistence\Repositories\ServerRegistrationRepository.cs" />
<Compile Include="Persistence\Repositories\SimilarNodeNameComparer.cs" />
<Compile Include="Persistence\Repositories\StylesheetRepository.cs" />
<Compile Include="Persistence\Repositories\TemplateRepository.cs" />
<Compile Include="Persistence\Repositories\UserRepository.cs" />
+10 -66
View File
@@ -2,12 +2,12 @@
<configuration>
<configSections>
<sectionGroup name="umbracoConfiguration">
<sectionGroup name="umbracoConfiguration">
<section name="FileSystemProviders" type="Umbraco.Core.Configuration.FileSystemProvidersSection, Umbraco.Core" requirePermission="false" />
</sectionGroup>
</configSections>
<umbracoConfiguration>
<FileSystemProviders>
<Provider alias="media" type="Umbraco.Core.IO.PhysicalFileSystem, Umbraco.Core">
@@ -52,7 +52,7 @@
</Provider>
</FileSystemProviders>
</umbracoConfiguration>
<appSettings>
<add key="umbracoConfigurationStatus" value="6.0.0" />
<add key="umbracoReservedUrls" value="~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd" />
@@ -64,7 +64,7 @@
<add key="umbracoDefaultUILanguage" value="en" />
<add key="umbracoUseSSL" value="false" />
</appSettings>
<connectionStrings>
<add name="umbracoDbDSN" connectionString="Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;" providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>
@@ -83,133 +83,77 @@
<compilation defaultLanguage="c#" debug="true" batch="false" targetFramework="4.0"></compilation>
<machineKey validationKey="5E7B955FCE36F5F2A867C2A0D85DC61E7FEA9E15F1561E8386F78BFE9EE23FF18B21E6A44AA17300B3B9D5DBEB37AA61A2C73884A5BBEDA6D3B14BA408A7A8CD" decryptionKey="116B853D031219E404E088FCA0986D6CF2DFA77E1957B59FCC9404B8CA3909A1" validation="SHA1" decryption="AES" />
<!--<trust level="Medium" originUrl=".*"/>-->
<!-- Sitemap provider-->
<siteMap defaultProvider="UmbracoSiteMapProvider" enabled="true">
<providers>
<clear />
<add name="UmbracoSiteMapProvider" type="umbraco.presentation.nodeFactory.UmbracoSiteMapProvider" defaultDescriptionAlias="description" securityTrimmingEnabled="true" />
<add name="UmbracoSiteMapProvider" type="umbraco.presentation.nodeFactory.UmbracoSiteMapProvider, umbraco" defaultDescriptionAlias="description" securityTrimmingEnabled="true" />
</providers>
</siteMap>
</system.web>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="MiniProfiler" publicKeyToken="b44f9351044011a3" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="NuGet.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.11220.104" newVersion="1.0.11220.104" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -9,10 +9,10 @@ namespace Umbraco.Tests.Cache
public class CacheRefresherTests
{
[TestCase("", "123456", "testmachine", true)] //empty hash will continue
[TestCase("fffffff28449cf33", "123456", "testmachine", false)] //match, don't continue
[TestCase("fffffff28449cf33", "12345", "testmachine", true)] // no match, continue
[TestCase("fffffff28449cf33", "123456", "testmachin", true)] // same
[TestCase("fffffff28449cf3", "123456", "testmachine", true)] // same
[TestCase("2e6deefea4444a69dbd15a01b4c2749d", "123456", "testmachine", false)] //match, don't continue
[TestCase("2e6deefea4444a69dbd15a01b4c2749d", "12345", "testmachine", true)] // no match, continue
[TestCase("2e6deefea4444a69dbd15a01b4c2749d", "123456", "testmachin", true)] // same
[TestCase("2e6deefea4444a69dbd15a01b4c2749", "123456", "testmachine", true)] // same
public void Continue_Refreshing_For_Request(string hash, string appDomainAppId, string machineName, bool expected)
{
if (expected)
+1 -1
View File
@@ -6,7 +6,7 @@ using Umbraco.Core;
namespace Umbraco.Tests
{
[TestFixture]
[TestFixture]
public class HashCodeCombinerTests
{
+184
View File
@@ -0,0 +1,184 @@
using System;
using System.IO;
using System.Reflection;
using NUnit.Framework;
using Umbraco.Core;
namespace Umbraco.Tests
{
[TestFixture]
public class HashGeneratorTests
{
private string Generate(bool isCaseSensitive, params string[] strs)
{
using (var generator = new HashGenerator())
{
foreach (var str in strs)
{
if (isCaseSensitive)
generator.AddString(str);
else
generator.AddCaseInsensitiveString(str);
}
return generator.GenerateHash();
}
}
[Test]
public void Generate_Hash_Multiple_Strings_Case_Sensitive()
{
var hash1 = Generate(true, "hello", "world");
var hash2 = Generate(true, "hello", "world");
var hashFalse1 = Generate(true, "hello", "worlD");
var hashFalse2 = Generate(true, "hEllo", "world");
Assert.AreEqual(hash1, hash2);
Assert.AreNotEqual(hash1, hashFalse1);
Assert.AreNotEqual(hash1, hashFalse2);
}
[Test]
public void Generate_Hash_Multiple_Strings_Case_Insensitive()
{
var hash1 = Generate(false, "hello", "world");
var hash2 = Generate(false, "hello", "world");
var hashFalse1 = Generate(false, "hello", "worlD");
var hashFalse2 = Generate(false, "hEllo", "world");
Assert.AreEqual(hash1, hash2);
Assert.AreEqual(hash1, hashFalse1);
Assert.AreEqual(hash1, hashFalse2);
}
private DirectoryInfo PrepareFolder()
{
var assDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
var dir = Directory.CreateDirectory(Path.Combine(assDir.FullName, "HashCombiner", Guid.NewGuid().ToString("N")));
foreach (var f in dir.GetFiles())
{
f.Delete();
}
return dir;
}
[Test]
public void HashCombiner_Test_String()
{
using (var combiner1 = new HashGenerator())
using (var combiner2 = new HashGenerator())
{
combiner1.AddCaseInsensitiveString("Hello");
combiner2.AddCaseInsensitiveString("hello");
Assert.AreEqual(combiner1.GenerateHash(), combiner2.GenerateHash());
combiner2.AddCaseInsensitiveString("world");
Assert.AreNotEqual(combiner1.GenerateHash(), combiner2.GenerateHash());
}
}
[Test]
public void HashCombiner_Test_Int()
{
using (var combiner1 = new HashGenerator())
using (var combiner2 = new HashGenerator())
{
combiner1.AddInt(1234);
combiner2.AddInt(1234);
Assert.AreEqual(combiner1.GenerateHash(), combiner2.GenerateHash());
combiner2.AddInt(1);
Assert.AreNotEqual(combiner1.GenerateHash(), combiner2.GenerateHash());
}
}
[Test]
public void HashCombiner_Test_DateTime()
{
using (var combiner1 = new HashGenerator())
using (var combiner2 = new HashGenerator())
{
var dt = DateTime.Now;
combiner1.AddDateTime(dt);
combiner2.AddDateTime(dt);
Assert.AreEqual(combiner1.GenerateHash(), combiner2.GenerateHash());
combiner2.AddDateTime(DateTime.Now);
Assert.AreNotEqual(combiner1.GenerateHash(), combiner2.GenerateHash());
}
}
[Test]
public void HashCombiner_Test_File()
{
using (var combiner1 = new HashGenerator())
using (var combiner2 = new HashGenerator())
using (var combiner3 = new HashGenerator())
{
var dir = PrepareFolder();
var file1Path = Path.Combine(dir.FullName, "hastest1.txt");
File.Delete(file1Path);
using (var file1 = File.CreateText(Path.Combine(dir.FullName, "hastest1.txt")))
{
file1.WriteLine("hello");
}
var file2Path = Path.Combine(dir.FullName, "hastest2.txt");
File.Delete(file2Path);
using (var file2 = File.CreateText(Path.Combine(dir.FullName, "hastest2.txt")))
{
//even though files are the same, the dates are different
file2.WriteLine("hello");
}
combiner1.AddFile(new FileInfo(file1Path));
combiner2.AddFile(new FileInfo(file1Path));
combiner3.AddFile(new FileInfo(file2Path));
Assert.AreEqual(combiner1.GenerateHash(), combiner2.GenerateHash());
Assert.AreNotEqual(combiner1.GenerateHash(), combiner3.GenerateHash());
combiner2.AddFile(new FileInfo(file2Path));
Assert.AreNotEqual(combiner1.GenerateHash(), combiner2.GenerateHash());
}
}
[Test]
public void HashCombiner_Test_Folder()
{
using (var combiner1 = new HashGenerator())
using (var combiner2 = new HashGenerator())
using (var combiner3 = new HashGenerator())
{
var dir = PrepareFolder();
var file1Path = Path.Combine(dir.FullName, "hastest1.txt");
File.Delete(file1Path);
using (var file1 = File.CreateText(Path.Combine(dir.FullName, "hastest1.txt")))
{
file1.WriteLine("hello");
}
//first test the whole folder
combiner1.AddFolder(dir);
combiner2.AddFolder(dir);
Assert.AreEqual(combiner1.GenerateHash(), combiner2.GenerateHash());
//now add a file to the folder
var file2Path = Path.Combine(dir.FullName, "hastest2.txt");
File.Delete(file2Path);
using (var file2 = File.CreateText(Path.Combine(dir.FullName, "hastest2.txt")))
{
//even though files are the same, the dates are different
file2.WriteLine("hello");
}
combiner3.AddFolder(dir);
Assert.AreNotEqual(combiner1.GenerateHash(), combiner3.GenerateHash());
}
}
}
}
@@ -1,6 +1,4 @@
using System;
using System.Collections.Specialized;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Web.Security;
using Moq;
using NUnit.Framework;
@@ -83,10 +81,10 @@ namespace Umbraco.Tests.Membership
mServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => null);
mServiceMock.Setup(service => service.GetDefaultMemberType()).Returns("Member");
mServiceMock.Setup(
service => service.CreateWithIdentity(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Callback((string u, string e, string p, string m) =>
service => service.CreateWithIdentity(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Callback((string u, string e, string p, string m, bool isApproved) =>
{
createdMember = new Member("test", e, u, p, memberType);
createdMember = new Member("test", e, u, p, memberType, isApproved);
})
.Returns(() => createdMember);
var provider = new MembersMembershipProvider(mServiceMock.Object);
@@ -114,10 +112,10 @@ namespace Umbraco.Tests.Membership
mServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => null);
mServiceMock.Setup(service => service.GetDefaultMemberType()).Returns("Member");
mServiceMock.Setup(
service => service.CreateWithIdentity(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Callback((string u, string e, string p, string m) =>
service => service.CreateWithIdentity(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Callback((string u, string e, string p, string m, bool isApproved) =>
{
createdMember = new Member("test", e, u, p, memberType);
createdMember = new Member("test", e, u, p, memberType, isApproved);
})
.Returns(() => createdMember);
@@ -147,10 +145,10 @@ namespace Umbraco.Tests.Membership
mServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => null);
mServiceMock.Setup(service => service.GetDefaultMemberType()).Returns("Member");
mServiceMock.Setup(
service => service.CreateWithIdentity(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Callback((string u, string e, string p, string m) =>
service => service.CreateWithIdentity(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Callback((string u, string e, string p, string m, bool isApproved) =>
{
createdMember = new Member("test", e, u, p, memberType);
createdMember = new Member("test", e, u, p, memberType, isApproved);
})
.Returns(() => createdMember);
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Moq;
using NUnit.Framework;
@@ -122,7 +123,7 @@ namespace Umbraco.Tests.Persistence.Repositories
//re-get
dictionaryItem = repository.Get(dictionaryItem.Id);
// Assert
Assert.That(dictionaryItem, Is.Not.Null);
@@ -140,10 +141,10 @@ namespace Umbraco.Tests.Persistence.Repositories
// Arrange
var provider = new PetaPocoUnitOfWorkProvider(Logger);
var unitOfWork = provider.GetUnitOfWork();
using (var repository = CreateRepository(unitOfWork))
{
var dictionaryItem = (IDictionaryItem) new DictionaryItem("Testing1235");
var dictionaryItem = (IDictionaryItem) new DictionaryItem("Testing1235");
repository.AddOrUpdate(dictionaryItem);
unitOfWork.Commit();
@@ -160,7 +161,6 @@ namespace Umbraco.Tests.Persistence.Repositories
}
[Test]
public void Can_Perform_GetAll_On_DictionaryRepository()
{
@@ -319,7 +319,7 @@ namespace Umbraco.Tests.Persistence.Repositories
unitOfWork.Commit();
var dictionaryItem = (DictionaryItem)repository.Get(1);
// Assert
Assert.That(dictionaryItem, Is.Not.Null);
Assert.That(dictionaryItem.Translations.Count(), Is.EqualTo(3));
@@ -364,6 +364,24 @@ namespace Umbraco.Tests.Persistence.Repositories
}
}
[Test]
public void Can_Perform_GetDictionaryItemKeyMap_On_DictionaryRepository()
{
Dictionary<string, Guid> keyMap;
var provider = new PetaPocoUnitOfWorkProvider(Logger);
using (var unitOfWork = provider.GetUnitOfWork(readOnly: true))
{
var repository = CreateRepository(unitOfWork);
keyMap = repository.GetDictionaryItemKeyMap();
}
Assert.IsNotNull(keyMap);
Assert.IsNotEmpty(keyMap);
foreach (var kvp in keyMap)
Console.WriteLine("{0}: {1}", kvp.Key, kvp.Value);
}
[TearDown]
public override void TearDown()
{
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using Umbraco.Core.Persistence.Repositories;
namespace Umbraco.Tests.Persistence.Repositories
{
[TestFixture]
public class SimilarNodeNameTests
{
[TestCase("Alpha", "Alpha", 0)]
[TestCase("Alpha", "ALPHA", +1)] // case is important
[TestCase("Alpha", "Bravo", -1)]
[TestCase("Bravo", "Alpha", +1)]
[TestCase("Alpha (1)", "Alpha (1)", 0)]
[TestCase("Alpha", "Alpha (1)", -1)]
[TestCase("Alpha (1)", "Alpha", +1)]
[TestCase("Alpha (1)", "Alpha (2)", -1)]
[TestCase("Alpha (2)", "Alpha (1)", +1)]
[TestCase("Alpha (2)", "Alpha (10)", -1)] // this is the real stuff
[TestCase("Alpha (10)", "Alpha (2)", +1)] // this is the real stuff
[TestCase("Kilo", "Golf (2)", +1)]
[TestCase("Kilo (1)", "Golf (2)", +1)]
public void ComparerTest(string name1, string name2, int expected)
{
var comparer = new SimilarNodeName.Comparer();
var result = comparer.Compare(new SimilarNodeName { Name = name1 }, new SimilarNodeName { Name = name2 });
if (expected == 0)
Assert.AreEqual(0, result);
else if (expected < 0)
Assert.IsTrue(result < 0, "Expected <0 but was " + result);
else if (expected > 0)
Assert.IsTrue(result > 0, "Expected >0 but was " + result);
}
[Test]
public void OrderByTest()
{
var names = new[]
{
new SimilarNodeName { Id = 1, Name = "Alpha (2)" },
new SimilarNodeName { Id = 2, Name = "Alpha" },
new SimilarNodeName { Id = 3, Name = "Golf" },
new SimilarNodeName { Id = 4, Name = "Zulu" },
new SimilarNodeName { Id = 5, Name = "Mike" },
new SimilarNodeName { Id = 6, Name = "Kilo (1)" },
new SimilarNodeName { Id = 7, Name = "Yankee" },
new SimilarNodeName { Id = 8, Name = "Kilo" },
new SimilarNodeName { Id = 9, Name = "Golf (2)" },
new SimilarNodeName { Id = 10, Name = "Alpha (1)" },
};
var ordered = names.OrderBy(x => x, new SimilarNodeName.Comparer()).ToArray();
var i = 0;
Assert.AreEqual(2, ordered[i++].Id);
Assert.AreEqual(10, ordered[i++].Id);
Assert.AreEqual(1, ordered[i++].Id);
Assert.AreEqual(3, ordered[i++].Id);
Assert.AreEqual(9, ordered[i++].Id);
Assert.AreEqual(8, ordered[i++].Id);
Assert.AreEqual(6, ordered[i++].Id);
Assert.AreEqual(5, ordered[i++].Id);
Assert.AreEqual(7, ordered[i++].Id);
Assert.AreEqual(4, ordered[i++].Id);
}
[TestCase(0, "Charlie", "Charlie")]
[TestCase(0, "Zulu", "Zulu (1)")]
[TestCase(0, "Golf", "Golf (1)")]
[TestCase(0, "Kilo", "Kilo (2)")]
[TestCase(0, "Alpha", "Alpha (3)")]
[TestCase(0, "Kilo (1)", "Kilo (1) (1)")] // though... we might consider "Kilo (2)"
[TestCase(6, "Kilo (1)", "Kilo (1)")] // because of the id
public void Test(int nodeId, string nodeName, string expected)
{
var names = new[]
{
new SimilarNodeName { Id = 1, Name = "Alpha (2)" },
new SimilarNodeName { Id = 2, Name = "Alpha" },
new SimilarNodeName { Id = 3, Name = "Golf" },
new SimilarNodeName { Id = 4, Name = "Zulu" },
new SimilarNodeName { Id = 5, Name = "Mike" },
new SimilarNodeName { Id = 6, Name = "Kilo (1)" },
new SimilarNodeName { Id = 7, Name = "Yankee" },
new SimilarNodeName { Id = 8, Name = "Kilo" },
new SimilarNodeName { Id = 9, Name = "Golf (2)" },
new SimilarNodeName { Id = 10, Name = "Alpha (1)" },
};
Assert.AreEqual(expected, SimilarNodeName.GetUniqueName(names, nodeId, nodeName));
}
}
}
@@ -218,15 +218,7 @@ AnotherContentFinder
//ensure they are all found
Assert.IsTrue(plugins.Result.ContainsAll(shouldContain));
}
[Test]
public void PluginHash_From_String()
{
var s = "hello my name is someone".GetHashCode().ToString("x", CultureInfo.InvariantCulture);
var output = PluginManager.ConvertHashToInt64(s);
Assert.AreNotEqual(0, output);
}
[Test]
public void Get_Plugins_Hash()
{
@@ -96,5 +96,25 @@ namespace Umbraco.Tests.PropertyEditors
Assert.AreEqual(expected, result);
}
[TestCase(null, "1", false, 1)]
[TestCase(null, "1", true, 1)]
[TestCase(null, "0", false, 0)]
[TestCase(null, "0", true, 0)]
[TestCase(null, null, false, 0)]
[TestCase(null, null, true, 0)]
[TestCase(null, "-1", false, -1)]
[TestCase(null, "-1", true, -1)]
[TestCase(null, "1.65", false, 1.65)]
[TestCase(null, "1.65", true, 1.65)]
[TestCase(null, "-1.65", false, -1.65)]
[TestCase(null, "-1.65", true, -1.65)]
public void CanConvertDecimalAliasPropertyEditor(Core.Models.PublishedContent.PublishedPropertyType propertyType, object value, bool preview, double expected)
{
var converter = new DecimalValueConverter();
var result = converter.ConvertDataToSource(propertyType, value, preview);
Assert.AreEqual(expected, result);
}
}
}

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