Compare commits

..

395 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
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
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
364 changed files with 9861 additions and 2976 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.3
7.6.6
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.6.3")]
[assembly: AssemblyInformationalVersion("7.6.3")]
[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.3");
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; }
@@ -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);
}
}
}
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
@@ -16,8 +17,16 @@ namespace Umbraco.Tests.PublishedContent
private UmbracoContext ctx;
private string xmlContent = "";
private bool createContentTypes = true;
protected override string GetXmlContent(int templateId)
public override void Initialize()
{
base.Initialize();
// make sure we get them from the content service
PublishedContentType.GetPublishedContentTypeCallback = null;
}
protected override string GetXmlContent(int templateId)
{
return xmlContent;
}
@@ -57,7 +66,7 @@ namespace Umbraco.Tests.PublishedContent
var publishedContent = ctx.ContentCache.GetById(1100);
Assert.That(publishedContent.IsDocumentType("base", true));
}
[Test]
public void IsDocumentType_Recursive_InvalidBaseType_ReturnsFalse()
{
@@ -73,23 +82,23 @@ namespace Umbraco.Tests.PublishedContent
if (createContentTypes)
{
var contentTypeService = ctx.Application.Services.ContentTypeService;
var baseType = new ContentType(-1) {Alias = "base", Name = "Base"};
var baseType = new ContentType(-1) { Alias = "base", Name = "Base" };
const string contentTypeAlias = "inherited";
var inheritedType = new ContentType(baseType, contentTypeAlias) {Alias = contentTypeAlias, Name = "Inherited"};
var inheritedType = new ContentType(baseType, contentTypeAlias) { Alias = contentTypeAlias, Name = "Inherited" };
contentTypeService.Save(baseType);
contentTypeService.Save(inheritedType);
createContentTypes = false;
}
#region setup xml content
xmlContent = @"<?xml version=""1.0"" encoding=""utf-8""?>
<!DOCTYPE root[
<!DOCTYPE root[
<!ELEMENT inherited ANY>
<!ATTLIST inherited id ID #REQUIRED>
]>
<root id=""-1"">
<inherited id=""1100"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""1"" sortOrder=""1"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Home"" urlName=""home"" writerName=""admin"" creatorName=""admin"" path=""-1,1046"" isDoc=""""/>
</root>";
#endregion
}
}
}

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