Compare commits

...

1010 Commits

Author SHA1 Message Date
Mads Rasmussen 33e6db98cd add client files for script editor 2017-01-10 11:10:43 +01:00
Shannon 77d47f0b28 fixes error with server side validation + data tyep editor, ensures template controller and data type controller inherit from BackOfficeNotificationsController, ensures BackOfficeNotificationsController is attributed with PrefixlessBodyModelValidator 2017-01-10 12:29:30 +11:00
Shannon d66c57cfd0 Ensures that the Name field shows validation correctly with server side validation - needs Mads to verify this is ok. 2017-01-10 12:05:48 +11:00
Per Ploug 12e48d069b Fixes issue with DateTime values and strongly typed queries 2017-01-05 11:34:38 +01:00
Per Ploug dbdb1cbd06 Merge branch 'temp-template-editor' of https://github.com/umbraco/Umbraco-CMS into temp-template-editor 2017-01-05 08:45:28 +01:00
Per Ploug 8b479b57e5 Change query condition from name to alias 2017-01-05 08:45:04 +01:00
Warren Buckley 663b0f3931 Merge pull request #1674 from umbraco/temp-U4-9338
fixes: U4-9338 Add focus to code editor on load and after closing dia…
2017-01-04 15:17:13 +00:00
Mads Rasmussen 18d8223d7e fixes: U4-9338 Add focus to code editor on load and after closing dialogs 2017-01-04 13:04:48 +01:00
Warren Buckley 1a215f3176 Merge pull request #1648 from umbraco/temp-U4-9273
Fixes: U4-9273 Add date picker to query builder
2017-01-04 11:16:10 +00:00
Mads Rasmussen ddad642a88 fix callbacks 2017-01-04 10:45:40 +01:00
Mads Rasmussen 339957bd91 remove unnecessary dependencies 2017-01-04 10:43:56 +01:00
Per Ploug 051801f337 Couple of copy updates for the render section 2017-01-03 13:10:54 +01:00
Shannon Deminick 46922dd259 Merge pull request #1664 from umbraco/temp-U4-9328
Fixes: U4-9328 UI: It shouldn’t be possible to select the current tem…
2017-01-03 14:41:28 +11:00
Shannon Deminick e2adb25da0 Merge pull request #1665 from umbraco/temp-U4-9325
fixes: U4-9325 New template editor stays in a $dirty state if you cha…
2017-01-03 14:38:30 +11:00
Mads Rasmussen 5146658e0f fixes: U4-9325 New template editor stays in a $dirty state if you change and then save 2017-01-02 13:03:15 +01:00
Mads Rasmussen dece680221 Fixes: U4-9328 UI: It shouldn’t be possible to select the current template or the selected master template in the master template picker. 2016-12-30 11:36:20 +01:00
Mads Rasmussen 48ee9d6b0e Merge pull request #1663 from umbraco/temp-U4-9274
fixes: U4-9274 Master template is not saved
2016-12-30 10:53:10 +01:00
Shannon 3e82a48f4d Fixes tree syncing and fixes server side code to reset the master template if it's cleared 2016-12-30 11:38:27 +11:00
Shannon bd448ef05a U4-9326 Removing a master template from a Template does not update the Template's path correctly 2016-12-30 11:27:55 +11:00
Mads Rasmussen 82efa14b7a add UI to remove master template 2016-12-29 13:50:57 +01:00
Mads Rasmussen 61f25edafc sync tree 2016-12-29 13:50:11 +01:00
Shannon 436875e8ec fixes null check with setting master template 2016-12-29 14:02:15 +11:00
Shannon ac087a87d3 Merge branch 'refs/heads/dev-v7.6' into temp-template-editor 2016-12-29 13:58:14 +11:00
Shannon 903ce09426 Merge remote-tracking branch 'refs/remotes/origin/dev-v7' into dev-v7.6
# Conflicts:
#	build/UmbracoVersion.txt
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
2016-12-29 13:57:55 +11:00
Shannon 02dc510078 Merge branch 'refs/heads/dev-v7.6' into temp-template-editor 2016-12-29 13:56:11 +11:00
Shannon ffefe417db bumps version 2016-12-29 12:23:30 +11:00
Per Ploug 00adffc8b3 Merge remote-tracking branch 'origin/temp-template-editor' into temp-template-editor
# Conflicts:
#	src/Umbraco.Web/Editors/TemplateQueryController.cs
#	src/Umbraco.Web/Models/TemplateQuery/QueryCondition.cs
2016-12-29 02:16:58 +01:00
Per Ploug 2ec3278637 Merge remote-tracking branch 'refs/remotes/origin/dev-v7' into temp-template-editor 2016-12-29 01:51:10 +01:00
Per Ploug 1f52a0c186 Changes the querybuilder to use the correct Where syntax 2016-12-29 01:50:43 +01:00
Shannon 40f7d820a6 publicizes a few APIs and adds more API docs 2016-12-29 11:36:39 +11:00
mikkelhm 19f7e6bd88 When Querying we need to use the Alias to search for, in stead of the name, this is due to names like "Created Date" and "Last Updated Date", who has aliases like "CreateDate", and "UpdateDate" 2016-12-28 14:07:22 +01:00
mikkelhm dea3553885 Change back to using CurrentPage.Site() when queuing with the Query Builder, as Model.Content.Site(), doesnt support the queries the Query Builder creates 2016-12-28 14:04:40 +01:00
Shannon d83d23803a fixes build 2016-12-28 19:11:45 +11:00
Shannon fae5dd517e bumps version to next alpha 2016-12-28 18:57:25 +11:00
Shannon 247c96ac6e makes public the MigrationBase.Context property 2016-12-28 17:22:36 +11:00
Shannon Deminick 360e06bbc5 Merge pull request #1660 from umbraco/deploy-157
deploy-157 - simplify tables creation in migrations
2016-12-28 15:51:04 +11:00
Mikkel Holck Madsen 2d94ac7a19 Merge pull request #1658 from umbraco/temp-U4-9199
Fixes: U4-9199 Grid RTE (rich text editor/ tinyMCE) does not have a m…
2016-12-27 14:45:42 +01:00
Stephan ef48baf7ae deploy-157 - simplify tables creation in migrations 2016-12-23 10:31:14 +01:00
Shannon 8e06a88a2c bumps version, publicizes method 2016-12-23 14:52:18 +11:00
Shannon Deminick 6898d9b270 Merge pull request #1657 from umbraco/temp-u4-9250
U4-9250 - Guid all the Macros
2016-12-23 10:24:12 +11:00
Shannon 0aa8a5c243 more whitespace fixing 2016-12-23 09:41:23 +11:00
Shannon c5326fc5c9 fixes whitespace in version file 2016-12-23 09:31:54 +11:00
Mads Rasmussen 4c97c689e9 Fixes: U4-9199 Grid RTE (rich text editor/ tinyMCE) does not have a max height, causing the user to have to scroll up to see RTE menu buttons 2016-12-22 14:06:23 +01:00
Stephan 9431e878f3 Version 7.6.0-alpha035 2016-12-22 11:34:33 +01:00
Stephan 3ac71a37e8 U4-9250 - add more tests 2016-12-22 11:24:01 +01:00
Stephan 0ac5e0daf4 U4-9250 - rename GetAllAll method - yea that was bad 2016-12-22 11:14:09 +01:00
Stephan f3a7ada586 U4-9250 - add keys to ctors 2016-12-22 11:10:45 +01:00
Mads Rasmussen d835008c67 Fixes: U4-9275 Show correct render section in “Sections” dialog 2016-12-22 10:57:07 +01:00
Shannon bd4f3ad0d9 bumps umb version so the build works. 2016-12-22 18:44:47 +11:00
Shannon 8083edddb9 Adds check to DetermineInstalledVersion to detect if it's 7.6 based on the new DB changes 2016-12-22 16:36:25 +11:00
Shannon 886942c4e8 Updated MacroServiceTests to include testing for the Key 2016-12-22 15:24:54 +11:00
Stephan 7576c8138e U4-9250 - fix tests 2016-12-21 16:47:32 +01:00
Mads Rasmussen 296adf70b4 remove lorem ipsum 2016-12-21 16:15:26 +01:00
Stephan b3a6c70ae7 U4-9250 - revert some changes 2016-12-21 15:34:17 +01:00
Stephan ef28173511 U4-9250 - fixes 2016-12-21 15:23:23 +01:00
Stephan b25cb9995f U4-9250 - Guid the IMacroService 2016-12-21 15:23:22 +01:00
Stephan 38e8e1cf9c U4-9250 - fix migration 2016-12-21 15:23:22 +01:00
Stephan f25641b2a7 U4-9250 - Guid all the Macros 2016-12-21 15:23:22 +01:00
Mads Rasmussen 4101a1cb17 add umbraco version number to umbdatepicker docs 2016-12-21 14:04:59 +01:00
Mads Rasmussen 4911c2718c add better spacing between filters 2016-12-21 13:51:01 +01:00
Mads Rasmussen aa5ad746eb fix issue with date not updating properly 2016-12-21 13:00:45 +01:00
Sebastiaan Janssen c88ee55e8d Merge pull request #1656 from umbraco/temp-u4-9240
U4-9240 - kill umbracoDeployChecksum
2016-12-21 09:14:10 +01:00
Sebastiaan Janssen f2f4c23c80 Merge pull request #1652 from umbraco/U4-9301
Updates login controller to not accept non local urls
2016-12-20 13:55:31 +01:00
Stephan 01340e0316 U4-9240 - kill umbracoDeployChecksum 2016-12-20 11:26:34 +01:00
Claus 67ea15706e Merge pull request #1651 from umbraco/temp-U4-9282
U4-9282 Rollback not working
2016-12-20 11:24:05 +01:00
Claus 5cc75b8cc3 Merge pull request #1654 from umbraco/temp-U4-9302
U4-9302 Add logging of non security related connection string details…
2016-12-20 11:01:50 +01:00
Claus 653ac66ff3 Merge pull request #1653 from umbraco/temp-U4-9262
U4-9262 CleanForXss breaks rgba() values set as grid background color…
2016-12-20 10:32:36 +01:00
Shannon 3f7e593bc2 U4-9302 Add logging of non security related connection string details when the connection fails 2016-12-20 14:10:06 +11:00
Shannon 39505cd868 U4-9262 CleanForXss breaks rgba() values set as grid background color style 2016-12-20 13:27:53 +11:00
Shannon 0daaa3e785 Revert "Merge pull request #1618 from AliSheikhTaheri/U4-9180"
This reverts commit 4050a375bc, reversing
changes made to a058f26462.
2016-12-20 12:28:45 +11:00
Shannon Deminick 4050a375bc Merge pull request #1618 from AliSheikhTaheri/U4-9180
U4-9180 Optimise Log4net
2016-12-20 11:08:11 +11:00
Niels Hartvig da27108d0d Updates login controller to not accept non local urls 2016-12-19 10:44:22 +01:00
hartvig a058f26462 Update README.md 2016-12-19 09:20:21 +01:00
Shannon c8f0f05570 U4-9246 Should ship with numRecompilesBeforeAppRestart="50" to avoid max recompilations reached errors 2016-12-19 17:10:29 +11:00
Shannon 347ed2896a U4-9282 Rollback not working 2016-12-19 16:58:24 +11:00
Shannon 5c40a1f9e9 bumps version 2016-12-19 16:42:05 +11:00
Mads Rasmussen 219f855d86 remove unused then from promise 2016-12-15 14:57:06 +01:00
Mads Rasmussen 46c4f9d3a1 add support for hide, show and update events 2016-12-15 14:39:40 +01:00
Per Ploug 17011a1e76 Fixes issue with saving master 2016-12-15 13:55:59 +01:00
Per Ploug 9ceb5305d5 Enables sections to wrapped around selected code 2016-12-15 13:55:45 +01:00
Per Ploug c8a92434af Fixes issue with inserting macros + updates the dialog ui 2016-12-15 13:55:26 +01:00
Per Ploug 9aea19cee5 Updates copy in dialogs 2016-12-15 13:54:54 +01:00
Per Ploug 0c0c60b83f Fixes: U4-9276 update copy in insert dialog 2016-12-15 09:28:48 +01:00
Shannon 7254db40eb publicizes ExamineExtensions.ConvertSearchResultToPublishedContent 2016-12-15 17:44:32 +11:00
Shannon 04481c33e7 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-12-15 10:45:57 +11:00
Shannon 4c107470c3 updates some angular docs 2016-12-15 10:43:53 +11:00
Mads Rasmussen df10358088 Fix weird looking save and publish button group in content section 2016-12-13 11:53:41 +01:00
Mads Rasmussen 7cbfe01c0b use umbDateTimePicker component in query builder 2016-12-13 10:58:24 +01:00
Stephan 4863052a08 Revert "deploy-11 - implement DeployVersionAttribute"
This reverts commit f51a086137.
2016-12-13 10:58:19 +01:00
Mads Rasmussen e97e8caab8 add umbDateTimePicker component 2016-12-13 10:57:19 +01:00
Stephan cb09681cb0 Merge remote-tracking branch 'origin/dev-v7' into dev-v7.6 2016-12-13 10:36:33 +01:00
Stephan b9b7c9f965 More database fixing (sqlCE) 2016-12-13 10:35:37 +01:00
Warren Buckley 4b39f490f3 Merge pull request #1602 from cheeseytoastie/U4-9148_-_Splash_screen_apostophe_typo
U4-9148 noNodes Splash screen apostrophe char typo fixed (in "Be a pa…
2016-12-09 13:32:53 +00:00
Sebastiaan Janssen c607ceda48 Merge pull request #1557 from tompipe/U4-9127-SortMemberProperties
Fixed issue with member properties sort order
2016-12-09 08:59:52 +01:00
Claus d4acd4629a Merge pull request #1646 from umbraco/temp-U4-9259
Lazily creates the static queries instead of eagerly, this fixes an i…
2016-12-08 10:09:32 +01:00
Shannon b413b7b5af Lazily creates the static queries instead of eagerly, this fixes an issue of if these services are accessed before Umbraco has booted 2016-12-08 12:48:44 +11:00
Stephan 0415e910dc Merge pull request #1645 from umbraco/temp-U4-9255
U4-9255 Not having access to settings section causes backoffice user …
2016-12-07 13:06:24 +01:00
Claus 960040e51e U4-9255 Not having access to settings section causes backoffice user to be logged out when browsing media list views 2016-12-07 12:57:29 +01:00
Emil Wangaa 5936f72263 Merge pull request #1643 from umbraco/temp-u4-9249
U4-9249 - fix member type standard properties
2016-12-07 12:25:01 +01:00
Stephan ba27c7e8e8 U4-9249 - fix member type standard properties 2016-12-06 15:46:17 +01:00
Stephan b4ef37a61a More database fixing 2016-12-05 16:39:20 +01:00
Stephan 6c4185dc01 Version 7.6.0-alpha032 2016-12-05 12:13:11 +01:00
Stephan f51a086137 deploy-11 - implement DeployVersionAttribute 2016-12-05 11:58:17 +01:00
Stephan b8ff4a5906 Merge remote-tracking branch 'origin/dev-v7' into dev-v7.6 2016-12-05 11:58:00 +01:00
Sebastiaan Janssen f48ba93a01 Merge pull request #1639 from umbraco/temp-htmlencode-tags
Ensures tag values are Html encoded both on the client side and on th…
2016-12-05 08:10:41 +01:00
Shannon 4823235bf5 Ensures the cleaned value isn't double html encoded 2016-12-05 17:21:24 +11:00
Shannon 90f30c3f3c Ensures tag values are Html encoded both on the client side and on the server side to prevent any xss 2016-12-05 17:13:07 +11:00
Stephan f79e63a13b Fix background-thread-safe database usage 2016-12-02 18:15:42 +01:00
Stephan b0aae7248c Import DatabaseDebugHelper (disabled) 2016-12-02 18:15:16 +01:00
Stephan 467b12491c Merge dev-v7 into dev-v7.6 2016-12-02 12:01:31 +01:00
Stephan 22397ded9b Be more tolerant with Xml cache document 2016-12-02 11:53:37 +01:00
Stephan de1da4b060 Merge pull request #1635 from umbraco/temp-startuphandler-ordering
This allows for sorting startup handlers and modifying the list of startup handlers before they execute
2016-12-02 11:48:57 +01:00
Stephan b7240f2048 Merge 2016-12-02 08:47:36 +01:00
Stephan 13f7f96101 Refactor app event resolver weights 2016-12-02 08:45:36 +01:00
Shannon 006ee00527 Ensures that all weight's for startup handlers that are in a Core namespace have a -100 default applied, all public ones by default will have 100 applied. Allows for developers to use the reserved negative numbers if they must - but we need to doc this! 2016-12-02 13:05:45 +11:00
Stephan 3e8f85a4b4 Be more tolerant with Xml cache document 2016-12-01 14:30:50 +01:00
Mads Rasmussen 286907b89e fix unit tests 2016-11-30 12:13:04 +01:00
Mads Rasmussen bd0c1cd932 clean up umb-era-button + add button style to template editor buttons 2016-11-30 10:38:04 +01:00
Mads Rasmussen daaa2bf911 replace yellow buttons in query builder with blue 2016-11-29 15:24:02 +01:00
Stephan bdb6b48e3f Merge remote-tracking branch 'origin/dev-v7' into dev-v7.6 2016-11-28 13:08:22 +01:00
Stephan 8305a1acd3 Merge pull request #1636 from umbraco/temp-U4-9222
U4-9222 The in memory XML cache is cloned everytime there is a content save even if there is nothing published
2016-11-28 13:06:11 +01:00
Stephan 309081cccf Merge branch origin/dev-v7 into temp-U4-9222 2016-11-28 13:06:06 +01:00
Stephan f97bc0fbb6 Merge origin/dev-v7 into dev-v7.6 2016-11-28 12:57:20 +01:00
Stephan f7aee1c12f Version 7.6.0-alpha031 2016-11-28 12:49:55 +01:00
Shannon 1221c0e416 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-11-28 12:04:06 +01:00
Shannon c505cc689b Obsoletes access to ApplicationContext from UmbracoContext 2016-11-28 12:03:46 +01:00
Stephan 48dbd5c570 Ensure CacheRefresherEventHandler triggers first 2016-11-28 11:00:58 +01:00
Sebastiaan Janssen 51397d7c28 Merge branch 'dev-v7' into dev-v7.6 2016-11-28 10:49:37 +01:00
Shannon Deminick 69a8cb71ea Merge pull request #1628 from umbraco/temp-u4-9201
temp-u4-9201
2016-11-28 10:42:37 +01:00
Stephan 184a01b64d U4-9201 - fixes 2016-11-28 10:09:45 +01:00
Stephan 86cc3f69aa Merge pull request #1637 from umbraco/temp-sqlhelper-usings
Refactor all usages of SqlHelper, ExecuteReader and ExecuteXmlReader …
2016-11-28 10:05:48 +01:00
Stephan 3a216c055e U4-9222 - use HasPublishedVersion test 2016-11-28 09:52:45 +01:00
Sebastiaan Janssen ee3a4614c3 Refactor all usages of SqlHelper, ExecuteReader and ExecuteXmlReader into using blocks 2016-11-26 18:02:57 +01:00
Stephan bb9bc73daa Merge remote-tracking branch 'origin/dev-v7' into temp-startuphandler-ordering 2016-11-25 18:53:58 +01:00
Shannon 5b5e1847eb Updates legacy CMSNode and Document to use the PetaPoco Database intead of SqlHelper for the methods that the xml cache uses to update itself (so it's using one connection) 2016-11-25 18:08:18 +01:00
Shannon eeb94e1668 U4-9222 The in memory XML cache is cloned everytime there is a content save even if there is nothing published 2016-11-25 18:07:27 +01:00
Shannon 14bf4bbd32 throws exception if the delegate is already set 2016-11-25 15:55:33 +01:00
Shannon 0e61d18b9e Ensure core handlers are always first no matter what 2016-11-25 15:53:08 +01:00
Shannon 531fa9f25a Ensures the delegate cannot be set once the event handlers are resolved. 2016-11-25 14:34:04 +01:00
Shannon a44a670f50 Removed the IApplicationEventsFilter interface, adds a delegate property that can be set instead 2016-11-25 14:14:43 +01:00
Shannon 81750c41bd Removes events for filtering and instead use a special interface to perform the filtering, updates ctor for WeightAttribute to only accept positive numbers for public, internally it could be negative numbers, updates the filtering to always ensure that core handlers are at the beginning 2016-11-25 10:35:36 +01:00
Stephan 672568d1f5 Add missing file 2016-11-24 18:16:14 +01:00
Stephan 0179540023 Rename WeightAttribute, change default to 100, cleanup 2016-11-24 18:13:05 +01:00
Shannon ed37b84b3b makes public the WeightedPluginAttribute, uses this for resolving the startup handlers so they could be sorted, adds special event to allow modifying the startup handlers. 2016-11-24 11:20:01 +01:00
Stephan 0689bf4f31 U4-9201 - fix it all 2016-11-23 15:26:41 +01:00
Sebastiaan Janssen 47c8e6854e Fixes: U4-9217 - Sanitize tags before storing them in the database 2016-11-23 14:24:26 +01:00
Stephan 3300dbbe5e Merge branch 'dev-v7.6' into temp-u4-9201 2016-11-23 11:56:53 +01:00
Stephan 5784ea96e7 UnRevert "Backport SafeCallContext, DefaultDatabaseFactory fixes from 7.6"
This reverts commit 8ba6cb3abf.
2016-11-23 11:26:30 +01:00
Stephan a77763ee89 Merge origin/dev-v7 into dev-v7.6 2016-11-23 11:03:52 +01:00
Stephan 1def61432e U4-9216 - fix saving containers 2016-11-23 10:58:52 +01:00
Shannon e9b2175506 Fixes null check problem in ExamineEvents.ContentTypeCacheRefresherCacheUpdated 2016-11-22 15:16:07 +01:00
Sebastiaan Janssen a2a4ad3947 Fixes U4-9212 2016-11-22 14:31:29 +01:00
Sebastiaan Janssen d95f818e43 Fixes U4-9212 2016-11-22 14:04:31 +01:00
Sebastiaan Janssen 64978dbe89 Merge pull request #1560 from mikkelhm/dev-v7
U4-9209 - Updates web.config.install.xdt to re-add the assemblyBinding for Html…
2016-11-21 22:54:49 +01:00
Sebastiaan Janssen 77e9643a09 Update NuGet CDF dependency 2016-11-21 08:17:18 +01:00
Stephan ef409298e8 Merge branch 'dev-v7.6' into temp-u4-9201 2016-11-18 15:23:47 +01:00
Shannon 17316363f1 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-11-18 14:34:50 +01:00
Shannon 0e57d558f6 updates cdf version 2016-11-18 14:34:31 +01:00
Claus f23247cd85 Merge pull request #1627 from umbraco/temp-U4-9185
U4-9185 lastLockoutDate does not get set when too many invalid passwo…
2016-11-18 14:13:29 +01:00
Shannon 93ee850bcc publicize 2 events on UmbracoModule 2016-11-18 13:48:18 +01:00
Shannon 8ba6cb3abf Revert "Backport SafeCallContext, DefaultDatabaseFactory fixes from 7.6"
This reverts commit 59ace3d881.
2016-11-18 13:38:49 +01:00
Stephan bad0d15c1c U4-9201 - troubleshoot 2016-11-18 13:32:56 +01:00
Sebastiaan Janssen a266a22daf Merge pull request #1629 from dampee/patch-1
readme.md : remove spaces behind ##
2016-11-18 10:57:24 +01:00
Damiaan c4d36f06f8 remove spaces behind ##
the github markdown will show ## at the end of the line if it is followed by a space
2016-11-18 10:47:32 +01:00
Stephan 35aac2cdec Merge origin/dev-v7 into dev-v7.6 2016-11-18 09:52:45 +01:00
Stephan 6101b4edde U4-9201 - use UsingSafeDatabase where appropriate 2016-11-18 09:43:10 +01:00
Stephan 13ed3757da U4-9201 - properly manage database instances 2016-11-18 09:43:10 +01:00
Stephan d086244820 U4-9201 - expose PetaPoco Database type + dispose 2016-11-18 09:43:00 +01:00
Shannon Deminick 78a2a4a55b Merge pull request #1624 from umbraco/temp-u4-9195
U4-9195 - fix PetaPoco page of int
2016-11-17 17:06:02 +01:00
Shannon a70f37a53e U4-9185 lastLockoutDate does not get set when too many invalid password attempts are made 2016-11-17 16:46:06 +01:00
Mads Rasmussen 597a10fc5d small fixes to overlay buttons + insert order 2016-11-17 10:33:15 +01:00
Mads Rasmussen 1a80e94bca clean up insert field overlay 2016-11-17 09:31:35 +01:00
Sebastiaan Janssen 0a883ae109 Make sure Umbraco runs in Visual Studio 2017 2016-11-16 18:55:12 +01:00
Stephan 568a4987e3 U4-9195 - fix PetaPoco page of int 2016-11-16 17:51:00 +01:00
Warren Buckley 02bfe3ad72 Merge pull request #1603 from rjabreu/U4-9036
added finish button so page only reloads after user input. also added…
2016-11-16 16:14:53 +00:00
Stephan 27eaa8d4af Inject filesystems into partial repositories 2016-11-16 15:19:15 +01:00
Shannon Deminick 3eba4f462f Merge pull request #1619 from umbraco/temp-u4-6994
U4-6994 - N+1 queries
2016-11-16 13:46:22 +01:00
Shannon Deminick 55f3d72cc8 Merge pull request #1543 from umbraco/temp-u4-9108
U4-9018 - provide a way to disable server master election
2016-11-16 13:10:16 +01:00
Shannon Deminick e0eb8473ee Merge pull request #1454 from umbraco/dev-v7-deploy
U4-8909 - Merge dev-v7-deploy into dev-v7
2016-11-16 13:06:41 +01:00
Mads Rasmussen 6c5d2c8057 fix header 2016-11-16 12:22:03 +01:00
Mads Rasmussen c3fc21a2b3 remove organise overlay 2016-11-16 12:21:52 +01:00
Mads Rasmussen 2596043a94 restructure organize overlay so master template picker is available in the editor and sections are in their own dialog 2016-11-16 11:19:57 +01:00
Sebastiaan Janssen 2fa2cc1574 Merge pull request #1622 from umbraco/temp-U4-9188
U4-9188 Remove unnecessary duplicate index IX_cmsPropertyData
2016-11-16 10:18:21 +01:00
Stephan 7ea156d422 IEventMessagesFactory without HttpContext 2016-11-16 09:57:24 +01:00
Shannon 95f5773046 U4-9188 Remove unnecessary duplicate index IX_cmsPropertyData 2016-11-16 08:23:53 +01:00
Stephan 28fe2f7d22 Merge remote-tracking branch 'origin/dev-v7' into dev-v7-deploy 2016-11-15 18:43:14 +01:00
Stephan 289d7a01d8 Fix BulkInsert, was rolling back 2016-11-15 18:41:03 +01:00
Sebastiaan Janssen 47dbb648fb Merge pull request #1614 from umbraco/temp-u4-9077
U4-9077 - relation type repository cache
2016-11-15 18:30:01 +01:00
Stephan 0478f01113 Fix merge 2016-11-15 14:08:30 +01:00
Stephan ddf29c5875 Merge dev-v7.6 into dev-v7-deploy 2016-11-15 13:59:19 +01:00
Stephan ad82270dcc Merge branch origin/dev-v7 into dev-v7.6 2016-11-15 13:48:01 +01:00
Stephan 6c8a033a56 Fix build.bat 2016-11-15 13:46:49 +01:00
Stephan e499f2d148 U4-9108 - add missing change 2016-11-15 13:44:44 +01:00
Stephan 62325f0a27 Merge branch origin/dev-v7 into temp-u4-9108 2016-11-15 13:34:13 +01:00
Shannon Deminick ff499bff04 Merge pull request #1607 from umbraco/temp-u4-backport
U4-8909 backport from 7.6
2016-11-15 13:11:05 +01:00
Sebastiaan Janssen 26a04ca7e9 Merge pull request #1610 from umbraco/temp-U4-9134
U4-9134 XSS security issue in the grid
2016-11-15 12:56:21 +01:00
Claus 6f39439e3d removing string.empty checks for attributes.
removing the redundant clean for outputting model.value in TextString.cshtml.
2016-11-15 12:10:36 +01:00
Claus 34d4b284fe Merge pull request #1613 from umbraco/temp-U4-7833
U4-7833 Changing doc type results in invalid cache, lucene indexes, e…
2016-11-15 11:14:56 +01:00
Mads Rasmussen 44ff0e16e6 add titles in insert dialog 2016-11-15 09:43:58 +01:00
Mads Rasmussen c00120bb9a set font size to 14px 2016-11-15 09:43:28 +01:00
Stephan d800a4198d fix meh 2016-11-15 09:14:55 +01:00
Mads Rasmussen 1f3d305a55 remove $scope watch 2016-11-14 20:20:03 +01:00
Mads Rasmussen addad5b7dc fix http request 2016-11-14 19:57:55 +01:00
Mads Rasmussen 22204a62d4 move http requests to resource file 2016-11-14 19:22:49 +01:00
Stephan 9d2fb0dd03 Fix after merges 2016-11-14 19:01:44 +01:00
Stephan a5695b71eb Merge pull request #1553 from umbraco/temp-U4-9105
U4-9105 SPIKE: Ensure our Lambda expression tree parsers at our service layer are not performance bottlenecks
2016-11-14 18:58:16 +01:00
Stephan 2b9ffdb6b9 Merge branch origin/dev-v7 into dev-v7-deploy 2016-11-14 18:53:53 +01:00
Stephan 539e7c80bf Merge branch origin/dev-v7 into temp-U4-9105 2016-11-14 18:45:56 +01:00
Stephan cfc1704c64 Fix build after merge 2016-11-14 18:33:16 +01:00
Stephan bbe1cb1813 Merge branch origin/dev-v7 into temp-u4-6994 2016-11-14 18:31:36 +01:00
Stephan feb120cbeb Merge branch 'dev-v7' into temp-u4-6994 2016-11-14 18:20:06 +01:00
Stephan 2bc07ad4cc Merge branch 'dev-v7' into temp-U4-9105 2016-11-14 18:13:45 +01:00
Sebastiaan Janssen 1c036b1a11 Merge pull request #1562 from umbraco/temp-u4-9136
Temp u4 9136
2016-11-14 18:04:37 +01:00
Stephan f5fe07ffb7 U4-6994 - more N+1 and refactoring 2016-11-14 17:52:40 +01:00
Shannon 213f02cbc6 Revert "U4-7833 Changing doc type results in invalid cache, lucene indexes, etc..."
This reverts commit 3deda7efab.
2016-11-14 17:39:46 +01:00
Shannon 2de465e8f3 Ensures that indexes are rebuild for items that have had their content type's or property type's aliases changed, also ensures that the content refresher kicks in if a property type alias has changed (this wasn't previously being done) 2016-11-14 17:39:28 +01:00
Sebastiaan Janssen 5b714572e3 Bump version 2016-11-14 17:04:55 +01:00
Sebastiaan Janssen 8e95acb4c5 Merge pull request #1561 from umbraco/temp-U4-9132
U4-9132 Macros from packages are empty when restored
2016-11-14 17:02:07 +01:00
Sebastiaan Janssen 0439e5782e Merge pull request #1542 from umbraco/temp-u4-9115
U4-9115 - move locks to umbracoLocks table
2016-11-14 16:18:48 +01:00
Sebastiaan Janssen 740abb1426 We don't support C# 6 yet 2016-11-14 16:18:20 +01:00
Stephan df12f19c53 U4-9115 - fix issue 2016-11-14 16:08:21 +01:00
Sebastiaan Janssen 9c40218f48 Merge pull request #1551 from umbraco/temp-U4-9104
U4-9104 Update the UmbracoExamine logic for Media to read the data di…
2016-11-14 15:41:31 +01:00
Sebastiaan Janssen 714b7019c5 Fix unit tests to have the correct types as well 2016-11-14 15:38:50 +01:00
Sebastiaan Janssen 935d010dd2 The foreach is actually more readable 2016-11-14 15:26:25 +01:00
Sebastiaan Janssen 199c502396 Get the correct types 2016-11-14 15:24:41 +01:00
Mads Rasmussen 9470892118 query builder overlay: use overlay directive instead of dialogservice to open contentPicker 2016-11-14 13:21:42 +01:00
Mads Rasmussen 91b925f95c change white-space on pre elements so line wraps 2016-11-14 13:07:26 +01:00
Mads Rasmussen b3e9617aff query builder overlay first refactor: use controllerAs syntax + move css to .less file instead of inline + fix indention 2016-11-14 13:06:45 +01:00
Ali Sheikh Taheri 19b24b5109 Added maximum number of backups to keep. 2016-11-14 11:56:21 +00:00
Ali Sheikh Taheri 3aaa33ebe9 added .log file extension for backup logs. 2016-11-14 11:55:09 +00:00
Ali Sheikh Taheri 4ae7a32e29 Fix for maximum file size. 2016-11-14 11:54:42 +00:00
Mads Rasmussen d7aeae3d26 bind open partial view overlay function to view model 2016-11-14 11:16:53 +01:00
Mads Rasmussen f6d8a980a6 Merge branch 'dev-v7' into temp-template-editor
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/less/belle.less
#	src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html
#	src/Umbraco.Web/Umbraco.Web.csproj
2016-11-14 11:04:15 +01:00
Claus f2c406f168 Merge pull request #1572 from umbraco/temp-U4-4196-gkonings-html5-dropzone
U4-4196 U7 - Umbraco HTML5 Drop Zone should honor media types
2016-11-14 09:59:22 +01:00
Claus 2115367353 updating the migration to include only needed ids.
formatting stuff in js.
2016-11-14 09:57:17 +01:00
Claus 9e24b694b3 adding migration to retain functionality as it has always been in root when upgrading. 2016-11-10 13:09:22 +01:00
Claus 4f5bc9eb89 updating MediaController with AutoSelect option. 2016-11-10 12:36:52 +01:00
Mads Rasmussen f9d8754d88 add support for one custom media type 2016-11-10 12:00:07 +01:00
Mads Rasmussen 07c2a14321 If there is only 1 allowed media type set the alias to auto to let the server decide 2016-11-10 11:13:00 +01:00
Mads Rasmussen e77bddd0f2 add filtering of media types 2016-11-10 11:08:28 +01:00
Stephan 42522f5af3 U4-6994 - remove N+1 in ContentRepository.GetByPublishedVersion, .GetAllVersions 2016-11-09 17:21:14 +01:00
Stephan 5c3d605d34 U4-9077 - in addition, deal with N+1 for relations 2016-11-09 15:33:28 +01:00
Claus 3deda7efab U4-7833 Changing doc type results in invalid cache, lucene indexes, etc...
For now: add messages in the UI to tell people they need to publish the items again and rebuilt their indexes.
2016-11-09 13:09:31 +01:00
Stephan b441c73604 U4-9077 - relation type cache refresher + policy 2016-11-09 13:05:23 +01:00
Claus df59596775 Merge branch 'crgrieve-U4-4410' into dev-v7 2016-11-09 11:49:20 +01:00
Claus cdb0c57416 readding the fix crgrieve did for treepicker.controller.js. 2016-11-09 11:48:32 +01:00
Claus 0749c6865d Merge branch 'U4-4410' of git://github.com/crgrieve/Umbraco-CMS into crgrieve-U4-4410 2016-11-09 11:40:25 +01:00
Stephan a80bb1e219 Merge branch 'U4-9077' of https://github.com/lars-erik/Umbraco-CMS into temp-u4-9077 2016-11-09 11:36:42 +01:00
Claus ff2805c428 mostly just formatting and cleanup - no changes as such. 2016-11-09 11:13:35 +01:00
Claus 69c45a4b05 Merge pull request #1612 from tnielsenskybruddk/dev-v7
Link to member type from member properties
2016-11-09 10:29:49 +01:00
Claus 737244a65e Merge pull request #1567 from tnielsenskybruddk/dev-v7
Link to mediatype from media properties
2016-11-09 10:15:14 +01:00
Claus 7018969d14 removing unused language keys. 2016-11-09 09:29:43 +01:00
Claus d1ba7f31f8 Merge pull request #1566 from rpjengaard/dev-v7
Removed old options for linked targets and replaced with checkbox ins…
2016-11-09 09:18:27 +01:00
Thomas Nielsen cbfd04e950 Link to member type from member properties 2016-11-08 23:37:29 +01:00
Thomas Nielsen 981c0b83d3 Oops wrong pull request 2016-11-08 23:16:10 +01:00
Thomas Nielsen 16ae5cf634 Link to member type from member properties 2016-11-08 23:00:14 +01:00
Claus 4a42bfa9bb U4-9160 Headline in the "Republish entire site" dialog is not translated 2016-11-08 10:53:29 +01:00
Claus 3e32652b24 Merge pull request #1565 from abjerner/patch-13
Headline in the "Republish entire site" dialog is now translated
2016-11-08 10:52:42 +01:00
Claus 957096a70a fixing links to be https. 2016-11-08 10:33:05 +01:00
Claus 8bb069e996 U4-9134 XSS security issue in the grid
exposing xss clean method on templateutilities.
making the clean xss string extensions public instead of internal.
ensuring the included grid renderers clean for xss.
ensuring the included grid editors using html.raw with value directly, cleans for xss.
2016-11-08 09:55:24 +01:00
Claus a0c672eb91 Merge pull request #1568 from rasmusfjord/dev-v7
Translated dialogs to DK/EN
2016-11-08 08:44:01 +01:00
Claus eddd996ed6 Merge pull request #1601 from piotrwegner/dev-v7-pl-translation
added PL translation
2016-11-08 08:38:34 +01:00
crgrieve c0a2326a8d Removing whitespace when parsing MNTP comma separated list. 2016-11-07 21:03:57 +00:00
crgrieve e429f8611e Remove all whitespace when parsing MNTP allowed doctypes. 2016-11-07 20:53:59 +00:00
Claus fcca95787b fixing backwards compatibility. 2016-11-07 13:05:17 +01:00
Ivar 8944870d4f Renamed icon-globe---europe-africa to icon-globe-europe-africa 2016-11-07 13:05:15 +01:00
Claus b93c3d9caa Merge pull request #1564 from abryukhov/patch-6
Update ru.xml UI language file
2016-11-07 11:56:44 +01:00
Claus 4d2aba2577 Merge pull request #1599 from AndyFelton/U4-9147
Modified grammar on health check dashboard
2016-11-07 11:26:02 +01:00
Claus ce780ee4f4 Merge pull request #1595 from AndyFelton/U4-9146
Health check data integrity colons missing
2016-11-07 11:24:25 +01:00
Claus a6134bfacd Merge pull request #1569 from AronGreen/dev-v7
Danish translations related to Redirect URL Management
2016-11-07 11:20:43 +01:00
Claus a96f48d0a8 changing media controller logic. 2016-11-04 13:52:36 +01:00
Stephan 8fa1499a2f Merge origin/dev-v7 into dev-v7-deploy 2016-11-04 12:18:39 +01:00
Stephan 74e0a4d999 7.6 merge review fixes 2016-11-03 19:20:42 +01:00
ricardo abreu 7085f198a9 changed reloadPage function ($window to window) 2016-11-03 17:29:46 +00:00
ricardo abreu 4f211aaf48 added finish button so page only reloads after user input. also added localization for en/en_us 2016-11-03 17:13:27 +00:00
Piotr Wegner 4d2bf19891 added PL translation 2016-11-03 17:09:01 +00:00
Steve Morgan dfbadb1550 U4-9148 noNodes Splash screen apostrophe char typo fixed (in "Be a part of the community" - we're) 2016-11-03 17:03:33 +00:00
Sebastiaan Janssen 0eeb481d85 Merge pull request #1586 from LottePitcher/U4-9068
Truncate should not finish halfway through a two word unicode character
2016-11-03 17:53:49 +01:00
Andy Felton 66bce71a8b "it's" replaced with "its" on "Checks to see if your site is revealing information in it's headers that gives away unnecessary details about the technology used to build and host it." 2016-11-03 16:51:33 +00:00
Andy Felton b198ecbc02 Modifed grammer as follows
MacroErrors are set to 'throw' which will prevent some or all pages in your site from loading completely when there's any errors in macros. Rectifying this will set the value to 'inline'. modifed to  "when there's any errors in macros" should be replaced with "if there are any errors in macros"
2016-11-03 16:51:06 +00:00
Sebastiaan Janssen ecbe058d00 Merge pull request #1591 from RachBreeze/U4-7239
U4-7239 Now trims the parameters
2016-11-03 17:16:22 +01:00
Andy Felton 22f37d02dc Added missing colon 2016-11-03 16:00:04 +00:00
Lotte Pitcher c8b23195f6 When truncating if the last characters was the first half of a two word unicode character, also include the second half to avoid YSOD 2016-11-03 14:30:38 +00:00
Sebastiaan Janssen 02840965d7 Merge pull request #1577 from Draga/U4-9055
U4-9055
2016-11-03 15:25:03 +01:00
Sebastiaan Janssen 5b13ab255a Merge pull request #1575 from readingdancer/U4-9091
U4-9091 - Fixed the font being used in the Media Picker for files
2016-11-03 15:09:22 +01:00
CORP\Rachel.Breeze ae659e3c84 U4-7239 Now trims the parameters so that if a default is set in a comma and space seperated list, the parameter is now populated. 2016-11-03 13:40:46 +00:00
Stefano Chiodino c1ffefc6af U4-9055 remove background-color on preview that was interfering with the website
style
2016-11-03 11:51:01 +00:00
Chris Houston 1b2d75ee52 Fixed the font being used in the Media Picker when a file has been selected. 2016-11-03 11:43:03 +00:00
Sebastiaan Janssen d5b2ce9c09 Merge pull request #1571 from drpeck/U4-8183
(U4-8183) Changed the link picker dialog from Page Title to Link title
2016-11-03 12:25:27 +01:00
David Peck 9162575b35 (U4-8183) Changed the casing to match other labels 2016-11-03 10:53:33 +00:00
David Peck 0ff26aa442 (U4-8183) Changed the link picker dialog from Page Title to Link title in en and en_us 2016-11-03 10:50:10 +00:00
Claus a06b920785 Merge pull request #1563 from umbraco/temp-u4-9137
U4-9137 - Fix PublishedMediaCache getting trashed media
2016-11-03 11:25:21 +01:00
Claus 0441827578 using the provided media type when uploading images, instead of using default Image media type. 2016-11-03 10:41:06 +01:00
Claus 85c2ec68ac allowing default image and file media types at root. 2016-11-03 10:39:59 +01:00
Lars-Erik Aabech bf50c25854 Only caching relation types
First hackathon task done. :)
2016-11-03 10:26:31 +01:00
Mads Rasmussen 24402388b4 position the overlay to the right 2016-11-03 09:57:10 +01:00
AronGreen 7b345d6cb0 Danish translations related to Redirect URL Management 2016-11-02 22:02:47 +01:00
Rasmus Fjord 018f9f1776 removed hg ignore 2016-11-02 21:30:18 +01:00
Rasmus Fjord 71f3948de2 Translated copy dialog (relate to and include descendants) to dk 2016-11-02 21:23:02 +01:00
Thomas Nielsen ea67e21796 Link to mediatype from media properties 2016-11-02 21:20:03 +01:00
René Pjengaard Bank a83739c269 Removed old options for linked targets and replaced with checkbox instead in linkpicker 2016-11-02 20:58:21 +01:00
Rasmus Fjord cc5f127dcf Translated "openInNewWindow" to a better sound in danish. 2016-11-02 20:57:17 +01:00
Rasmus Fjord e015e73abe Translation of Moving item(media / content) 2016-11-02 20:55:15 +01:00
Rasmus Fjord 0624d224a9 Translated set permissions windows 2016-11-02 20:30:05 +01:00
Rasmus Fjord 030708194a Oversat publish events 2016-11-02 20:15:55 +01:00
Anders Bjerner a5b0fbb83d Headline in the "Republish entire site" dialog is now translated 2016-11-02 19:51:54 +01:00
Alexander Bryukhov 5a5be024e4 Update ru.xml UI language file
Dictionary item editor keys added
2016-11-03 00:12:44 +07:00
Rasmus Fjord b1b42b5262 Merge branch 'dev-v7' of https://github.com/rasmusfjord/Umbraco-CMS into dev-v7 2016-11-02 16:45:31 +01:00
Stephan 07f4da9b00 Cleanup WebProfiler from 8.x 2016-11-02 14:26:04 +01:00
Stephan 59ace3d881 Backport SafeCallContext, DefaultDatabaseFactory fixes from 7.6 2016-11-02 14:26:04 +01:00
Mads Rasmussen 0426f1f17d Changes from Gerard Konings + a couple of small fixes 2016-11-02 14:24:17 +01:00
Stephan c2d3d057a5 U4-9137 - Fix PublishedMediaCache getting trashed media 2016-11-02 13:59:04 +01:00
Stephan 5426c570fc U4-9136 - group size 200 2016-11-02 13:53:03 +01:00
Stephan 3a6e2e6735 U4-9136 - rebuild Xml data in a more resilient way 2016-11-02 13:52:58 +01:00
Claus ef38808ba5 Merge branch 'merge-U4-8782' into dev-v7 2016-11-01 14:34:56 +01:00
Claus 7fe5f0c099 Merge branch 'Flaeng-Email-validation-on-user-form' into merge-U4-8782
Conflicts:
	src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs
2016-11-01 14:28:38 +01:00
Claus 5f615d30b2 Merge branch 'Email-validation-on-user-form' of git://github.com/Flaeng/Umbraco-CMS into Flaeng-Email-validation-on-user-form 2016-11-01 13:35:04 +01:00
Claus 7ce2bbe9b1 Merge branch 'mikecp-temp-U4-8782' into merge-U4-8782 2016-11-01 13:34:19 +01:00
Claus 4c408eb1b7 Merge branch 'temp-U4-8782' of git://github.com/mikecp/Umbraco-CMS into mikecp-temp-U4-8782 2016-11-01 13:32:09 +01:00
Sebastiaan Janssen 82a2f50d03 Merge pull request #1554 from umbraco/temp-u4-9121
U4-9121 - improve url perfs
2016-11-01 09:56:11 +01:00
Claus e8237f6190 adding culture parameters for this and a few others that were missing. 2016-10-31 15:09:10 +01:00
Claus 4d13622432 U4-9132 Macros from packages are empty when restored
changing the package installer to use the new API macroservice instead of the old legacy classes.
marked a few methods as obsoleted.
2016-10-31 14:55:11 +01:00
Stephan c77174059d Backport MainDom cleanup from 7.6 2016-10-31 11:06:17 +01:00
Stephan 69b442a31a Fix - PublicAccessEntry rules clearing 2016-10-31 11:02:00 +01:00
mikkelhm e9724c8785 Updates web.config.install.xdt to re-add the assemblyBinding for HtmlAgilityPack after removing it earlier 2016-10-30 20:46:18 +01:00
Tom Pipe 0a49d54a85 Fixed issue with member properties sort order 2016-10-29 18:23:25 +01:00
Stephan 958392f09b U4-9105 - bit of cleanup 2016-10-28 16:30:20 +02:00
Stephan cb79bcd876 Merge branch 'dev-v7' into temp-U4-9105 2016-10-28 14:38:43 +02:00
Stephan c500f98ad8 U4-9121 - improve url perfs 2016-10-28 14:33:44 +02:00
Sebastiaan Janssen 41a8dd10de Merge pull request #1545 from umbraco/temp-u4-9090
U4-9090 - Upgrade to ModelsBuilder 3.0.5 (reuse compiled live dll on …
2016-10-28 10:37:13 +02:00
Sebastiaan Janssen 9283e57429 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-10-27 22:09:43 +02:00
Sebastiaan Janssen 3bdb3f8c1e U4-9065 Update github readme from Kris's notes
#U4-9065 Fixed
2016-10-27 22:08:52 +02:00
Sebastiaan Janssen 3aee8b069d Merge pull request #1547 from umbraco/temp-U4-9039
Fixes: U4-9039 No progress indication when uploading local package
2016-10-27 21:47:05 +02:00
Sebastiaan Janssen 3e79b65539 Merge pull request #1549 from umbraco/temp-u4-8995
U4-8995 - fix health check for trySkipIisError
2016-10-27 21:30:55 +02:00
Shannon e2d8a28087 ensures the generic base class static query instance is lazily created 2016-10-27 18:45:42 +02:00
Shannon ba0ef3676d U4-9109 changes all usage of automapper ResolveUsing<T> to instantiate the resolver explicitly - this prevents IoC frameworks registered against automapper to not explode if these resolvers have not been added to the container. 2016-10-27 18:32:16 +02:00
Shannon 3f609fdf90 Moves a few queries to re-used query instances 2016-10-27 18:03:13 +02:00
Shannon 9717d03a75 oops, didn't mean to commit this 2016-10-27 18:03:13 +02:00
Shannon 21e2c35ab0 U4-9111 Benchmark BulkCopy changes from U4-9107 2016-10-27 18:03:13 +02:00
Claus 563f8fbdca forgot one :) 2016-10-27 11:07:41 +02:00
Claus 221354a7d8 U4-9104 Update the UmbracoExamine logic for Media to read the data directly from the umbracoXml table.
updated some tests to use the testbehavior attribute so they dont rely on being run in a specific order.
2016-10-27 10:47:32 +02:00
Stephan 7495d89a79 U4-9107 - enable bench on empty db 2016-10-26 19:26:10 +02:00
Stephan 15ad07f5db Merge pull request #1544 from umbraco/temp-U4-9107
U4-9107 Change BulkInsertRecords to use BulkCopy or TableDirect (SQLCE)
2016-10-26 19:24:41 +02:00
Stephan c95c4c359a Merge branch 'dev-v7' into temp-U4-9107 2016-10-26 18:03:43 +02:00
Stephan 1a1dd99a89 Merge pull request #1550 from umbraco/temp-U4-9101
U4-9101 fix up how cache refresh instructions are read or written and to prevent duplicate processing
2016-10-26 18:01:58 +02:00
Stephan 71afe908b4 U4-9101 - comments and misc 2016-10-26 18:01:32 +02:00
Stephan e3c3acfca9 Merge branch 'dev-v7' into temp-U4-9101 2016-10-26 17:48:41 +02:00
Shannon 7e81768abc adds exception checking to ExamineExtensions 2016-10-26 14:25:32 +02:00
Stephan 6d0bca471e U4-8995 - fix health check for trySkipIisError 2016-10-26 14:24:31 +02:00
Shannon 8e4e7e5b19 Ensures no duplicates are processed between rows 2016-10-26 12:19:36 +02:00
Shannon c667627d2f Changes max row retrieval to 100 2016-10-26 12:01:43 +02:00
Shannon 8b411c3d46 Adds checks to see if the app is shutting down while processing instruction batches, if so it will exit instruction processing. Also set a timeout on the wait lock so that if the app is shutting down it will after 5 seconds. 2016-10-26 11:37:59 +02:00
Claus db7c20d99a fixing unit test failing on da-DK culture sorting. 2016-10-26 11:32:25 +02:00
Shannon f153332ad5 updates logging levels for MainDom 2016-10-25 16:56:55 +02:00
Shannon 876d78b4ad During instruction processing, always check if the app is shutting down and if so then exit, if it's in the middle of a batch it will exit even if it's processed a few and will not save the last synced id meaning the batch will get processed again .Reverts the change to process only a portion of the instructions json blob and save back to the db - that won't work in LB scenarios. 2016-10-25 16:23:49 +02:00
Shannon 68e871d175 Ensures that any given JSON blob written to the instructions can only contain the maximum number of instructions to process 2016-10-25 16:01:55 +02:00
Shannon d7d4b26a66 This changes the instruction fetch process to query for the top records based on the MaxProcessingInstructionCount. This changes the Fetch to be a Query so they are not all loaded into memory and instead uses a db reader. This checks if any JSON blob contains more than the MaxProcessingInstructionCount and if so, it breaks out of the reader, takes the max amount to be processed and re-saves the remaining back to the same record so that this single request does not over-process instructions (which can take a long time and cause all sorts of problems) 2016-10-25 15:50:33 +02:00
Mads Rasmussen f1d5ccb1e3 Fixes: U4-9039 No progress indication when uploading local package 2016-10-25 15:40:31 +02:00
Stephan bf67cd5acd Merge pull request #1539 from umbraco/temp-U4-9093
U4-9093 Fix SQL used to rebuild the media & content xml structures in…
2016-10-25 14:05:13 +02:00
Stephan e330d40005 U4-9090 - Upgrade to ModelsBuilder 3.0.5 (reuse compiled live dll on restart) 2016-10-25 12:40:27 +02:00
Shannon 1a6986cfcf U4-9111 Benchmark BulkCopy changes from U4-9107 2016-10-25 12:34:06 +02:00
Stephan b617b9e391 U4-9108 - add config setting 2016-10-25 12:32:50 +02:00
Shannon dadcbc8b31 U4-9107 Change BulkInsertRecords to use BulkCopy or TableDirect (SQLCE) 2016-10-25 12:29:17 +02:00
Stephan 07bb57fac8 U4-9018 - provide a way to disable server master election 2016-10-25 12:22:06 +02:00
Stephan c58cffe4a2 Add tests for locks 2016-10-25 10:38:38 +02:00
Stephan 95af144ae9 Migrate locks to their own umbracoLocks table 2016-10-25 10:38:05 +02:00
Shannon 92f5ad220a oops, changes back so we have less joins, we don't need to query on cmsDocument or published, we know it will be that 2016-10-21 18:17:31 +02:00
Shannon 1a8f53d1de Fixes tests 2016-10-21 18:16:02 +02:00
Shannon 4f77caee02 U4-9093 Fix SQL used to rebuild the media & content xml structures in the data integrity check 2016-10-21 16:23:32 +02:00
Shannon d64757f3b0 U4-9093 Fix SQL used to rebuild the media & content xml structures in the data integrity check 2016-10-21 16:17:13 +02:00
Shannon 74a5bf5503 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-10-21 16:12:11 +02:00
Shannon ee8efbb1ab Adds notes about bulk copy 2016-10-21 16:11:57 +02:00
Claus 7ab2703388 Merge branch 'sniffdk-U4-205' into dev-v7 2016-10-20 13:59:00 +02:00
Claus f753dfa2a7 minor updates and a little reformatting. 2016-10-20 13:56:52 +02:00
Stephan 1aade7c27c Version 7.6.0-alpha028 2016-10-20 13:30:52 +02:00
Claus 8fa02913be Merge branch 'U4-205' of git://github.com/sniffdk/Umbraco-CMS into sniffdk-U4-205 2016-10-20 12:53:44 +02:00
Stephan e8538cc035 Merge remote-tracking branch 'origin/dev-v7' into dev-v7-deploy 2016-10-20 12:23:22 +02:00
Stephan 65ef97d9ba deploy-91 - make MediaExtensions public (why not) 2016-10-20 12:04:30 +02:00
Sebastiaan Janssen 21426610ad Need to take the current schema into account for the ExcessiveHeadersCheck 2016-10-19 17:01:15 +02:00
Stephan 20fc78419e Refactor / fix SignalR integration, add nuspec dependency 2016-10-19 15:07:48 +02:00
Sebastiaan Janssen 40b0a62cc3 Use int.MaxValue instead of 0 2016-10-19 14:58:56 +02:00
Shannon Deminick 3949b78c61 Merge pull request #1533 from callumbwhyte/U4-9042
U4-9042: Fixes backoffice members list view for custom membership providers
2016-10-19 14:48:44 +02:00
Claus 55179d7400 adding missing multiple content picker macro parameter. 2016-10-19 13:56:26 +02:00
Mads Rasmussen 517147346e Merge pull request #1534 from umbraco/temp-u4-9048
temp-U4-9048 - security when uploading files
2016-10-19 11:01:19 +02:00
Mads Rasmussen e1e63d079f add curly brackets to fix "grunt vs" task 2016-10-19 10:48:14 +02:00
Sebastiaan Janssen 86744046e3 Merge pull request #1531 from umbraco/temp-u4-8981
U4-8981 - fix package actions
2016-10-19 09:15:01 +02:00
Stephan a5f1c3e564 Merge pull request #1530 from umbraco/temp-U4-8769
fixes: U4-8769 ImageCropper focal points randomly sets to 'null'
2016-10-19 09:01:55 +02:00
Stephan 2b2734cd66 U4-8981 - fix package actions 2016-10-19 08:48:35 +02:00
Lars-Erik Aabech f199b0a651 Added default cachehelper to the relation repositories 2016-10-18 22:35:46 +02:00
Sebastiaan Janssen c2d33f3301 Merge pull request #1532 from richarth/patch-1
Update noNodes.aspx
2016-10-18 22:12:52 +02:00
Sebastiaan Janssen 8fc999f771 Merge pull request #1510 from lukawefocus/dev-v7
U4-7238 issue sorting listview after 7.3.0 upgrade
2016-10-18 20:25:17 +02:00
Sebastiaan Janssen be0fb51193 Merge pull request #1529 from mzajkowski/U4-6710
Cast tag value to unicoded text before inserting it into database
2016-10-18 18:37:11 +02:00
Sebastiaan Janssen 097f5355e2 U4-9050 Update to latest Examine 0.1.70.0 2016-10-18 18:03:43 +02:00
Sebastiaan Janssen 843fad9963 Merge pull request #1477 from arknu/U4-8968
Fix U4-8968: Add missing check for backoffice session in ClaimsIdentity
2016-10-18 17:53:14 +02:00
Sebastiaan Janssen 7b5670f275 U4-9076 Update to latest ImageProcessor 2016-10-18 16:45:16 +02:00
Sebastiaan Janssen f4410891e4 Merge pull request #1459 from umbraco/temp-U4-8829-dashboards-from-remote-feed
Temp u4 8829 dashboards from remote feed
2016-10-18 15:50:15 +02:00
Sebastiaan Janssen 9da95ce28f Moved UmbracoAuthorize to the class level
Unfortunately can't consolidate GetCacheItem and InsertCacheItem because of different timespan
Can't directly cache the `content` variable due to problems with modified closures
2016-10-18 14:16:37 +02:00
Stephan dda988f0ea Merge remote-tracking branch 'origin/dev-v7' into dev-v7-deploy 2016-10-18 12:25:31 +02:00
Sebastiaan Janssen 33e05625ed Fixes based on review 2016-10-18 10:10:50 +02:00
Sebastiaan Janssen b8575d04ad Adds default/fallback dashboard missing content 2016-10-18 09:56:25 +02:00
Stephan b64b67ce81 U4-9048 - return proper Forbidden status code when uploading to invalid folder 2016-10-18 08:47:03 +02:00
Stephan 1b6a2c7d5c U4-9048 - validate user before retrying queued promises 2016-10-18 08:46:41 +02:00
Callum Whyte a1a90d5bff Fixes backoffice members list view for custom membership providers by using key instead of id in edit URL 2016-10-17 16:26:20 +01:00
richarth 08733d7351 Update noNodes.aspx
Grammar correction
2016-10-17 14:28:16 +01:00
Sebastiaan Janssen 5d0d65c624 Merge branch 'dev-v7' into temp-U4-8829-dashboards-from-remote-feed 2016-10-17 15:00:40 +02:00
Stephan 6c7c333d8f Merge pull request #1523 from umbraco/temp-U4-8896
fixes: U4-8896 U7 (7.4.2) - Uploading images in media library fails
2016-10-17 14:45:24 +02:00
Mads Rasmussen b039fbfb13 Merge pull request #1498 from bjarnef/dev-v7-U4-9007
Format package created date
2016-10-17 14:41:36 +02:00
Mads Rasmussen 428bc7fbad Merge pull request #1525 from JeffreyPerplex/patch-2
Update imagecropper.html
2016-10-17 14:21:55 +02:00
Stephan fe9686f215 U4-8981 - fix package actions 2016-10-17 14:21:51 +02:00
Stephan ac42c8ae26 Fix 2eb050e, broke Xslt edit 2016-10-17 14:06:08 +02:00
Mads Rasmussen e4a472f902 fixes: U4-8769 ImageCropper focal points randomly sets to 'null' 2016-10-17 13:32:09 +02:00
Stephan c5c974e996 Merge branch 'dev-v7' into dev-v7.6 2016-10-17 11:21:19 +02:00
Sebastiaan Janssen 900f8970f0 Check for null orderBy argument earlier to avoid doing unnecessary work 2016-10-17 09:56:50 +02:00
Claus dd6c24d3b8 Merge pull request #1527 from leekelleher/issue/U4-9073
Grid: Quote editor - wrong CSS style rule for italic
2016-10-17 09:08:52 +02:00
Dennis Jørgensen fb83b9dca3 Changed email validation to the validation used when creating users (MembershipProviderBase). 2016-10-16 18:45:01 +02:00
Marcin Zajkowski 8175e68ecd Cast tag value to unicoded text before inserting it into database
Quick fix for: http://issues.umbraco.org/issue/U4-6710
2016-10-16 03:15:02 +02:00
Dennis Jørgensen ac0159f67e Changed style for form controls and text for email-field 2016-10-15 22:47:35 +02:00
Dennis Jørgensen f1c8fb7b17 Added validation to the user edit-form in the backoffice 2016-10-15 22:00:03 +02:00
Dennis Jørgensen 3b43979a06 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-10-15 20:24:19 +02:00
leekelleher c839285f90 Grid: Quote editor - wrong CSS style rule for italic
[Issue #U4-9073](http://issues.umbraco.org/issue/U4-9073)

In `grid.editors.config.js`, the style config for the Quote editor has an incorrect CSS style rule for italic, it has...

```css
font-variant: italic;
```

It should be...

```css
font-style: italic;
```

I wasn't sure which `grid.editors.config.js` to change, so I did them all.
2016-10-14 16:37:06 +01:00
Claus 21378a07c8 Merge pull request #1466 from AndyButland/u4-8941
u4-8941 - Used configurable application URL when constructing password reset link
2016-10-14 11:05:37 +02:00
Jeffrey Schoemaker 74e6633f2a Update imagecropper.html
Remove ng-show="imageIsLoaded" so "Remove file" is always visible when there's an image or file uploaded, even if it can't be rendered because whether is .tif-file (correct image, but not rendered in modern browsers), .pdf-file (foolish action) or the image is removed from the server (staging with a production-environment-database).

Related to http://issues.umbraco.org/issue/U4-8490
2016-10-14 10:31:12 +02:00
Claus 8693b13e68 Merge pull request #1511 from umbraco/temp-U4-8992
U4-8992 - update content and media xml caches when upgrading from bef…
2016-10-13 15:31:09 +02:00
Mads Rasmussen a0a861370b Merge pull request #1499 from darrenferguson/dev-v7
U4-9012 The word "Oops" should probably be removed, because we can ca…
2016-10-13 15:20:59 +02:00
Mads Rasmussen 7282626c0f Merge pull request #1514 from abryukhov/patch-6
Update UI language ru.xml
2016-10-13 14:50:12 +02:00
Mads Rasmussen cf604255fc fixes: U4-8896 U7 (7.4.2) - Uploading images in media library fails 2016-10-13 13:12:24 +02:00
Shannon Deminick b275850aca Merge pull request #1515 from seth-reeser/patch-1
Update README.md
2016-10-13 11:46:43 +02:00
Seth Reeser 8aa36a82c4 Update README.md 2016-10-12 22:48:10 -04:00
Alexander Bryukhov 06132fcdaf Update UI language ru.xml
New key in healthCheck area added
2016-10-12 11:17:04 +07:00
Stephan f1e5b3fcfa Prevent tests from failing due to dates rounding 2016-10-11 15:06:33 +02:00
Mads Rasmussen fba4b91bec Merge pull request #1465 from abryukhov/patch-6
Localizing URL tracker dashboard
2016-10-11 14:42:37 +02:00
Mads Rasmussen 0ef987207b Merge pull request #1489 from abryukhov/patch-7
U4-8985 Label for row configurations in the grid editor
2016-10-11 14:21:06 +02:00
Mads Rasmussen 2d7b5b959e Merge pull request #1497 from bjarnef/dev-v7-U4-8897
Change color of remove button to red
2016-10-11 14:01:27 +02:00
Mads Rasmussen 2837861d9a Merge pull request #1501 from jt3432/dev-v7
Added title attribute to image tags
2016-10-11 13:27:32 +02:00
Mads Rasmussen 212222c98e Merge pull request #1505 from bjarnef/dev-v7-U4-9031
Make increase/decrease buttons in grid layout and row configurations …
2016-10-11 13:14:09 +02:00
Mads Rasmussen 15237a6d91 Merge pull request #1512 from Joddsson/changeDocTypeToolbar
Styled toolbar buttons in ChangeDocType dialog
2016-10-11 13:02:03 +02:00
Ivar 95b2ef0f3c Styled toolbar buttons in ChangeDocType dialog 2016-10-10 23:27:42 +00:00
Stephan c452d31f25 Prevent tests from failing due to dates rounding 2016-10-10 19:18:49 +02:00
Stephan 7361d1f16f U4-8992 - update content and media xml caches when upgrading from before 7.3 2016-10-10 18:25:54 +02:00
Luka Kuljic 7ffb22a40f U4-7238 issue sorting listview after 7.3.0 upgrade
http://issues.umbraco.org/issue/U4-7238

System field publish only available for Content, didn't work on content
sorting by this field. Fixed by prefixing the field with table:
cmsDocumen.published.
2016-10-06 15:59:59 +02:00
Claus a6948d492a Merge remote-tracking branch 'origin/dev-v7' into dev-v7-deploy 2016-10-06 13:17:43 +02:00
Claus f78e496e69 Merge pull request #1509 from umbraco/temp-u4-8983
U4-8983 - clear EntityService cache on content events
2016-10-06 10:56:30 +02:00
Shannon b3e6f0fd22 Merge branch 'refs/heads/dev-v7' into dev-v7-deploy
# Conflicts:
#	src/Umbraco.Core/IO/FileSystemExtensions.cs
2016-10-06 10:35:45 +02:00
Stephan 48ed511ba5 U4-8983 - clear EntityService cache on content events 2016-10-06 09:06:25 +02:00
Stephan 3cff6fdd6c Merge pull request #1451 from umbraco/temp-u4-8698
U4-8698 - fix notification service perfs issues
2016-10-06 08:31:39 +02:00
Shannon Deminick 81da2e49f7 Merge pull request #1508 from umbraco/temp-U4-9005
U4-9005 Update comments in urlrewriting.config to note it's obsolete
2016-10-05 18:32:51 +02:00
Shannon 2cd6427958 Fixes more issues with notifications which weren't sending properly do to a i++ instead of a ++1, have refactored that to read better. Also fixes up performance issues since we were returning every single fully resolved IContent for all versions when all we need is the top 2 version ids, have added methods to do that plus a unit test. Have tested the emails and the diffs and they all work. 2016-10-05 18:30:03 +02:00
Sebastiaan Janssen 061f1ae0b1 U4-9005 Update comments in urlrewriting.config to note it's obsolete 2016-10-05 17:49:09 +02:00
Stephan ca60b1e24d More BackgroundTaskRunner troubleshooting 2016-10-05 15:07:47 +02:00
Stephan a279be1b47 Build TLC 2016-10-05 14:35:44 +02:00
Shannon f503cd41de Merge branch 'refs/heads/dev-v7' into temp-u4-8698 2016-10-05 11:52:05 +02:00
Shannon Deminick 4428877158 Merge pull request #1507 from umbraco/temp-U4-6809
U4-6809 u7.2.6 Updating media items with large file cause out of memo…
2016-10-05 11:23:50 +02:00
Shannon 876f61ac27 U4-8788 ContentService.GetByIds() returns items in different order
U4-8937 ContentController.PostSort is not honouring the passed sorted ids.
2016-10-05 11:20:48 +02:00
Claus 2cc541e084 U4-6809 u7.2.6 Updating media items with large file cause out of memory exception 2016-10-05 11:06:51 +02:00
Shannon ddd3c78fa6 Merge branch 'refs/heads/temp-u4-8937' into dev-v7 2016-10-05 11:05:44 +02:00
Shannon Deminick 62dffedc02 Merge pull request #1491 from umbraco/temp-U4-9001
U4-9001 Health Check, HTTPS Configuration is missing a message when c…
2016-10-05 10:53:49 +02:00
Claus 13e5409ab2 Merge pull request #1492 from jswietek/U4-8975
U4 8975
2016-10-05 10:51:14 +02:00
Stephan 198fff508d Version 7.6.0-alpha027 2016-10-05 09:57:45 +02:00
Stephan 3fd918d381 Refacetor BackgroundTaskRunner, fix async issues 2016-10-04 14:12:06 +02:00
Stephan 35c7fb60fd Refactor BackgroundTaskRunner, support cancellation of current task 2016-10-03 15:15:51 +02:00
bjarnef 927e9cf14a Make increase/decrease buttons in grid layout and row configurations use same icons 2016-10-02 21:09:52 +02:00
michael f0db4824ec Solve issue U4-8782 : E-mail validation when editing user + update error message when creating new user to use localized text 2016-09-30 23:20:17 +02:00
Stephan 79623a8a67 Fix BackgroundTaskRunner for tests without an app context 2016-09-29 16:04:27 +02:00
Per Ploug 7611829f2e Changes http to https 2016-09-29 13:28:57 +02:00
Per Ploug d34dcb0b27 Load template editor correct without massive ace deps 2016-09-29 13:26:25 +02:00
Stephan 37d8b71d5d Version 7.6.0-alpha021 2016-09-29 11:13:42 +02:00
Stephan 81f44024f7 Publicize ImageHelper 2016-09-29 09:06:47 +02:00
Stephan e477c8b0b3 Merge branch origin/dev-v7 into dev-v7-deploy 2016-09-29 09:03:56 +02:00
Jason Thomas 1ff5d171e3 Added title attribute to image tags for mediapicker.html and umb-media-grid.html. 2016-09-28 17:22:08 -06:00
Sebastiaan Janssen b8aaebf51a Fix automapper remove/insert transform 2016-09-28 16:05:35 +02:00
Shannon Deminick 2c9bc5135c Merge pull request #1483 from umbraco/temp-U4-8984
U4-8984 Upgrade AutoMapper to latest 3.x
2016-09-28 15:41:38 +02:00
Shannon 248177f518 Ensures Nuspec has correct AutoMapper, ensures config transform is correct (we cannot remove something that isn't there since it never existed before) 2016-09-28 15:33:32 +02:00
Shannon Deminick d34901fd13 Merge pull request #1500 from markwemekamp/dev-v7
Bugfix in Initialize method of UmbracoMediaFile
2016-09-27 09:44:29 +02:00
Mark 94b12dfb02 Updated code according to coding rules 2016-09-27 09:36:35 +02:00
Mark 0cc88a1706 Bugfix in Initialize method of UmbracoMediaFile
GetExtension returns an empty string instead of null which causes the
substring to return an argumentoutofrange exception. Discovered this
when trying to use Save(HttpPostedFile file) and Save(HttpPostedFileBase
file), but since the temporary generated path didn't include an
extension, these methods always threw an exception
2016-09-27 09:08:56 +02:00
Rasmus Fjord bd3ad153d2 bah 2016-09-26 11:05:15 +02:00
Darren Ferguson 78524398b7 U4-9012 The word "Oops" should probably be removed, because we can cancel publish by API, it may be deliberate. http://issues.umbraco.org/issue/U4-9012 2016-09-23 18:43:55 +01:00
Stephan 76461e866b Version 7.6.0-alpha020 2016-09-23 17:25:53 +02:00
Stephan 3f22e727f6 Some things need to be public/adjusted for Deploy 2016-09-23 16:42:42 +02:00
Stephan c606314c0f Remove InternalsVisibleTo Umbraco.Deploy 2016-09-23 13:55:27 +02:00
Stephan 37e12cd0be Fix unit tests interferences 2016-09-22 22:18:05 +02:00
Stephan b063928732 Version 7.6.0-alpha0016 2016-09-22 21:46:23 +02:00
Stephan 111a3ca6ac Refactor Shadow FileSystems 2016-09-22 21:45:59 +02:00
bjarnef f97123015a Format package created date 2016-09-22 19:55:32 +02:00
bjarnef b1e6559f4d Change color of remove button to red 2016-09-22 19:29:32 +02:00
michael 2d0725fbad update with latest labels from en_us.xml 2016-09-22 12:15:13 +02:00
michael 1a0ced4f15 Merge remote-tracking branch 'umbraco/dev-v7' into dev-v7 2016-09-22 01:07:01 +02:00
Stephan 7176c99264 Merge branch origin/dev-v7 into dev-v7-deploy 2016-09-21 16:03:17 +02:00
Stephan 30c32da5e6 Version 7.6.0-alpha014 2016-09-21 16:02:32 +02:00
Sebastiaan Janssen 9d9c36b253 U4-9001 Health Check, HTTPS Configuration is missing a message when certificate is valid 2016-09-21 13:04:06 +02:00
Jakub Swietek 6d9a747b34 Added option to delete cell from a row 2016-09-21 13:00:02 +02:00
Jakub Swietek a28cd8a54f Changed row cell's minimum width to 1 2016-09-21 12:57:57 +02:00
Jakub Swietek 44ad842542 Added option to delete selected section from layout 2016-09-21 12:56:31 +02:00
Jakub Swietek 917e05a16c Changed section's minimum width to 1 2016-09-21 12:55:05 +02:00
Stephan 23608ca70c Merge branch 'dev-v7-deploy' of https://github.com/umbraco/Umbraco-CMS into dev-v7-deploy 2016-09-21 12:40:44 +02:00
Stephan 3ab01a2164 Implement shadow filesystems, IFileSystem2.GetSize 2016-09-21 12:40:29 +02:00
Claus d9e608329d removing a using statement. 2016-09-21 12:30:33 +02:00
Claus 367ad70be7 adding signalr to core. 2016-09-21 12:27:32 +02:00
Alexander Bryukhov e60d5c8f2c U4-8985 Label for row configurations in the grid editor 2016-09-20 20:39:31 +07:00
Warren Buckley 03f16dfb78 Merge pull request #1485 from umbraco/temp-U4-8986
U4-8986 Allowing for more complex settings of the applyTo configurati…
2016-09-20 10:40:48 +01:00
Claus c9106065fd config transform for nuget upgrade. 2016-09-20 09:12:44 +02:00
Warren Buckley 2c9e96406b Merge pull request #1486 from umbraco/temp-U4-8987
U4-8987 Grid editor radiobuttonlist in settings should allow prevalue…
2016-09-19 12:01:54 +01:00
Warren Buckley 21c7d6a667 Merge pull request #1484 from umbraco/temp-U4-8985
U4-8985 Label for row configurations in the grid editor
2016-09-19 10:45:22 +01:00
Warren Buckley e0f95f18d3 Small mod to ensure the copy for the updated warning is easier to read that modifying the label is OK to do so 2016-09-19 10:07:23 +01:00
Warren Buckley b9ffbe9a57 Merge pull request #1481 from umbraco/temp-U4-8924
U4-8924 Heath Check: Pingback to HTTPS uses wrong protocol
2016-09-19 09:11:38 +01:00
Sebastiaan Janssen dc9b2b3ca8 Fix the ClickJackingCheck to make sure it adds an "s" to "http" when SSL is enforced or site is running on port 443 2016-09-19 09:44:03 +02:00
Claus baafa604fe Merge pull request #1448 from abjerner/patch-11
The p in picker should be uppercase
2016-09-17 14:34:04 +02:00
Claus e79bfebb76 U4-8987 Grid editor radiobuttonlist in settings should allow prevalues to have a label 2016-09-17 14:01:58 +02:00
Claus 131fdab675 U4-8986 Allowing for more complex settings of the applyTo configuration for grid editor. 2016-09-17 12:35:49 +02:00
Claus efc2a8e2ea U4-8985 Label for row configurations in the grid editor 2016-09-16 23:20:47 +02:00
Claus d725f1362f U4-8984 Upgrade AutoMapper to latest 3.x 2016-09-16 21:23:31 +02:00
Claus e79427619b Revert "U4-8984 Upgrade AutoMapper to latest 3.x"
This reverts commit 4887302b51.
2016-09-16 21:22:35 +02:00
Claus 4887302b51 U4-8984 Upgrade AutoMapper to latest 3.x 2016-09-16 21:21:14 +02:00
Warren Buckley aea735f20e Merge pull request #1441 from umbraco/temp-U4-8866
U4-8866 Deleting a parent document type fails if any documents using …
2016-09-16 15:46:50 +01:00
Stephan e868a57979 Fix TemplateRepository so it initializes VirtualPath 2016-09-16 13:31:34 +02:00
Warren Buckley 7a34b490c7 Merge pull request #1468 from umbraco/temp-u4-8954
U4-8954 - fix WhereIn issue with non-value-types
2016-09-16 11:37:12 +01:00
Warren Buckley 8091d9a098 Resetting UmbracoSettings file in this PR back to what it was previously - seems to have been committed by mistake 2016-09-16 11:04:50 +01:00
Sebastiaan Janssen e2e6440109 Merge pull request #1482 from romanlytvyn/temp-u4-8956
U4-8956 PublicAccessEntry.ClearRules() triggers an unhandled exception
2016-09-16 09:49:54 +02:00
Roman Lytvyn caffb36ec2 U4-8956 PublicAccessEntry.ClearRules() triggers an unhandled exception
fixed System.InvalidOperationException (Collection was modified;
enumeration operation may not execute.) by reverse iterating the
collection.
2016-09-16 10:35:14 +03:00
Sebastiaan Janssen 0d054de6ac U4-8924 Heath Check: Pingback to HTTPS uses wrong protocol 2016-09-15 17:37:42 +02:00
Warren Buckley 5397f2c53a Merge pull request #1447 from umbraco/temp-u4-8906
U4-8906 - optimize member perfs
2016-09-15 15:14:34 +01:00
Warren Buckley 61b11025bd Merge pull request #1476 from umbraco/temp-U4-8966
U4-8966 Unable to uninstall Umbraco Forms - The relative virtual path…
2016-09-15 13:40:48 +01:00
Stephan ab3b04c165 Fix SqlHelper so it uses to current db connection 2016-09-15 12:14:25 +02:00
Claus 8c8a0160a1 U4-7705 Media Picker does not render when image has been deleted
refixing - seems to have been left out in a merge somewhere.
2016-09-14 08:43:32 +02:00
Asbjørn Riis-Knudsen cbd980357b Fix U4-8968: Add missing check for backoffice session in ClaimsIdentity (like the comment says) 2016-09-13 22:36:14 +02:00
Stephan 5cd7cba4fb Fix content repo to respect dates if forced 2016-09-13 19:48:38 +02:00
Stephan 6b0377bb71 Cleanup SafeCallContext 2016-09-13 10:14:27 +02:00
Stephan 1589f9105c Bugfix SafeCallContext 2016-09-13 08:33:04 +02:00
Stephan 597b9bbfcb Introduce SafeCallContext to fix breaking test
(wondering if using logical call context a breaking change)
2016-09-13 08:01:45 +02:00
Sebastiaan Janssen 8b37f1dc6c Really cleaned up all of the other unneeded usings now... 2016-09-12 23:29:34 +02:00
Sebastiaan Janssen 6ec7028fe8 No need to add umbraco.Utils.. also cleaned up all of the other unneeded usings 2016-09-12 23:26:39 +02:00
Sebastiaan Janssen 14c0055899 U4-8966 Unable to uninstall Umbraco Forms - The relative virtual path 'bin/Umbraco.Forms.Core.dll' is not allowed here. 2016-09-12 23:24:01 +02:00
Stephan d84cfe001f Merge branch origin/dev-v7.6 into dev-v7-deploy 2016-09-12 14:07:02 +02:00
Stephan 6cccf84043 Merge branch 'dev-v7' into dev-v7.6 2016-09-12 14:03:41 +02:00
Claus abfa20ec31 Merge pull request #1475 from umbraco/temp-U4-8965
U4-8965 Updates for ImageProcessor parameters to support new crop mod…
2016-09-12 14:03:25 +02:00
Claus e0981f1c44 Merge pull request #1475 from umbraco/temp-U4-8965
U4-8965 Updates for ImageProcessor parameters to support new crop mod…
2016-09-12 13:36:24 +02:00
Claus 2ca7304215 Merge pull request #1444 from Jeavon/u4-8876
Update ImageCropMode & ImageCropAnchor enums with options available i…
2016-09-12 13:33:03 +02:00
Claus 88f8052573 U4-8965 Updates for ImageProcessor parameters to support new crop modes in v. 4.4.0 2016-09-12 12:51:48 +02:00
Michael Latouche 6407c24977 Update fr.xml 2016-09-10 01:51:45 +02:00
michael fb8d71fc63 Merge remote-tracking branch 'umbraco/dev-v7' into dev-v7
# Conflicts:
#	src/Umbraco.Web.UI/umbraco/config/lang/fr.xml
2016-09-10 01:45:47 +02:00
michael 8ee98ebdf9 Review and add translation labels to language file fr.xml (sync with latest en version) 2016-09-09 13:37:24 +02:00
Claus 3f65ec3318 fileservice getting and setting xslt file content. 2016-09-09 13:36:34 +02:00
Claus b67855b7a3 xslt file repository and methods for getting xslt files in FileService. 2016-09-09 13:33:14 +02:00
Claus 0299de4fdd adding in stream methods for partial views. 2016-09-09 13:31:43 +02:00
Claus ba09e945f0 changes to partialview repositories initialization.
adding methods for getting/setting partialview macro files.
2016-09-09 13:28:30 +02:00
michael d74a30e4e4 Review and add translation labels to language file fr.xml 2016-09-09 13:17:53 +02:00
Claus 2eb050e663 removing a checkbox that didnt do anything at all. 2016-09-09 12:49:08 +02:00
Claus 7499c9a19c fixing typos and a rename. 2016-09-09 11:09:42 +02:00
Stephan e309afa1a0 Merge branch 'dev-v7-deploy' of https://github.com/umbraco/Umbraco-CMS into dev-v7-deploy 2016-09-09 09:28:46 +02:00
Stephan 5d71df36bd Fix Entity to respect dates if forced 2016-09-09 09:28:25 +02:00
Claus 7be76f10d6 accessing file streams for ScriptRepository and StylesheetRepository.
changed naming of existing file service methods to conform.
2016-09-09 09:26:29 +02:00
Stephan 22a62421f0 Merge branch origin/dev-v7 into dev-v7-deploy 2016-09-08 16:58:57 +02:00
Stephan be3032192a Add WhereAnyIn sql extension 2016-09-08 15:23:48 +02:00
Stephan 37dc9989c4 Fix DefaultDatabaseFactory non-http instance 2016-09-08 15:23:28 +02:00
Stephan eb7a0cb85d U4-8954 - fix WhereIn issue with non-value-types 2016-09-08 10:40:36 +02:00
Stephan 5afeb315ba U4-8954 - rename file 2016-09-08 10:39:56 +02:00
Stephan c2eeff6e47 U4-8954 - fix WhereIn issue with non-value-types 2016-09-08 10:37:03 +02:00
Shannon 893c2a99be adds some comments 2016-09-08 09:30:13 +02:00
Stephan 36188f00b0 Fix exceptions (more explicit) 2016-09-07 13:24:49 +02:00
AndyButland 9da18d0697 Used configurable application URL when constructing password reset link 2016-09-06 08:42:53 +02:00
Alexander Bryukhov 3bb991edd3 Missing key 'signInWith' added 2016-09-06 11:52:19 +07:00
Alexander Bryukhov dd0373b855 Localizing URL tracker dashboard 2016-09-06 11:36:00 +07:00
Shannon Deminick 48786fcae1 Merge pull request #1464 from umbraco/temp-U4-8939
Temp u4 8939
2016-09-05 15:11:23 +02:00
Sebastiaan Janssen 28b4945d36 No longer need this now that it's part of JsJQueryCore 2016-09-05 14:59:22 +02:00
Sebastiaan Janssen 4a5314d8b9 No longer need this now that it's part of JsJQueryCore 2016-09-05 14:56:06 +02:00
Shannon Deminick c67adcc43f Merge pull request #1463 from umbraco/temp-U4-8939
U4-8939 Old openContentPicker() method is failing
2016-09-05 14:51:29 +02:00
Sebastiaan Janssen 0a43fea1c0 U4-8939 Old openContentPicker() method is failing
Adding jquery-migrate to make sure legacy applications keep working
2016-09-05 14:42:45 +02:00
Sebastiaan Janssen a20b7f9303 Merge pull request #1457 from umbraco/temp-u4-8917
U4-8719 - bugfix the redirect dashboard
2016-09-05 12:48:30 +02:00
Stephan 3fc76f61d0 MainDom - fixing application identifier 2016-09-05 12:33:26 +02:00
Stephan 5b9b6be383 Merge pull request #1455 from abjerner/patch-12
Added support for progress bar/list for when uploading a single file
2016-09-05 12:22:54 +02:00
Stephan fce0a4b0eb U4-8937 - cleanup 2016-09-05 12:20:05 +02:00
Stephan 381de750e7 Merge branch 'U4-8937' of https://github.com/SayTen/Umbraco-CMS into temp-u4-8937 2016-09-05 11:44:06 +02:00
Stephan 40f6de950c Merge pull request #1460 from umbraco/temp-U4-8938
U4-8938 [OutputCache] headers changed from Cache-Control: public to p…
2016-09-05 11:35:58 +02:00
Stephan 916c350352 Merge pull request #1461 from umbraco/temp-U4-8898
U4-8898 Blank login screen after upgrade to 7.5.x
2016-09-05 11:30:48 +02:00
Sebastiaan Janssen 4186791d9a Removing this reference for now, doesn't seem like the best way to reference a dll and the sln build fine without this 2016-09-04 13:13:45 +02:00
Sebastiaan Janssen 02cef43815 Localizing the URL tracker dashboard 2016-09-04 13:09:37 +02:00
Sebastiaan Janssen 8d291efedd In the spirit of DRY: centralized IsAdmin() check in an extension method
Made sure that non-admins can't trigger the enable/disable URL tracker endpoint
Renamed "admin" in GetEnableState to "isUserAdmin" for clarity
2016-09-04 11:44:16 +02:00
Sebastiaan Janssen a5c8052439 Better error message when package install fails 2016-09-03 13:55:54 +02:00
Sebastiaan Janssen 704169abab Merge branch 'refs/heads/dev-v7' into temp-U4-8889 2016-09-03 13:27:31 +02:00
Sebastiaan Janssen 8ee8b52832 Bumps version 2016-09-03 13:26:40 +02:00
Sebastiaan Janssen 81819aa3b7 Merge branch 'refs/heads/master-v7' into dev-v7 2016-09-03 13:25:02 +02:00
Sebastiaan Janssen 90ffae5526 Adds back some try-catches that were previously removed so we can actually log the errors 2016-09-03 13:23:32 +02:00
Sebastiaan Janssen a3c99531bf U4-8898 Blank login screen after upgrade to 7.5.x
Moves the updating of the CDF version to the very beginning before we even redirect to the login screen so it is nicely cachebusted
2016-09-03 10:23:17 +02:00
Sebastiaan Janssen 1b6bf2f331 U4-8938 [OutputCache] headers changed from Cache-Control: public to private 2016-09-03 10:16:34 +02:00
Per Ploug f5d18157bf resource to load dashboard data 2016-09-02 16:27:40 +02:00
Per Ploug 7c7dd0736e DashboardBoard to render remote grid data
- Includes offline mode
- loading state
- replaces content with data loaded from dashboard.umbraco.org
2016-09-02 16:27:30 +02:00
Per Ploug 0a5cd9f113 Change dashboardcontroller to UmbracoApiController
- Enables us to proxy css through the local server without a token on
the css request
- Adds method to load remote grid json
- Adds method to load remote grid css
2016-09-02 16:26:47 +02:00
Matt Cheale 9b498b8471 U4-8937 ContentController.PostSort is not honouring the passed sorted ids.
* Updates media to content for comments and logging.
* Adds sorting of the retrieved content items to match the passed sort order before persisting.
2016-09-02 14:50:54 +01:00
Stephan fee217e8d7 U4-8719 - minor fix 2016-09-02 15:01:58 +02:00
Stephan c05a28a901 U4-8719 - bugfix the redirect dashboard, move to content section 2016-09-02 14:54:18 +02:00
Stephan fa45cd1a88 tmp 2016-09-02 14:44:16 +02:00
Simon Busborg 6cb5331918 Fixed mistake where :not was applied to every umb-table-cell 2016-09-02 14:37:31 +02:00
Simon Busborg fca865a743 Fixed Redirects UI.. Added flex-box basis utility, removed date and edit button 2016-09-02 14:33:07 +02:00
Anders Bjerner 1f313b9487 Added support for progress bar/list for when uploading a single file 2016-09-02 11:39:16 +02:00
Stephan 0e7ac68c24 Deploy - clear dashboard.config 2016-09-01 16:52:12 +02:00
Stephan 0d3a413708 Merge remote-tracking branch 'origin/dev-v7' into dev-v7-deploy 2016-09-01 16:01:03 +02:00
Stephan 85d243508c Merge pull request #1453 from umbraco/temp-U4-8923
U4-8923 Adding new property to media breaks ability to save
2016-09-01 15:55:48 +02:00
Stephan 365da75d1b U4-8698 - fix notification service perfs issues 2016-09-01 15:25:40 +02:00
Sebastiaan Janssen a74feab9eb U4-8923 Adding new property to media breaks ability to save
If you add a new property to a member or media type and then try to update an
existing media item/member ContentRepository didn't have this problem because
it was already using the additional if statement that has now also been added to
MemberRepository and MediaRepository
2016-09-01 15:15:47 +02:00
Sebastiaan Janssen ae591d4883 U4-8889 Package install fails
Fixes one of the problems with installing packages (when 1 file needs to be copied to multiple places) and adds better logging for other potential problems
2016-09-01 14:19:12 +02:00
Stephan 3489bf22bb U4-8698 - fix notification service perfs issues 2016-09-01 12:15:03 +02:00
Stephan 9e82b8d693 U4-8906 - optimize member perfs 2016-09-01 12:11:12 +02:00
Claus 71482f0fc9 U4-8584 Starterkit thumbnails are not really thumbnails
updating url for thumbnails in the "new" starterkit code - seems we forgot those and only updated the legacy installer.
2016-08-29 08:54:01 +02:00
Anders Bjerner 8216fa1d88 The p in picker should be uppercase 2016-08-26 21:49:10 +02:00
Stephan 4133574db0 U4-8906 - optimize member perfs 2016-08-26 15:30:24 +02:00
Stephan 41fafaf7ae Merge branch origin/dev-v7 into dev-v7-deploy 2016-08-26 13:20:53 +02:00
Stephan 0789295701 Temp - 7.6.0-alpha003 - even with internals visible to, need IBackgroundTask to be public 2016-08-24 10:11:38 +02:00
Sebastiaan Janssen af5455a500 Bumps version 2016-08-23 10:52:29 +02:00
Sebastiaan Janssen be57692a62 Change some event handlers back to .live instead of .on
#U4-8884 Fixed
2016-08-23 10:48:15 +02:00
Sebastiaan Janssen 460d884109 Update the companion PermissionEditor.aspx file too 2016-08-23 10:48:15 +02:00
Sebastiaan Janssen 1a1a3c43ca Merge pull request #1446 from or321/or321-patch-1
Update UmbracoCms.nuspec
2016-08-23 10:40:10 +02:00
or321 6df6b87c4c Update UmbracoCms.nuspec
Update Newtonsoft.Json dependency to allow version 9.0.1 . This will match the same change in UmbracoCms.Core.nuspec file
2016-08-23 11:01:21 +03:00
Stephan bb81298e84 Temp - 7.6.0-alpha002 + internals visible to deploy 2016-08-23 09:40:02 +02:00
Sebastiaan Janssen 172895f17f U4-8884 Users editor doesn't work any more in 7.5.0
#U4-8884 Fixed
2016-08-22 15:18:04 +02:00
Simon Busborg 8d3add8834 Fixes: U4-8878 Text in grid items in reorder-mode is now right aligned 2016-08-22 09:10:05 +02:00
Sebastiaan Janssen ae257550da Update README.md 2016-08-21 15:33:08 +02:00
Sebastiaan Janssen 4653746117 Correct notation of path/name combo 2016-08-21 11:06:25 +02:00
Sebastiaan Janssen 84bd22190b Use names artifacts 2016-08-21 10:58:57 +02:00
Sebastiaan Janssen 5e58e0d0a5 Wrong artifact filter 2016-08-20 16:05:46 +02:00
Sebastiaan Janssen 8b2fa22b90 Attempt to have dev-v7 builds deploy to nightlies 2016-08-20 15:49:21 +02:00
Sebastiaan Janssen f76fd360f1 Bumps version 2016-08-20 10:29:49 +02:00
Jeavon bc9a6abccf Update ImageCropMode & ImageCropAnchor enums with options available in ImageProcessor v4.4+ 2016-08-19 16:14:56 +01:00
Sebastiaan Janssen 39ebb9545d Merge pull request #1442 from umbraco/temp-U4-8868
U4-8868 Ensuring all usages of .live() is updated
2016-08-18 15:32:03 +02:00
Sebastiaan Janssen 6572eea915 Merge pull request #1443 from jannikanker/jannikanker-U4-8867
U4-8867 (IFRAME casing typos)
2016-08-18 13:05:14 +02:00
Stephan bd6e2477b5 Post-merge 2016-08-18 13:02:52 +02:00
Jannik Anker 99ad5d6826 Update en_us.xml 2016-08-18 12:57:17 +02:00
Jannik Anker 2a1697b0a3 Update en.xml 2016-08-18 12:55:37 +02:00
Jannik Anker 583a09260e Update ClickJackingCheck.cs 2016-08-18 12:52:34 +02:00
Claus 344dab65d4 U4-8868 Ensuring all usages of .live() is updated
changed .on bind handlers to use .live instead.
removed an old jquery.1.4.4 which seems unreferenced and unused in the whole project.
2016-08-18 12:45:15 +02:00
Stephan acae05d287 Merge branch origin/dev-v7 into dev-v7-deploy 2016-08-18 12:38:38 +02:00
Claus 9f5a9f179f U4-8866 Deleting a parent document type fails if any documents using a child document type exist
ensures that we also manually delete content of any child content type being deleted, instead of only deleting content of the actual content type sent for delete.
2016-08-18 11:17:05 +02:00
Sebastiaan Janssen f658613fad Update README.md 2016-08-18 10:14:12 +02:00
Claus 1216f4a49e Merge pull request #1436 from umbraco/temp-u4-8856
U4-8856 - don't flood log with media errors
2016-08-17 10:52:02 +02:00
Sebastiaan Janssen 460e72fc1f Dealing with quirky trees.configs 2016-08-16 16:03:50 +02:00
Stephan 908c8837e9 U4-8856 - don't flood log with media errors 2016-08-16 15:41:52 +02:00
Sebastiaan Janssen 11c720cc2a Fixes trees config transform to work with versions older than 7.4 too 2016-08-16 14:39:52 +02:00
Sebastiaan Janssen c93b4fa1fe Reverts: Makes sure the build uses a predictable version of npm 2016-08-16 14:39:52 +02:00
Stephan d409d17189 U4-8813 - bugfix 2016-08-16 14:36:18 +02:00
Stephan 38c876bb53 Revert "U4-8813 - bugfix"
This reverts commit 95fb7f97d0.
2016-08-16 14:35:31 +02:00
Stephan 95fb7f97d0 U4-8813 - bugfix 2016-08-16 14:30:19 +02:00
Sebastiaan Janssen 9dfa9e2fb6 Bump the version 2016-08-16 13:37:05 +02:00
Sebastiaan Janssen 6ee8382ff3 Makes sure the build uses a predictable version of npm 2016-08-16 13:35:40 +02:00
Claus 69fb5e9932 Merge branch 'abjerner-patch-10' into dev-v7 2016-08-16 13:28:27 +02:00
Claus ca9f3bbd5a updating various references to use examine constants. 2016-08-16 13:27:46 +02:00
Claus fe7efa4fba Merge branch 'patch-10' of git://github.com/abjerner/Umbraco-CMS into abjerner-patch-10 2016-08-16 13:11:34 +02:00
Sebastiaan Janssen 1ec2cc430b Merge pull request #1429 from bjarnef/dev-v7-U4-8844
Set border radius for modal to zero.
2016-08-16 13:10:51 +02:00
Sebastiaan Janssen c1a8ea9df3 Merge pull request #1433 from umbraco/temp-U4-8850
U4-8850 Configuring a custom BackOfficeUserManager type will not work if the type is not specifically BackOfficeUserManager
2016-08-16 13:09:50 +02:00
Stephan cd2c79e7d5 U4-8813 - cleanup 2016-08-16 12:45:10 +02:00
Claus d5d0a958d3 removed console.logs 2016-08-16 11:45:42 +02:00
Mads Rasmussen 9e9e51cf29 Merge pull request #1432 from theotron/U4-8845
U4-8845 - Prevents double-click on confirm delete from deleting from bin
2016-08-16 09:50:47 +02:00
Sebastiaan Janssen 808793edd8 Updating to latest ImageProcessor 2016-08-16 09:35:05 +02:00
Sebastiaan Janssen 3895a93b61 Replaces the old packages tree item with the new one and puts it at the top 2016-08-16 09:35:05 +02:00
Shannon eadb9ba276 Merge branch 'refs/heads/dev-v7' into temp-U4-8850 2016-08-12 17:08:05 +02:00
Shannon fc582b0516 adds db schema check to validate if 7.4 has been installed, changes the versions detected to only be minor versions (they shouldn't have indicated build versions), updates code to not use deprecated methods 2016-08-12 16:54:24 +02:00
Shannon Deminick 432fac7dc9 Merge pull request #1430 from umbraco/temp-U4-8849
Fixes: U4-8849 301 Url tracker - When deleting last item on a page th…
2016-08-12 16:40:49 +02:00
Sebastiaan Janssen fad69046df Don't ship with the test-baseUrl 2016-08-12 16:38:48 +02:00
Shannon 6bcadfea44 Removes the explicit castings to (BackOfficeUserManager) since that isn't actually the base class! The base class is BackOfficeUserManager<BackOfficeIdentityUser>, all of this identity stuff is a bit of a generics nightmare but that also do to the generic nightmare that is OWIN. Moves more logic to the base class so it can be used by sub classes, fixes the base class to use a generic user type 2016-08-12 16:17:14 +02:00
theotron a3c457e50b Fixes U4-8845 - Double-click on confirm delete, deletes from bin as well
http://issues.umbraco.org/issue/U4-8845
2016-08-12 14:39:12 +01:00
Sebastiaan Janssen b2a56fa58f Merge branch 'ugurcelenk-dev-v7' into dev-v7 2016-08-12 14:19:09 +02:00
Sebastiaan Janssen f97c20253a Turkish Language file updated #1431 2016-08-12 14:18:50 +02:00
Ugur Celenk 51f57eb5ce Turkish Language file updated 2016-08-12 14:58:10 +03:00
Sebastiaan Janssen 54e82f9ed1 Fix nasty typo 2016-08-12 12:25:58 +02:00
Shannon 2ff3ce933b U4-8850 Configuring a custom BackOfficeUserManager type will not work if the type is not specifically BackOfficeUserManager 2016-08-12 12:20:00 +02:00
Mads Rasmussen 1c15daca52 Fixes: U4-8849 301 Url tracker - When deleting last item on a page the url tracker should check for new results. 2016-08-12 10:49:20 +02:00
Shannon de2d4bef13 Ensure the current umbraco version is passed up to Our for the new packaging section 2016-08-12 10:19:08 +02:00
bjarnef 8c6f56d3f5 Set border radius for modal to zero. 2016-08-11 18:46:01 +02:00
Sebastiaan Janssen 2f0b26db47 Merge pull request #1428 from umbraco/temp-U4-8841
U4-8841 Scheduled publishing in 7.5.0-latest has some problems
2016-08-11 17:37:16 +02:00
Shannon 1fd020a0f2 adds better debug logging to scheduled publishing 2016-08-11 14:33:10 +02:00
Shannon e12c294150 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-11 14:06:49 +02:00
Shannon 8d1d394ded Adds latest stable Examine version 2016-08-11 14:06:38 +02:00
Claus 3274965c34 typo 2016-08-11 12:43:12 +02:00
Claus 54fb1c6231 fixes the offsetting not being applied when loading the datepicker. 2016-08-11 11:22:50 +02:00
Morten Christensen d3ff1cbba9 Merge pull request #1426 from umbraco/temp-U4-8671
U4-8671 Media Types Missing in 7.4
2016-08-11 11:03:08 +02:00
Claus f4072bc975 Merge branch 'update-site-count-installer' into dev-v7 2016-08-11 08:13:46 +02:00
paulsterling 31e0913488 Updating number for current sites to 360 000 2016-08-10 14:49:30 -07:00
Claus f55e673632 adding a few tests for U4-8567. 2016-08-10 14:58:55 +02:00
Shannon f1087fce3c Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-10 14:41:09 +02:00
Shannon 5620074790 U4-8718 Latest ClientDependency release 2016-08-10 14:40:54 +02:00
Claus 600d7be2ac U4-8567 UmbracoHelper.CreateEncryptedRouteString fails to parse additionalRouteVals when it is of type Dictionary<string, object> 2016-08-10 13:45:06 +02:00
Claus 596888a8f6 Revert "Revert "U4-8833 The default sorting field for the member list view should be LoginName not Name""
This reverts commit d355d2609a.
2016-08-10 12:58:41 +02:00
Claus 0f0a0a186c U4-8838 Media type list has issues 2016-08-10 12:13:03 +02:00
Sebastiaan Janssen 200f0bb67e Don't add the Get Started panel back on upgrades 2016-08-10 11:59:35 +02:00
Sebastiaan Janssen af1be7f32f Insert <areas> if they're missing 2016-08-10 11:59:35 +02:00
Shannon d355d2609a Revert "U4-8833 The default sorting field for the member list view should be LoginName not Name" 2016-08-10 11:42:58 +02:00
Shannon 06da9f4f7d Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-10 11:42:12 +02:00
Shannon 5bd5bf87ad Fixes the search sorting for the packages section against our 2016-08-10 11:41:58 +02:00
Claus db78e26647 U4-8833 The default sorting field for the member list view should be LoginName not Name
correcting LoginName to username.
2016-08-10 11:23:46 +02:00
Claus a2adfe4798 Merge pull request #1425 from umbraco/temp-U4-8830
Fixes: U4-8830 Redirect url dashboard - add confirm dialog when remov…
2016-08-10 10:58:25 +02:00
Claus a7b19e1acf Merge pull request #1424 from umbraco/temp-U4-8825
Fixes: U4-8825 Show SVG preview in media picker
2016-08-10 10:47:35 +02:00
Claus a92aa6ad9a fixed up a comment and some cleanup. 2016-08-10 10:04:47 +02:00
Claus 154e4a19a5 cleaning and formatting. 2016-08-10 10:01:04 +02:00
Claus 0142bc61bc U4-8671 Media Types Missing in 7.4
renders child nodes in media type tree.
fixed up the context menus returned on nodes so you can create children if not disabled in config.
2016-08-10 09:56:28 +02:00
Shannon d99a691bdc Changes magic strings to constants for database provider types. 2016-08-09 15:36:02 +02:00
Shannon 10422079b6 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-09 15:33:49 +02:00
Shannon c1da28dd47 U4-8837 Change paging query for SQL server 2012+ to be more efficient 2016-08-09 15:33:35 +02:00
Sebastiaan Janssen 2018dab869 Fixed deprecation warning with moment.js 2016-08-09 15:32:17 +02:00
Shannon 5b88f35471 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-09 15:30:54 +02:00
Shannon 2ee71ecb96 U4-8833 The default sorting field for the member list view should be LoginName not Name 2016-08-09 15:30:43 +02:00
Mads Rasmussen 213a25e3fe fixes: U4-8836 Add empty state to content and member list view 2016-08-09 14:27:48 +02:00
Sebastiaan Janssen 14b527a9fa Makes sure the redirect dashboard is added in zip and for NuGet upgrades
Also adds healthcheck for NuGet upgrades
2016-08-09 14:12:28 +02:00
Shannon 2d25c4dad5 deletes tests to attempt to test the sorting issue: U4-8831 which didn't work because it's on sql ce 2016-08-09 14:01:18 +02:00
Shannon 8bdf0924de Merge remote-tracking branch 'refs/remotes/origin/dev-v7' into dev-v7 2016-08-09 13:59:00 +02:00
Shannon 1b85163a7f U4-8831 Paging logic is flawed when ordering by a potentially non-unique value 2016-08-09 13:58:53 +02:00
Shannon 634dfaaf75 U4-8833 The default sorting field for the member list view should be LoginName not Name 2016-08-09 13:55:41 +02:00
Claus 2279e6cc53 U4-8834 Removing code assigning PropertyData IDs for new properties even though it isn't used 2016-08-09 13:39:40 +02:00
Mads Rasmussen 82c5b91deb Fixes: U4-8832 Remove custom styling of pagination on list views 2016-08-09 13:30:19 +02:00
Shannon 9d2efdfb37 Adds test to confirm bug U4-8831 2016-08-09 12:47:14 +02:00
Mads Rasmussen 952cfc6d5f Fixes: U4-8830 Redirect url dashboard - add confirm dialog when removing redirect 2016-08-09 12:13:56 +02:00
Mads Rasmussen ff2311d19c bring back the checkered background for white images 2016-08-09 12:02:30 +02:00
Mads Rasmussen ef64098f4e remove checkered background from picked media 2016-08-09 10:34:47 +02:00
Mads Rasmussen 611acf8cea Show SVG preview in picked media 2016-08-09 10:34:27 +02:00
Shannon 910e6b7a64 U4-8766 v7.5.0-beta2 exception from Examine Grid Indexer 2016-08-09 09:40:29 +02:00
Sebastiaan Janssen bffd9c340d Wrong parameter name being sent to the RedirectUrlManagementController 2016-08-09 09:21:22 +02:00
Simon Busborg df116555ad fix search 2016-08-09 09:11:19 +02:00
Mads Rasmussen ca7e9c90b9 fixes: U4-8827 Add empty state for no search result and no added redirects to url redirects dashboard 2016-08-09 08:47:01 +02:00
Mads Rasmussen 65fc23dadc Fixes: U4-8828 Redirect urls dashboard - when search field has focus and enter is pressed the first redirect gets deleted 2016-08-09 08:44:45 +02:00
Sebastiaan Janssen 3ac7512a98 Merge pull request #1116 from rpjengaard/patch-1
Update da.xml
2016-08-08 17:23:20 +02:00
Sebastiaan Janssen a553fabce4 Merge pull request #1262 from umbraco/UmbracoCMS-Settings-Dashboard
Fixed issue: U4-8435 so the link is correct in settingsdashboardintro…
2016-08-08 17:07:55 +02:00
Sebastiaan Janssen 2a2453a969 Merge pull request #1283 from jbreuer/patch-1
Fix for U4-8510
2016-08-08 17:06:21 +02:00
Sebastiaan Janssen f4711a4473 Merge pull request #1340 from bjarnef/dev-v7-U4-8608
Document getByQuery
2016-08-08 17:02:53 +02:00
Sebastiaan Janssen 2069c585fb Merge branch 'temp-U4-8802' into dev-v7
# Conflicts:
#	src/Umbraco.Web/Routing/RedirectTrackingEventHandler.cs
#	src/Umbraco.Web/Umbraco.Web.csproj
2016-08-08 16:49:10 +02:00
Mads Rasmussen 045374993f Fixes: U4-8821 Prevent random form submits from healthcheck dashboard 2016-08-08 15:12:42 +02:00
Sebastiaan Janssen 57923866ed Merge pull request #1419 from umbraco/temp-U4-8813
U4-8813 RedirectTrackingEventhandler always iterates over all descend…
2016-08-08 14:59:58 +02:00
Shannon bf61956b7f oops fixes build 2016-08-08 14:48:05 +02:00
Shannon 9ad84a7eab fixes repository mapping the GUID id for redirect urls and removes unused properties 2016-08-08 14:47:48 +02:00
Shannon 4301af108f Merge branch 'temp-U4-8802' of https://github.com/umbraco/Umbraco-CMS into temp-U4-8802
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/dashboard/developer/redirecturls.html
#	src/Umbraco.Web/Editors/RedirectUrlManagementController.cs
2016-08-08 14:42:07 +02:00
Shannon c331ba134a Fixes 301 redirect js naming conventions, fixes URL handling, moves c# classes to the correct/constistent namespaces, fixes up models and N+1 requests, adds model mapping to not return the business logic model, adds controller method to check if it's enabled instead of returning the result as part of the search. 2016-08-08 14:40:53 +02:00
Mads Rasmussen 7d4e547b8d Fixes: U4-8820 Healthcheck dashboard should validate input for notification email 2016-08-08 14:30:59 +02:00
Mads Rasmussen cbd20cb9b3 Merge pull request #1406 from arknu/U4-8749
U4-8749: Allow default sort order to be custom properties
2016-08-08 14:01:53 +02:00
Claus 3170d6829a browser object null check in jquery.ba-bbq.min. 2016-08-08 13:26:21 +02:00
Claus 55752abdcf fixing InsertMacroSplitButton typo in jquery selector causing javascript errors.
fixing modal $.browser checks to not cause console errors due to deprecated browser object in jquery 1.9+.
2016-08-08 13:23:46 +02:00
Sebastiaan Janssen 69c952ddda Don't use HttpContext 2016-08-08 13:10:32 +02:00
Simon Busborg 4ff728b62a added target blank so it opens in another tab 2016-08-08 12:55:52 +02:00
Shannon Deminick 1b9a3e8ebc Merge pull request #1423 from abryukhov/patch-3
Update UI language ru.xml * dev-v7-U4-8597 - Social login form key added
2016-08-08 12:22:11 +02:00
Shannon fee4a84c66 Revert temp commit, adds logic to check if the segment value has changed + lots of notes 2016-08-08 12:19:03 +02:00
Shannon ad2a644bdf temp save to track history since i need to roll this back 2016-08-08 12:07:43 +02:00
Sebastiaan Janssen f4b0700528 Merge branch 'temp-U4-8802' of https://github.com/umbraco/Umbraco-CMS into temp-U4-8802 2016-08-08 12:00:14 +02:00
Sebastiaan Janssen 126c358546 Fixes build and use Guid where necessary 2016-08-08 11:57:48 +02:00
Alexander Bryukhov f316393955 Update UI language ru.xml 2016-08-08 16:41:19 +07:00
Simon Busborg 80d579891b Removes search when disabled 2016-08-08 11:33:56 +02:00
Claus bfc2e6f666 Merge branch 'bjarnef-dev-v7-U4-8597' into dev-v7 2016-08-08 11:32:02 +02:00
Claus c3035f26a7 Merge branch 'dev-v7-U4-8597' of git://github.com/bjarnef/Umbraco-CMS into bjarnef-dev-v7-U4-8597
Conflicts:
	src/Umbraco.Web.UI/umbraco/config/lang/da.xml
2016-08-08 11:31:29 +02:00
Sebastiaan Janssen b2e03dcc1b Merge branch 'refs/heads/dev-v7' into temp-U4-8802 2016-08-08 11:31:16 +02:00
Mads Rasmussen 97a765d6af Merge branch 'bjarnef-dev-v7-U4-8580' into dev-v7 2016-08-08 11:28:07 +02:00
Mads Rasmussen 67430392e3 Change object to img to make it render in Edge 2016-08-08 11:22:16 +02:00
Sebastiaan Janssen 6560f752d6 Merge branch 'refs/heads/dev-v7' into temp-U4-8802 2016-08-08 11:21:19 +02:00
Claus e02575830f Merge pull request #1420 from umbraco/temp-U4-8816
U4-8816 Update to jQuery  2.2.4
2016-08-08 11:00:47 +02:00
Shannon Deminick a838d20c3e Merge pull request #1422 from abryukhov/patch-9
Update UI language ru.xml
2016-08-08 10:57:22 +02:00
Alexander Bryukhov 081284bc62 Update UI language ru.xml
1. Duplicated 'prompt' area removed
2. Several typos corrected
2016-08-08 15:48:14 +07:00
Claus 9e9c1ad030 Merge pull request #1418 from drpeck/dev-v7
U4-8814 - HTml.Wrap adds children twice
2016-08-08 10:45:35 +02:00
Simon Busborg 32d48b12d1 Changed button when inactive, added class to toggle when table in inactive 2016-08-08 10:36:10 +02:00
Claus b4b91f0fef Merge branch 'pynej-sql-repalce' into dev-v7 2016-08-08 10:19:35 +02:00
Claus cbf67a4399 changing to Debug.Print. 2016-08-08 10:18:44 +02:00
Claus f58e0dc08e Merge branch 'sql-repalce' of git://github.com/pynej/Umbraco-CMS into pynej-sql-repalce 2016-08-08 09:58:39 +02:00
Shannon Deminick e449c237be Merge pull request #1421 from abryukhov/patch-8
Update UI language ru-RU.xml
2016-08-08 09:40:51 +02:00
Shannon Deminick 1dae6724cc Merge pull request #1227 from abryukhov/patch-6
Update UI language ru.xml
2016-08-08 09:40:20 +02:00
Simon Busborg a28c52aa16 Added styling to url list 2016-08-08 09:36:10 +02:00
Mads Rasmussen 26708ae82b Merge branch 'dev-v7-U4-8580' of git://github.com/bjarnef/Umbraco-CMS into bjarnef-dev-v7-U4-8580 2016-08-08 09:20:32 +02:00
Alexander Bryukhov 809970bc2e Update UI language ru-RU.xml
New 'bulk' area and few more corrections
2016-08-07 14:06:16 +07:00
Mads Rasmussen 27d041c055 Merge pull request #1416 from bjarnef/dev-v7-U4-8765-fix
Open documentation link in new browser window/tab
2016-08-05 21:36:27 +02:00
Shannon 7bf3d04a25 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-05 19:29:10 +02:00
Shannon 87934e52dc obsoletes strange IsGuid and changes logic to use what .Net does instead of regex in case others are using this. 2016-08-05 19:28:46 +02:00
Shannon 4022c3cec9 U4-8816 Update to jQuery 2.2.4 2016-08-05 19:15:11 +02:00
Shannon 816107a348 U4-8813 RedirectTrackingEventhandler always iterates over all descendants
fixes SHA1 hashing (moves to a ext method), fixes col length for new db for the redirect table, updates migration len to 40 to store the correct hash format, don't iterate descendents if there's nothing changed, fixes issue with RedirectTrackingEventHandler with regards to operating outside of a web request (i.e. console app)
2016-08-05 18:55:48 +02:00
Sebastiaan Janssen aedba40b54 Updates language file to specify which integrity check we're looking at. Quotes all table names correctly. Updates description for the check. 2016-08-05 18:03:05 +02:00
Shannon 31b17e3048 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-05 17:41:13 +02:00
Shannon 42666403a6 Fixes regression issue with building the xml cache file, moves the logic to query and build the xml document for the cache to the repository level. 2016-08-05 17:41:00 +02:00
Mads Rasmussen aa66fd6e33 rewrite controller as vm + refactor controller to follow angular style guide 2016-08-05 16:59:03 +02:00
Sebastiaan Janssen 19325ac522 Fixes the build 2016-08-05 14:44:37 +02:00
Mads Rasmussen b8b30bdc6e make resource for all redirect url end points 2016-08-05 14:35:58 +02:00
Claus 69b6044bc6 fixing null check on UmbracoContext.Current in RedirectTrackingEventHandler's PageCacheRefresher_CacheUpdated. 2016-08-05 14:01:25 +02:00
Sebastiaan Janssen 18a1aa2f6f Merge pull request #1413 from umbraco/temp-U4-8530
U4-8530 Make it possbile to hide preview button by DocumentType or ContentItem
2016-08-05 13:18:29 +02:00
Shannon 92f7782ab9 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-05 13:06:49 +02:00
Shannon 3e932ecf3f fixes icon and author urls for local package install 2016-08-05 13:06:35 +02:00
Sebastiaan Janssen dd62a917fd Merge pull request #1411 from umbraco/temp-U4-8808
U4-8808 Fixing up 301 redirects
2016-08-05 13:06:18 +02:00
Sebastiaan Janssen 958e20356c Merge pull request #1412 from umbraco/temp-U4-8786
U4-8786 Member search in listview returns error (7.5-beta2)
2016-08-05 13:04:42 +02:00
Mads Rasmussen 1f8dc9a424 move dashboard from App_Plugins to dashboards folder 2016-08-05 12:36:10 +02:00
Shannon 539637720f Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-05 12:31:00 +02:00
Shannon 6a3f146da1 Fixes health check index & throbber while fixing, fixes xml data integrity check to check for invalid XML that doesn't contain a GUID 2016-08-05 12:29:05 +02:00
David Peck 7fe7f88c98 Merge pull request #1 from drpeck/U4-8814
Children added to HtmlTagWrapper twice
2016-08-05 11:14:53 +01:00
David Peck 774f00d4f5 Children added to HtmlTagWrapper twice
By calling the overload on line 884 the children are added. To do it again results in the children being added twice.
2016-08-05 11:14:01 +01:00
Sebastiaan Janssen aab2c65aaa Merge pull request #1417 from umbraco/temp-U4-8156
U4-8156 Support minimum versions for Umbraco packages
2016-08-05 11:58:38 +02:00
Sebastiaan Janssen 3dcba7a6b0 urlHash column has to be 20 chars because SHA1 uses more bytes than MD5 2016-08-05 11:51:08 +02:00
Sebastiaan Janssen 3ece30bd8b Don't let the event handlers kick in if Redirect Tracking is turned off in the config 2016-08-05 11:41:08 +02:00
Shannon 36a191464d ensures table name is quoted properly 2016-08-05 11:26:20 +02:00
Simon Busborg 9131b73cbb Merge pull request #1415 from bjarnef/dev-v7-U4-8809
Show only empty recycle bin text, when filter doesn't has a value
2016-08-05 11:14:44 +02:00
Simon Busborg 68b3ea349e Merge pull request #1414 from bjarnef/dev-v7-U4-8805
Ensure editing area use full height when it only has a little...
2016-08-05 10:53:13 +02:00
Mads Rasmussen 2f0ba3ac07 First part of html + js cleanup - use angular components in dashboard view + make js fit. 2016-08-05 10:51:32 +02:00
Claus 6c271d92f9 migration should only delete table if it is using a integer id, otherwise leave it alone. 2016-08-05 08:25:58 +02:00
bjarnef e1daa79bab Open documentation link in new browser window/tab 2016-08-04 22:35:55 +02:00
bjarnef a136235c72 Show only empty recycle bin text, when filter doesn't has a value 2016-08-04 21:10:31 +02:00
bjarnef e8e440516f Ensure editing area use full height when it only has a little or no content 2016-08-04 20:30:54 +02:00
Sebastiaan Janssen b2e7c7a8d4 More specific exception when a conversion fails 2016-08-04 19:18:52 +02:00
Shannon 2c15db5950 U4-8530 Make it possbile to hide preview button by DocumentType or ContentItem 2016-08-04 18:34:20 +02:00
Shannon 7ed240d510 Merge branch 'Phosworks-U4-8530' into temp-U4-8530 2016-08-04 18:09:00 +02:00
Shannon a91b8e0acf Merge branch 'U4-8530' of https://github.com/Phosworks/Umbraco-CMS into Phosworks-U4-8530 2016-08-04 18:08:27 +02:00
Shannon 0be81aa4e5 U4-8786 Member search in listview returns error (7.5-beta2) 2016-08-04 18:01:57 +02:00
Sebastiaan Janssen 221edc76cf Merge remote-tracking branch 'refs/remotes/origin/dev-v7' into temp-U4-8802 2016-08-04 17:49:42 +02:00
Sebastiaan Janssen 0280d832b5 Some fixing based on code review 2016-08-04 17:48:50 +02:00
Sebastiaan Janssen 875070fed8 File should not have been committed 2016-08-04 17:02:46 +02:00
Shannon 9d62b2f5f9 nuspec and nuget refs updated to latest Models Builder 2016-08-04 16:59:26 +02:00
Shannon Deminick 548c7845cb Merge pull request #1409 from umbraco/temp-U4-8779
U4-8779 Sorting not working in Members List View in 7.5 Beta2
2016-08-04 16:46:54 +02:00
Shannon 9c7052f0fd Fixed the property join for sorting on custom columns, this would have only worked if there were actual values in those columns, we fix this now with an outer join instead of an inner join 2016-08-04 16:46:46 +02:00
Sebastiaan Janssen 177b61bbf5 Merge pull request #1292 from darrenferguson/dev-v7
Fix U4-8532 - No built in Active Directory authentication in Umbraco
2016-08-04 16:25:22 +02:00
Sebastiaan Janssen 8038016b55 U4-8778 The "Link your xx account" button doesn't work because it's a form wrapped in a form 2016-08-04 15:58:19 +02:00
Claus ae0ad2becf switching to sha1 instead of md5. 2016-08-04 15:46:02 +02:00
Claus ba11de51e3 deleting through the recycle bin also deletes redirect urls. 2016-08-04 15:46:01 +02:00
Claus ccaa198e25 changing integer IDs to guid for RedirectUrls. 2016-08-04 15:46:01 +02:00
Claus 66c0d9dc12 removing migrations from solution 2016-08-04 15:45:58 +02:00
Claus 59c3d6a206 cleaning up migrations. we're deleting the table so no need to do a bunch of migration stuff instead of just compiling it into one migration deleting and creating the table again. 2016-08-04 15:45:58 +02:00
Shannon 0ab145e4ac Ensures that type="strict" is added to the package creation, does some null checking on the stylesheets packaging so ysod doesn't occur, some code formatting. 2016-08-04 15:33:26 +02:00
Shannon 423588d018 code formatting 2016-08-04 15:20:57 +02:00
Shannon Deminick 16afab86f3 Merge pull request #1407 from umbraco/temp-U4-8754
U4-8754 Single content queries like Get(int id) for content, media an…
2016-08-04 15:05:58 +02:00
Sebastiaan Janssen 43737e78fb Sorry about that! 2016-08-04 15:05:49 +02:00
Shannon Deminick f6943ceab4 Merge pull request #1408 from umbraco/temp-U4-8361-2
U4-8361 301 Url Tracking
2016-08-04 14:51:50 +02:00
Sebastiaan Janssen 6495077568 Whoops 2016-08-04 14:50:55 +02:00
Sebastiaan Janssen c61a9ee433 AppendCacheExtension needs to be AppendHeader 2016-08-04 14:46:07 +02:00
Sebastiaan Janssen b7264b58f9 Fixed the mapping for HasPublishedVersion 2016-08-04 12:19:24 +02:00
Sebastiaan Janssen ba5be0e22a Adds search function 2016-08-04 11:21:42 +02:00
Mads Rasmussen d8f68f5f9b Merge branch 'spacebetween-U4-7475-grid-tinymce-styles' into dev-v7 2016-08-04 10:32:30 +02:00
Mads Rasmussen b365a9944f Fix js errors for grunt to build 2016-08-04 10:29:36 +02:00
Simon Busborg 5b2bcdbfac Merge pull request #1399 from marcemarc/temp-u4-8772
Fixes  U4-8772, adds icon to published but changed listview items
2016-08-04 10:08:04 +02:00
Mads Rasmussen abb994cf30 Merge branch 'U4-7475-grid-tinymce-styles' of git://github.com/spacebetween/Umbraco-CMS into spacebetween-U4-7475-grid-tinymce-styles 2016-08-04 10:02:11 +02:00
Sebastiaan Janssen 6e480058b9 Adds R# rule to give a little hint when newing up a disposable 2016-08-04 09:46:48 +02:00
Simon Busborg 912a460bd8 Merge pull request #1353 from abjerner/patch-7
Added a tooltip with icon alias on mouseover
2016-08-04 09:35:38 +02:00
Sebastiaan Janssen 52d366bb6f MD5CryptoServiceProvider is disposable 2016-08-04 08:58:30 +02:00
Asbjørn Riis-Knudsen 2ddbca8861 U4-8749: Add a service to allow acces to prevalues from inline listview editor 2016-08-03 22:07:06 +02:00
Sebastiaan Janssen e66eefbbd7 Fixes unit test 2016-08-03 21:42:40 +02:00
Sebastiaan Janssen f1d9775a0f Fix the build 2016-08-03 21:15:27 +02:00
Sebastiaan Janssen 1aa2845b4a Merge pull request #1360 from marcemarc/dev-u4-8657
Closes Issue U4-8657 - Add an overload to GetDictionaryValue to provide fallback text
2016-08-03 21:08:16 +02:00
Sebastiaan Janssen 1c88117498 U4-8803 Add "Create package" back as a right-click item on the "Created Packages" node
#U4-8803 Fixed
2016-08-03 20:17:43 +02:00
Sebastiaan Janssen 6237d4a3e5 Adds a toggle to disable/enable the URL tracker
Adds paging, adapted from https://github.com/robertjf/umbMemberListView/blob/master/MemberListView/App_Plugins/MemberManager/backoffice/dashboard/memberListView.controller.js
2016-08-03 20:01:43 +02:00
Sebastiaan Janssen 77cbdcf38f js files are ignored by default, need to force add them if we really want them 2016-08-03 19:05:04 +02:00
Sebastiaan Janssen 85a3abf643 Adds a setting to be able to disable redirect URL tracking 2016-08-03 17:57:41 +02:00
Sebastiaan Janssen c53a04d658 Needed to be fixed, just like for the ascending OrderBy - see U4-4474 2016-08-03 17:57:41 +02:00
Sebastiaan Janssen b4d5140d07 WIP Starting with taking Marc's code to get a rudimentary dashboard for the 301 URL tracker 2016-08-03 17:57:01 +02:00
Sebastiaan Janssen 11cafa2c4c Adds a setting to be able to disable redirect URL tracking 2016-08-03 17:54:21 +02:00
Sebastiaan Janssen a5f3b50699 Needed to be fixed, just like for the ascending OrderBy - see U4-4474 2016-08-03 17:52:27 +02:00
Shannon 00bc454080 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-08-03 14:04:33 +02:00
Shannon 67cd4aeb59 fixes user mgr logic 2016-08-03 14:04:25 +02:00
Claus b4ea03cdf3 U4-8779 Sorting not working in Members List View in 7.5 Beta2 2016-08-03 12:43:46 +02:00
Mads Rasmussen c8d7a62a47 Fixes: U4-8747 Actions menu button not aligned with heading input 2016-08-03 09:53:55 +02:00
Sebastiaan Janssen b9fcda8f39 U4-8361 301 Url Tracking
Adds the ability to add certain headers to a PublishedContentRequest - these are internal for now until we're sure we want to expose them
Adds response headers to tell browsers not to cache the 301 redirects so people can easily change their mind later
2016-08-02 17:01:32 +02:00
Sebastiaan Janssen e020779a14 U4-8751 GetCropUrl method should have a parameter for specifying the image format
Additional fix asking for InvariantContains instead of just Contains
2016-08-02 15:07:25 +02:00
Sebastiaan Janssen d611ae85e1 Merge pull request #1398 from arknu/U4-8751_2
U4-8751: Put format parameter at the end when format is specified in furtherOptions
2016-08-02 14:57:38 +02:00
Sebastiaan Janssen 2df8f55032 U4-8794 Allow Newtosoft JSON 9.0.1 to be installed
#U4-8794 Fixed
2016-08-02 14:45:57 +02:00
Sebastiaan Janssen 6788e8954e U4-8509 woff2 mime type 2016-08-02 14:37:08 +02:00
Sebastiaan Janssen 080da771ff U4-8457 Ensure <MacroErrors> default is updated from legacy inline setting to newer throw setting
#U4-8457 Fixed
2016-08-02 14:37:08 +02:00
Sebastiaan Janssen 08b3b635b4 Merge pull request #1305 from electricsheep/U4-8336
U4-8509 - Added woff2 mime type
2016-08-02 14:36:58 +02:00
Mads Rasmussen 8e411069f4 Merge pull request #1318 from umbraco/temp-U4-8584
Temp u4 8584
2016-08-02 13:26:34 +02:00
Claus 7d0c92937a U4-8754 Single content queries like Get(int id) for content, media and members needs to execute a TOP 1 (or LIMIT 1)
updated a bunch of the remaining repositories to also use this pattern where applicable (repos using mappers aren't compatible without more work).
2016-08-02 12:11:35 +02:00
Simon Busborg 1ca6674095 Fixes http://issues.umbraco.org/issue/U4-8770 2016-08-02 09:41:01 +02:00
Shannon 3ebb3dc544 U4-7813 Enable MiniProfiler to profiler during startup 2016-08-01 12:04:02 +02:00
Asbjørn Riis-Knudsen 1f6caa0164 U4-8749: add back some acceidentally deleted code to deal with existing values 2016-07-30 00:35:06 +02:00
Asbjørn Riis-Knudsen 6adccb66dd U4-8749: Use watch do dynamically refresh sort column list 2016-07-30 00:30:50 +02:00
Asbjørn Riis-Knudsen 6837dd2ce8 U4-8749: One more fix by @AndyButland 2016-07-29 23:55:20 +02:00
Asbjørn Riis-Knudsen b686fa74c9 U4-8749: Fixes by @AndyButland 2016-07-29 23:42:59 +02:00
Claus 22d12f3abc Merge branch 'bjarnef-dev-v7-U4-8488' into dev-v7 2016-07-29 11:23:36 +02:00
Claus bb4671faf1 Merge branch 'dev-v7-U4-8488' of git://github.com/bjarnef/Umbraco-CMS into bjarnef-dev-v7-U4-8488
Conflicts:
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js
2016-07-29 11:22:13 +02:00
Claus 57d2901c2e Merge pull request #1405 from umbraco/temp-U4-8367
U4-8367 Breadcrumb and save button breaks layout.
2016-07-29 10:48:31 +02:00
Claus 9914ab6c59 Merge branch 'bjarnef-dev-v7-U4-8748' into dev-v7 2016-07-29 10:38:33 +02:00
Claus ccd03cb1f2 fixes overlay width on small screens (mads). 2016-07-29 10:38:00 +02:00
Claus 89fd31085c Merge branch 'dev-v7-U4-8748' of git://github.com/bjarnef/Umbraco-CMS into bjarnef-dev-v7-U4-8748 2016-07-29 10:30:18 +02:00
Asbjørn Riis-Knudsen e53b81b627 U4-8749: Remove commented out code 2016-07-28 22:21:21 +02:00
Asbjørn Riis-Knudsen 385c53936e U4-8749: Initial implementation of the default sort order using the columns added instead of a fixed list 2016-07-28 22:18:17 +02:00
Mads Rasmussen be8a52e7b6 fix positioning of sub header when scrolling 2016-07-28 12:34:04 +02:00
Mads Rasmussen 3cdf80a82b change main editor from absolute positioning to flex box. Sets auto height on editor footer so it can expand 2016-07-28 12:33:32 +02:00
Mads Rasmussen b631db14c3 show full breadcrumb item on hover 2016-07-28 12:26:52 +02:00
Mads Rasmussen 5f7859a8c1 truncate breadcrumb items 2016-07-28 12:25:58 +02:00
Claus 1a2f7b8788 Merge branch 'dev-v7' of github.com:umbraco/Umbraco-CMS into dev-v7 2016-07-27 14:18:39 +02:00
Claus 39aca137a4 Merge branch 'temp-U4-8601' into dev-v7
Conflicts:
	src/Umbraco.Web.UI.Client/src/views/dashboard/developer/healthcheck.controller.js
	src/Umbraco.Web.UI.Client/src/views/dashboard/developer/healthcheck.html
2016-07-27 14:18:21 +02:00
Warren Buckley 88c6b0450e Merge pull request #1401 from umbraco/temp-U4-8733
U4-8733 Trying to include a stylesheet in a package results in a YSOD
2016-07-27 13:18:07 +01:00
Claus 9ae339f17b removing a console.log.
whitespace and some formatting.
2016-07-27 13:59:10 +02:00
Mads Rasmussen b1f13cdbb2 health check overview - hide status when group is loading 2016-07-27 13:15:22 +02:00
Mads Rasmussen 1636c16954 move loading indicator one level up in detail view, so it's visible first time the checks are run. 2016-07-27 12:40:45 +02:00
Claus f7f736fe63 Merge pull request #1403 from umbraco/temp-U4-8780
U4-8780 Error migrating from 7.2.2 -> 7.5 beta 2 - cmsStylesheetProperty invalid object name
2016-07-27 11:04:10 +02:00
bjarnef ba6736dbb3 Fix correct syntax of calc function in less 2016-07-27 10:31:18 +02:00
Mads Rasmussen 29be571afd Add button to check all groups + a bit of style polish 2016-07-27 09:31:01 +02:00
bjarnef c5b9e6a194 Load svg in <object> to have access to events and be able to manipulate svg 2016-07-27 01:36:17 +02:00
Jeremy Pyne 2cad3838f4 Update ExpressionTests.cs
Fixes for SQL replace test.
2016-07-26 10:27:19 -04:00
Sebastiaan Janssen c955cce28d Because the cmsStylesheetProperty table was already deleted by an earlier migration, it can't be deleted again
However because all of this runs in one transaction, it will try anyway, we need to do this in a "local" context instead
2016-07-26 16:20:22 +02:00
Sebastiaan Janssen bb376367d6 If the umbracoMigration table does not yet exist, then get the configured version from the web.config and parse it 2016-07-26 16:19:17 +02:00
Sebastiaan Janssen a83b524130 DetermineInstalledVersionByMigrations needs to check if the table exists, not the code asking for a version 2016-07-26 16:18:00 +02:00
Claus dcdd47dff4 adding a few unit tests to MemberService. 2016-07-26 16:05:30 +02:00
Jeremy Pyne c6a2d41888 Added test. 2016-07-26 09:45:45 -04:00
bjarnef d37b65adcf Extend model with extension property, display svg in <img> and font icon for other files 2016-07-26 14:45:03 +02:00
Claus 379a0d68f7 U4-8733 Trying to include a stylesheet in a package results in a YSOD 2016-07-26 13:38:06 +02:00
Sebastiaan Janssen c206965f88 U4-8777 ImageProcessor fails to generate thumbnail for animated gif
#U4-8777 Fixed

Updates to the latest ImageProcessor to ship in the zip release
2016-07-26 12:09:05 +02:00
Mads Rasmussen 8fd1743bce only render actions div if there are any actions 2016-07-26 12:01:24 +02:00
Claus 4acfd1dcca better error message for errors when embedding media. 2016-07-26 11:31:39 +02:00
Mads Rasmussen 67234ef115 Fixes: U4-8713 New packager - avoid horizontal scrollbar for narrow screens 2016-07-26 10:34:29 +02:00
Jeremy Pyne de89f555d4 Added missing Sql mapping for standard Replace function:
.Where<MyModel>(s => s.Name.Replace(" ", "-") == userName)

Should generate valid SQL:
REPLACE([dbo].[MyModel].[Name], ' ', '-')
2016-07-25 16:46:49 -04:00
Shannon Deminick 9f36d2b7c6 Update README.md 2016-07-25 11:13:06 +02:00
Simon Busborg 2aa27dcf8c Merge pull request #1395 from bjarnef/dev-v7-U4-8746
Open link in new browser window/tab
2016-07-25 10:45:56 +02:00
Simon Busborg 43da97332c Merge pull request #1396 from bjarnef/dev-v7-U4-8765
Open documentation link in new browser window/tab
2016-07-25 10:44:48 +02:00
Marc Goodson 379661e302 Fixes U4-8772, adds HasPublishedVersion property to mapping of IContent to ContentItemBasic, then adds existing 'has-unpublished-version' css class to list view row if item is published but has unpublished changes 2016-07-25 09:17:27 +01:00
Asbjørn Riis-Knudsen 5f3f698ffd U4-8751: Put format parameter at the end when format is specified in furtherOptions 2016-07-24 18:09:06 +02:00
Sebastiaan Janssen 4ab200d538 Request elevated command promt to install git (necessary for the install to succeed) 2016-07-23 11:52:47 +02:00
bjarnef 55fad36bad Open documentation link in new browser window/tab 2016-07-22 15:13:00 +02:00
Warren Buckley 99a7aa53a1 Merge pull request #1393 from umbraco/temp-U4-8755
U4-8755 - more explicit errors when xml cache is corrupt
2016-07-22 11:47:17 +01:00
Warren Buckley d783554476 Merge pull request #1392 from umbraco/temp-u4-8756
U4-8756 - fix 7.5 beta2 upgrade
2016-07-22 10:50:28 +01:00
bjarnef 5444b65eaf Open link in new browser window/tab 2016-07-21 19:56:57 +02:00
Warren Buckley c4400a20d6 Merge pull request #1388 from umbraco/temp-u4-8720
temp-u4-8720
2016-07-21 15:48:47 +01:00
Stephan 32d59bb2bc U4-8755 - more explicit errors when xml cache is corrupt 2016-07-21 16:46:46 +02:00
Stephan 6c6c56645d U4-8720 - add documentation 2016-07-21 15:20:45 +02:00
Warren Buckley be16e84dbb Merge pull request #1386 from umbraco/temp-u4-8663
U4-8663 - fix deleting properties in doctype editor
2016-07-21 11:39:29 +01:00
Stephan a4fec9dd0f U4-8756 - fix 7.5 beta2 upgrade 2016-07-21 11:49:25 +02:00
Sebastiaan Janssen 3f2ebbda59 U4-8757 DB error installing 7.5.0 beta2 with SQL server - first escape characters, THEN wrap the password in single quotes
#U4-8757 Fixed
2016-07-21 11:24:08 +02:00
bjarnef ed392cd252 Fix issue where subsequent submit of reset password form cleared error message 2016-07-21 02:31:40 +02:00
bjarnef 0fe24a45ff Fix position of user and help dialog position and optimization in mobile layout. 2016-07-21 00:47:28 +02:00
Sebastiaan Janssen b290e6af8a Merge pull request #1385 from umbraco/temp-u4-6247
U4-6247 - fix PublicAccess repo
2016-07-20 14:02:46 +02:00
Warren Buckley 6e440f0f69 Merge pull request #1375 from bjarnef/dev-v7-U4-8696
Only add class "-light" to grid items in content.
2016-07-20 11:12:24 +01:00
Lukas Vorlicek 2eaa2b3166 U4-7475 Feature UA-1736 (element+class styles) for TinyMCE in grid
credits to @SorenA https://github.com/umbraco/Umbraco-CMS/pull/630
2016-07-19 20:38:46 +02:00
Stephan a0caab410e U4-8720 - add dynamic support, UmbracoHelper methods 2016-07-19 16:13:46 +02:00
Warren Buckley 05ebc9dfa7 Merge branch 'abjerner-patch-9' into dev-v7 2016-07-19 14:41:08 +01:00
Warren Buckley f4a2990819 Replace inline style with CSS class that achieves same result 2016-07-19 14:38:44 +01:00
Stephan dc476dcb02 U4-8720 - get typed content by guid 2016-07-19 15:38:42 +02:00
Stephan 0603cb3ab1 U4-8720 - add IPublishedContent Site, Children ext. methods 2016-07-19 15:38:42 +02:00
Warren Buckley d81a95dbdc Merge branch 'patch-9' of https://github.com/abjerner/Umbraco-CMS into abjerner-patch-9 2016-07-19 14:06:51 +01:00
Stephan 576539c774 U4-8663 - fix deleting properties in doctype editor 2016-07-19 10:46:18 +02:00
Stephan 4786a8037c U4-6247 - fix PublicAccess repo 2016-07-18 19:26:49 +02:00
Anders Bjerner e7f0eda504 Might as well have constants for the external searcher (and indexers) 2016-07-08 12:45:17 +02:00
bjarnef b9b3de0b01 Only add class "-light" to grid items in content. 2016-07-07 23:08:58 +02:00
Anders Bjerner 826b9e9cc3 Added editor alias to the list of available editors 2016-07-04 13:09:07 +02:00
bjarnef 4b08442652 Fix localization 2016-07-01 00:04:09 +02:00
Simon Busborg fdd1a89fb3 Added utilities font weight 2016-06-28 13:11:19 +02:00
Marc Goodson 29e45534c5 Add an overload to GetDictionaryValue to provide a fallback - U4-8657 2016-06-27 16:46:52 +01:00
bjarnef 889ef47fd2 Update localization of listview bulk actions 2016-06-24 00:44:45 +02:00
Anders Bjerner 8d55a55a80 Added a tooltip with icon alias on mouseover 2016-06-23 17:45:01 +02:00
Wincent 944898d6e5 http://issues.umbraco.org/issue/U4-8530
Adds Preview property to ContentItemDisplay
2016-06-21 14:18:55 +02:00
bjarnef f247e1b66f Document getByQuery 2016-06-20 19:54:46 +02:00
Shannon Deminick c81488c3fe Merge pull request #1327 from lars-erik/temp-template-editor
Unit test for template editor.
2016-06-20 10:58:03 +02:00
Per Ploug 2688e281a7 insert partial view dialog 2016-06-14 01:07:41 +02:00
Lars-Erik Aabech b853b8e89f Tests pass with karma. Won't run with R# testrunner without uncommenting stub modules, but breaks running with karma. 2016-06-14 01:03:57 +02:00
Lars-Erik Aabech 0558fbd7ff Unit test for template editor. Currently testing that masterpage and layout is set. 2016-06-13 20:51:58 +02:00
Per Ploug 8471339578 merge 2016-06-13 20:36:30 +02:00
Per Ploug 3d95c3a744 partial view dialog 2016-06-13 20:35:00 +02:00
Per Ploug 523a093776 Adds partial view picker 2016-06-13 20:12:17 +02:00
hemraker 49d5e9a29e Add page field to overview 2016-06-13 19:58:02 +02:00
hemraker 221438c5fc Fixe merge confusion 2016-06-13 19:44:05 +02:00
hemraker a29de2f910 Close pageFieldOverlay on submit 2016-06-13 19:40:54 +02:00
hemraker 8de155c1a4 Merge remote-tracking branch 'refs/remotes/origin/temp-template-editor'
Conflicts:
	src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js
	src/Umbraco.Web.UI.Client/src/views/templates/edit.html
2016-06-13 19:36:50 +02:00
hemraker 846da6763a Add page field overlay 2016-06-13 19:31:40 +02:00
Per Ploug 40c9357adb merge 2016-06-13 19:12:01 +02:00
Per Ploug fba91b203c merge 2016-06-13 19:04:22 +02:00
Per Ploug 93891a6a71 Make the template tree use the new view for create 2016-06-13 19:03:06 +02:00
Per Ploug 5091f60bb2 create template tweaks 2016-06-13 19:03:06 +02:00
Mads Rasmussen 1bbcf47d07 add "insert overlay" with insert dictionary item and insert macro 2016-06-13 18:48:26 +02:00
Lars-Erik Aabech 7ef98207cb Organize dialog can now insert sections, rendersections, renderbody, and select master.
Cursor stays where it was before editor was blurred.
2016-06-13 17:27:57 +02:00
Per Ploug 646b3c6efb Insert dictionary item dialog
Includes a way to override the tree picker as it currently thinks
everything is an entity, which it isn't
2016-06-13 17:22:11 +02:00
Lars-Erik Aabech aef659cc92 merge the merge of the fork of the fork 2016-06-13 16:05:07 +02:00
Lars-Erik Aabech a0660c6696 merged 2016-06-13 16:03:43 +02:00
Per Ploug eb0166ae7a Merge remote-tracking branch 'origin/temp-template-editor' into temp-template-editor
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/templates/edit.html
2016-06-13 16:01:31 +02:00
Lars-Erik Aabech 44cde95b47 organize controller added with list of templates for master selection 2016-06-13 16:00:33 +02:00
Per Ploug 746072a65d sample use of insert layout 2016-06-13 15:49:57 +02:00
Per Ploug f17aadccda adds setLayout to the editor 2016-06-13 15:49:00 +02:00
Per Ploug b2ea92940e Moves querybuilder to a overlay 2016-06-13 15:48:47 +02:00
Mads Rasmussen e18a668e13 add toolbar 2016-06-13 15:22:13 +02:00
Mads Rasmussen db2dafd40c make it possible to lock a description in the editor header 2016-06-13 15:19:30 +02:00
hemraker a3614fee0d Added ace to gruntFile.js 2016-06-13 13:08:33 +02:00
Claus 2e9e8f23e9 adjustments for paddings. 2016-06-12 20:40:39 +02:00
Claus a099c40d93 U4-8584 Starterkit thumbnails are not really thumbnails
adding a parameter to the image url to avoid loading a massive image when its only rendered in a thumbnail size.
2016-06-12 20:39:53 +02:00
Per Ploug 8a66943f4a Makes template tree load the new angular editor 2016-06-12 18:49:19 +02:00
Per Ploug 2368ea7cf8 Serverside template services 2016-06-12 18:49:05 +02:00
Per Ploug ebd2bf149c Basic editor + macro dialog implemented 2016-06-12 18:48:46 +02:00
Mads Rasmussen 7dfc288f93 setup view + load ace editor 2016-06-12 12:26:08 +02:00
Oliver Philpott 952ff74899 Fixed formatting for woff2 mimetype 2016-06-09 10:26:03 +01:00
Oliver Philpott 3f5729767d U4-8509 - Added woff2 mime type 2016-06-09 10:08:05 +01:00
Darren Ferguson def690b8c3 Fix U4-8532 - No built in Active Directory authentication in Umbraco 7.3+ 2016-05-30 11:15:03 +01:00
Darren Ferguson b168923d5f http://issues.umbraco.org/issue/U4-7032 : Include a password checker for Active Directory - as ability to authenticate via AD was removed in 7.3 2016-05-29 15:46:42 +01:00
Jeroen Breuer 1fc17e6f46 Fix for U4-8510 2016-05-24 17:04:39 +02:00
bjarnef 695c69af7f Updated indent 2016-05-22 21:11:51 +02:00
bjarnef 0607782028 Added localization for the new password reset stuff. 2016-05-22 21:08:21 +02:00
bjarnef 45ff11b884 Change "siten" to "sitet" 2016-05-22 14:26:37 +02:00
bjarnef e39f818389 Fix indent 2016-05-22 13:53:43 +02:00
bjarnef e2aee08959 Change back to original timeout value. 2016-05-22 13:52:02 +02:00
bjarnef 5fab1ca207 Localize move and copy overlay titles opened from listview actions. Prepare localization of bulk messages. 2016-05-22 13:46:48 +02:00
Dennis Aaen 02ffaa9ee8 Fixed issue: U4-8435 so the link is correct in settingsdashboardintro dashboard 2016-05-10 20:33:03 +02:00
Stephan 01990394dd Merge dev-v7 into dev-v7-deploy 2016-04-26 10:10:45 +02:00
Stephan bec9923c6a deploy-30 - revert unwanted change 2016-04-26 10:09:46 +02:00
Alexander Bryukhov 89cd2f50d7 Update UI language ru.xml
New area and keys for unsaved changes dialog localization (PR #1234)
New keys for list view localization PR #1235
2016-04-24 23:09:46 +06:00
Stephan 52f29a5fa1 deploy-30 - fixes 2016-04-18 12:09:32 +02:00
Stephan 179f36e2a2 deploy-30 - fixes 2016-04-15 16:36:53 +02:00
Stephan 378e8f5cd9 deploy-30 - fixes 2016-04-15 13:25:11 +02:00
Alexander Bryukhov c10534a064 Update UI language ru.xml
Missing keys & some typos found
2016-04-14 23:31:24 +06:00
Stephan 523283acd0 Merge branch 'dev-v7' into dev-v7-deploy 2016-04-14 18:28:46 +02:00
Stephan 4e9578bed4 Merge release-7.4.2 into dev-v7-deploy 2016-03-30 09:30:27 +02:00
Mads Krohn 3e46105ba8 Stupid git ... 2016-02-16 11:12:04 +01:00
Mads Krohn d8eaab2aa4 added a missing <br> to the danish translation. added current user to the changeKey text. 2016-02-16 11:03:01 +01:00
Mads Krohn ce897509ba added localization 2016-02-16 11:03:01 +01:00
Mads Krohn 330cd7a409 Check if the new key already exists. Added error message. Enhanced error handling logic. 2016-02-16 11:03:01 +01:00
unknown 56492cd1b2 implemented functionality for changing the key for dictionary items 2016-02-16 11:03:01 +01:00
Mads Krohn 9427979b1c Check if the new key already exists. Added error message. Enhanced error handling logic. 2016-02-16 00:06:56 +01:00
Mads Krohn 9d47529d20 Merge branch 'U4-205' of https://github.com/sniffdk/Umbraco-CMS into U4-205 2016-02-15 22:38:55 +01:00
unknown eec651c9d3 implemented functionality for changing the key for dictionary items 2016-02-15 22:36:19 +01:00
René Pjengaard f5ceab82f1 Update da.xml
Added translation for contentPublishedFailedAwaitingRelease
2016-02-12 14:00:45 +01:00
unknown 3921f88e30 implemented functionality for changing the key for dictionary items 2016-02-09 00:50:25 +01:00
Stephan 14adc2a3b3 deploy-30 refactoring 2016-01-26 14:18:30 +01:00
Stephan 7117414fb1 Merge origin/dev-v7 into dev-v7-deploy 2016-01-26 10:52:02 +01:00
Stephan d37cbe6309 Merge branch 'dev-v7' into dev-v7-deploy 2016-01-25 16:21:20 +01:00
Stephan ebae2ceb73 Merge 7.4.0 into dev-v7-deploy 2016-01-13 12:15:23 +01:00
Stephan f4c2437e53 Merge origin/7.4.0 into dev-v7-deploy
Conflicts:
	src/Umbraco.Core/IO/UmbracoMediaFile.cs
	src/Umbraco.Core/Media/ImageHelper.cs
	src/Umbraco.Web/Editors/ImagesController.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs
2015-12-18 18:44:57 +01:00
Stephan a05c71ec85 Fix files and medias upload 2015-12-16 17:22:34 +01:00
Stephan 02fd789f20 Sanitize UniqueId 2015-12-16 17:22:33 +01:00
Stephan e68dda81d2 Try to make sense of files and medias for Deploy 2015-12-09 16:45:40 +01:00
Stephan d3faf1d10a Merge 7.4.0 into dev-v7-deploy 2015-12-03 12:57:18 +01:00
Stephan 3e8ba73af2 Merge branch 'dev-v7-deploy' of https://github.com/umbraco/Umbraco-CMS into dev-v7-deploy 2015-12-03 12:23:13 +01:00
Stephan ee08552ad6 Merge remote-tracking branch 'origin/7.4.0' into dev-v7-deploy 2015-12-03 12:21:01 +01:00
Stephan 5772bcc7f2 Implement GetXxxFileStream for Deploy 2015-11-30 16:39:27 +01:00
Shannon b6c62af015 fixes upgrade script 2015-11-26 17:14:22 +01:00
737 changed files with 32372 additions and 13122 deletions
+2
View File
@@ -141,3 +141,5 @@ build/docs.zip
build/ui-docs.zip
build/csharp-docs.zip
build/msbuild.log
.vs/
src/packages/
+26 -14
View File
@@ -1,40 +1,52 @@
Umbraco CMS
===========
Umbraco is a free open source Content Management System built on the ASP.NET platform.
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 390,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
[![ScreenShot](vimeo.png)](https://vimeo.com/172382998/)
## Umbraco CMS ##
Umbraco is a free open source Content Management System built on the ASP.NET platform. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
## Building Umbraco from source ##
The easiest way to get started is to run `build/build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `grunt dev` in `src\Umbraco.Web.UI.Client`.
If you're interested in making changes to Belle make sure to read the [Belle ReadMe file](src/Umbraco.Web.UI.Client/README.md). Note that you can always [download a nightly build](http://nightly.umbraco.org/umbraco%207.0.0/) so you don't have to build the code yourself.
## Watch a introduction video ##
The easiest way to get started is to run `build/build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `grunt vs` in `src\Umbraco.Web.UI.Client`.
If you're interested in making changes to Belle without running Visual Studio make sure to read the [Belle ReadMe file](src/Umbraco.Web.UI.Client/README.md).
Note that you can always [download a nightly build](http://nightly.umbraco.org/?container=umbraco-750) so you don't have to build the code yourself.
## Watch an introduction video ##
[![ScreenShot](http://umbraco.com/images/whatisumbraco.png)](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
## Umbraco - the simple, flexible and friendly ASP.NET CMS ##
## Umbraco - The Friendly CMS ##
**More than 350,000 sites trust Umbraco**
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box.
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box. It's a developer's dream and your users will love it too.
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
Used by more than 350,000 active websites including [http://daviscup.com](http://daviscup.com), [http://heinz.com](http://heinz.com), [http://peugeot.com](http://peugeot.com), [http://www.hersheys.com/](http://www.hersheys.com/) and **The Official ASP.NET and IIS.NET website from Microsoft** ([http://asp.net](http://asp.net) / [http://iis.net](http://iis.net)), you can be sure that the technology is proven, stable and scales.
Used by more than 350,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 200,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
To view more examples, please visit [http://umbraco.com/why-umbraco/#caseStudies](http://umbraco.com/why-umbraco/#caseStudies)
To view more examples, please visit [https://umbraco.com/why-umbraco/#caseStudies](https://umbraco.com/why-umbraco/#caseStudies)
## Why Open Source? ##
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible and community contributions and packages are available for all to use.
## Downloading ##
The downloadable Umbraco releases live at [http://our.umbraco.org/download](http://our.umbraco.org/download).
The downloadable Umbraco releases live at [https://our.umbraco.org/download](https://our.umbraco.org/download).
## Forums ##
We have a forum running on [http://our.umbraco.org](http://our.umbraco.org). The discussions group on [Google Groups](https://groups.google.com/forum/#!forum/umbraco-dev) is for discussions on developing the core, and not on Umbraco-implementations or extensions in general. For those topics, please use [http://our.umbraco.org](http://our.umbraco.org).
Peer-to-peer support is available 24/7 at the community forum on [https://our.umbraco.org](https://our.umbraco.org).
## Contribute to Umbraco ##
If you want to contribute back to Umbraco you should check out our [guide to contributing](http://our.umbraco.org/contribute).
Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](https://our.umbraco.org/contribute).
## Found a bug? ##
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](http://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
+26 -14
View File
@@ -2,21 +2,23 @@ version: '{build}'
shallow_clone: true
build_script:
- cmd: >-
cd build
SET SLN=%CD%
SET SRC=%SLN%\src
SET PACKAGES=%SRC%\packages
CD build
SET "release="
FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i"
SET nuGetFolder=C:\Users\appveyor\.nuget\packages
..\src\.nuget\NuGet.exe sources Add -Name MyGetUmbracoCore -Source https://www.myget.org/F/umbracocore/api/v2/ >NUL
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
IF EXIST ..\src\umbraco.businesslogic\packages.config ..\src\.nuget\NuGet.exe install ..\src\umbraco.businesslogic\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Core\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
ECHO "Restoring NuGet into %PACKAGES%"
%SRC%\.nuget\NuGet.exe sources Add -Name MyGetUmbracoCore -Source https://www.myget.org/F/umbracocore/api/v2/ >NUL
%SRC%\.nuget\NuGet.exe restore %SRC%\umbraco.sln -Verbosity Quiet -NonInteractive -PackagesDirectory %PACKAGES%
ECHO Building Release %release% build%APPVEYOR_BUILD_NUMBER%
@@ -24,18 +26,28 @@ build_script:
SET MSBUILD="C:\Program Files (x86)\MSBuild\14.0\Bin\MsBuild.exe"
XCOPY "..\src\Umbraco.Tests\unit-test-log4net.CI.config" "..\src\Umbraco.Tests\unit-test-log4net.config" /Y
XCOPY "%SRC%\Umbraco.Tests\unit-test-log4net.CI.config" "%SRC%\Umbraco.Tests\unit-test-log4net.config" /Y
%MSBUILD% "..\src\Umbraco.Tests\Umbraco.Tests.csproj" /consoleloggerparameters:Summary;ErrorsOnly
%MSBUILD% "%SLN%/src/Umbraco.Tests/Umbraco.Tests.csproj" /consoleloggerparameters:Summary;ErrorsOnly;WarningsOnly /p:NugetPackagesDirectory=%PACKAGES%
build.bat nopause %release% build%APPVEYOR_BUILD_NUMBER%
build.bat -integration -release:%release% -comment:build%APPVEYOR_BUILD_NUMBER% -nugetfolder:%PACKAGES%
ECHO %PATH%
test:
assemblies: src\Umbraco.Tests\bin\Debug\Umbraco.Tests.dll
artifacts:
- path: build\UmbracoCms.*
name: UmbracoFiles
- path: build\msbuild.log
name: BuildLog
deploy:
- provider: AzureBlob
storage_account_name: umbraconightlies
storage_access_key:
secure: bmEMml2SF7QLHULiePa/a01XOeIa2SxJeXuaZ+1R27b+Vb2nNUQVYiPlUyF2cZAFSHI/zO/LekRsVU1rTescGhJjF7SSjKybymI3p+F/OWpwqiu2WfFee1ofXBFx8QHw
container: umbraco-750
artifact: UmbracoFiles
on:
branch: dev-v7
notifications:
- provider: Slack
auth_token:
+109 -30
View File
@@ -1,31 +1,95 @@
@ECHO OFF
:: UMBRACO BUILD FILE
:: ensure we have UmbracoVersion.txt
IF NOT EXIST UmbracoVersion.txt (
ECHO UmbracoVersion.txt missing!
GOTO :showerror
ECHO UmbracoVersion.txt is missing!
GOTO error
)
REM Get the version and comment from UmbracoVersion.txt lines 2 and 3
SET "release="
SET "comment="
FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i"
FOR /F "skip=2 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED comment SET "comment=%%i"
SET RELEASE=
SET COMMENT=
FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED RELEASE SET RELEASE=%%i
FOR /F "skip=2 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED COMMENT SET COMMENT=%%i
REM If there's arguments on the command line overrule UmbracoVersion.txt and use that as the version
IF [%2] NEQ [] (SET release=%2)
IF [%3] NEQ [] (SET comment=%3) ELSE (IF [%2] NEQ [] (SET "comment="))
REM process args
REM Get the "is continuous integration" from the parameters
SET "isci=0"
IF [%1] NEQ [] (SET isci=1)
SET INTEGRATION=0
SET nuGetFolder=%CD%\..\src\packages
SET SKIPNUGET=0
SET version=%release%
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
:processArgs
ECHO.
ECHO Building Umbraco %version%
ECHO.
:: grab the first parameter as a whole eg "/action:start"
:: end if no more parameter
SET SWITCHPARSE=%1
IF [%SWITCHPARSE%] == [] goto endProcessArgs
ReplaceIISExpressPortNumber.exe ..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj %release%
:: get switch and value
SET SWITCH=
SET VALUE=
FOR /F "tokens=1,* delims=: " %%a IN ("%SWITCHPARSE%") DO SET SWITCH=%%a& SET VALUE=%%b
:: route arg
IF '%SWITCH%'=='/release' GOTO argRelease
IF '%SWITCH%'=='-release' GOTO argRelease
IF '%SWITCH%'=='/comment' GOTO argComment
IF '%SWITCH%'=='-comment' GOTO argComment
IF '%SWITCH%'=='/integration' GOTO argIntegration
IF '%SWITCH%'=='-integration' GOTO argIntegration
IF '%SWITCH%'=='/nugetfolder' GOTO argNugetFolder
IF '%SWITCH%'=='-nugetfolder' GOTO argNugetFolder
IF '%SWITCH%'=='/skipnuget' GOTO argSkipNuget
IF '%SWITCH%'=='-skipnuget' GOTO argSkipNuget
ECHO "Invalid switch %SWITCH%"
GOTO error
:: handle each arg
:argRelease
set RELEASE=%VALUE%
SHIFT
goto processArgs
:argComment
SET COMMENT=%VALUE%
SHIFT
GOTO processArgs
:argIntegration
SET INTEGRATION=1
SHIFT
GOTO processArgs
:argNugetFolder
SET nuGetFolder=%VALUE%
SHIFT
GOTO processArgs
:argSkipNuget
SET SKIPNUGET=1
SHIFT
GOTO processArgs
:endProcessArgs
REM run
SET VERSION=%RELEASE%
IF [%COMMENT%] EQU [] (SET VERSION=%RELEASE%) ELSE (SET VERSION=%RELEASE%-%COMMENT%)
ECHO ################################################################
ECHO Building Umbraco %VERSION%
ECHO ################################################################
SET MSBUILDPATH=C:\Program Files (x86)\MSBuild\14.0\Bin
SET MSBUILD="%MSBUILDPATH%\MsBuild.exe"
SET PATH="%MSBUILDPATH%";%PATH%
ReplaceIISExpressPortNumber.exe ..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj %RELEASE%
ECHO.
ECHO Removing the belle build folder and bower_components folder to make sure everything is clean as a whistle
@@ -35,10 +99,10 @@ RD ..\src\Umbraco.Web.UI.Client\bower_components /Q /S
ECHO.
ECHO Removing existing built files to make sure everything is clean as a whistle
RMDIR /Q /S _BuildOutput
DEL /F /Q UmbracoCms.*.zip
DEL /F /Q UmbracoExamine.*.zip
DEL /F /Q UmbracoCms.*.nupkg
DEL /F /Q webpihash.txt
DEL /F /Q UmbracoCms.*.zip 2>NUL
DEL /F /Q UmbracoExamine.*.zip 2>NUL
DEL /F /Q UmbracoCms.*.nupkg 2>NUL
DEL /F /Q webpihash.txt 2>NUL
ECHO.
ECHO Making sure Git is in the path so that the build can succeed
@@ -47,11 +111,21 @@ CALL InstallGit.cmd
REM Adding the default Git path so that if it's installed it can actually be found
REM This is necessary because SETLOCAL is on in InstallGit.cmd so that one might find Git,
REM but the path setting is lost due to SETLOCAL
path=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
SET PATH="C:\Program Files (x86)\Git\cmd";"C:\Program Files\Git\cmd";%PATH%
ECHO.
ECHO Making sure we have a web.config
IF NOT EXIST %CD%\..\src\Umbraco.Web.UI\web.config COPY %CD%\..\src\Umbraco.Web.UI\web.Template.config %CD%\..\src\Umbraco.Web.UI\web.config
IF NOT EXIST "%CD%\..\src\Umbraco.Web.UI\web.config" COPY "%CD%\..\src\Umbraco.Web.UI\web.Template.config" "%CD%\..\src\Umbraco.Web.UI\web.config"
ECHO.
ECHO Reporting NuGet version
"%CD%\..\src\.nuget\NuGet.exe" help | findstr "^NuGet Version:"
ECHO.
ECHO Restoring NuGet packages
ECHO Into %nuGetFolder%
"%CD%\..\src\.nuget\NuGet.exe" restore "%CD%\..\src\umbraco.sln" -Verbosity Quiet -NonInteractive -PackagesDirectory "%nuGetFolder%"
IF ERRORLEVEL 1 GOTO :error
ECHO.
ECHO.
@@ -60,13 +134,15 @@ ECHO This takes a few minutes and logging is set to report warnings
ECHO and errors only so it might seems like nothing is happening for a while.
ECHO You can check the msbuild.log file for progress.
ECHO.
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment% /p:NugetPackagesDirectory=%nuGetFolder% /consoleloggerparameters:Summary;ErrorsOnly;WarningsOnly /fileLogger
IF ERRORLEVEL 1 GOTO :error
%MSBUILD% "Build.proj" /p:BUILD_RELEASE=%RELEASE% /p:BUILD_COMMENT=%COMMENT% /p:NugetPackagesDirectory="%nuGetFolder%" /consoleloggerparameters:Summary;ErrorsOnly /fileLogger
IF ERRORLEVEL 1 GOTO error
ECHO.
ECHO Setting node_modules folder to hidden to prevent VS13 from crashing on it while loading the websites project
attrib +h ..\src\Umbraco.Web.UI.Client\node_modules
IF %SKIPNUGET% EQU 1 GOTO success
ECHO.
ECHO Adding Web.config transform files to the NuGet package
REN .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
@@ -74,22 +150,25 @@ REN .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
ECHO.
ECHO Packing the NuGet release files
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version% -Symbols -Verbosity quiet
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %version% -Verbosity quiet
IF ERRORLEVEL 1 GOTO :error
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %VERSION% -Symbols -Verbosity quiet
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %VERSION% -Verbosity quiet
IF ERRORLEVEL 1 GOTO error
:success
ECHO.
ECHO No errors were detected!
ECHO There may still be some in the output, which you would need to investigate.
ECHO Warnings are usually normal.
ECHO.
ECHO.
GOTO :EOF
:error
ECHO.
ECHO Errors were detected!
ECHO.
REM don't pause if continuous integration else the build server waits forever
REM before cancelling the build (and, there is noone to read the output anyways)
IF isci NEQ 1 PAUSE
IF %INTEGRATION% NEQ 1 PAUSE
+18 -20
View File
@@ -1,8 +1,8 @@
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
<!--
****************************************************
INCLUDES
INCLUDES
*****************************************************
-->
@@ -35,9 +35,9 @@
{
using (var cryptoProvider = new SHA1CryptoServiceProvider())
{
var fileHash = cryptoProvider.ComputeHash(stream);
using (TextWriter w = new StreamWriter(OutputFile, false))
{
w.WriteLine(string.Join("", fileHash.Select(b => b.ToString("x2"))));
@@ -52,9 +52,9 @@
</UsingTask>
<!--
<!--
****************************************************
VARIABLES
VARIABLES
*****************************************************
-->
@@ -102,9 +102,9 @@
<SystemFolders Include="$(WebAppFolder)Views" />
</ItemGroup>
<!--
<!--
****************************************************
TARGETS
TARGETS
*****************************************************
-->
@@ -155,7 +155,7 @@
<Message Text="Finished zipping to build\$(BuildFolder)\$(buildDate)-$(BuildZipFileName)" Importance="high" />
</Target>
<Target Name="CreateSystemFolders" DependsOnTargets="CopyBelleBuild" Inputs="@(SystemFolders)" Outputs="%(Identity).Dummy">
<MakeDir Directories="@(SystemFolders)" />
</Target>
@@ -231,7 +231,7 @@
DestinationFiles="@(CustomLanguageFiles->'$(ConfigsFolder)Lang\%(RecursiveDir)%(Filename)%(Extension)')"
OverwriteReadOnlyFiles="true"
SkipUnchangedFiles="false" />
<Copy SourceFiles="@(WebConfigTransformFile)"
DestinationFiles="$(ConfigsFolder)Web.config.transform"
OverwriteReadOnlyFiles="true"
@@ -264,14 +264,12 @@
<Message Text="Compiling web project to build\$(BuildFolder)" Importance="high" />
<!-- For UseWPP_CopyWebApplication=True see http://stackoverflow.com/questions/1983575/copywebapplication-with-web-config-transformations -->
<!-- Build the Umbraco.Web.UI project -->
<MSBuild Projects="..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj" Properties="WarningLevel=0;Configuration=$(BuildConfiguration);UseWPP_CopyWebApplication=True;PipelineDependsOnBuild=False;OutDir=$(SolutionBinFolderAbsolutePath);WebProjectOutputDir=$(WebAppFolderAbsolutePath);Verbosity=minimal" Targets="Clean;Rebuild;" BuildInParallel="False" ToolsVersion="4.0" UnloadProjectsOnCompletion="False">
</MSBuild>
<MSBuild Projects="..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj" Properties="WarningLevel=0;Configuration=$(BuildConfiguration);UseWPP_CopyWebApplication=True;PipelineDependsOnBuild=False;OutDir=$(SolutionBinFolderAbsolutePath);WebProjectOutputDir=$(WebAppFolderAbsolutePath);Verbosity=minimal" Targets="Clean;Rebuild;" BuildInParallel="False" ToolsVersion="4.0" UnloadProjectsOnCompletion="False" />
<!-- DONE -->
<Message Text="Finished compiling projects" Importance="high" />
</Target>
<Target Name="SetVersionNumber" Condition="'$(BUILD_RELEASE)'!=''">
<PropertyGroup>
<NewVersion>$(BUILD_RELEASE)</NewVersion>
@@ -307,34 +305,34 @@
ReplacementText="AssemblyFileVersion(&quot;$(BUILD_RELEASE)&quot;)"/>
<!--This updates the AssemblyInformationalVersion for the solution to the umbraco version and comment-->
<FileUpdate
<FileUpdate
Condition="'$(BUILD_COMMENT)'!=''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)-$(BUILD_COMMENT)&quot;)"/>
<FileUpdate
<FileUpdate
Condition="'$(BUILD_COMMENT)'==''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)&quot;)"/>
<FileUpdate
<FileUpdate
Condition="'$(BUILD_NIGHTLY)'!=''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)-$(BUILD_NIGHTLY)&quot;)"/>
<FileUpdate
<FileUpdate
Condition="'$(BUILD_COMMENT)'!='' AND '$(BUILD_NIGHTLY)'!=''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)-$(BUILD_COMMENT)-$(BUILD_NIGHTLY)&quot;)"/>
<FileUpdate
<FileUpdate
Condition="'$(BUILD_COMMENT)'=='' AND '$(BUILD_NIGHTLY)'==''"
Files="..\src\SolutionInfo.cs"
Regex="AssemblyInformationalVersion\(&quot;(.+)?&quot;\)"
ReplacementText="AssemblyInformationalVersion(&quot;$(BUILD_RELEASE)&quot;)"/>
<!--This updates the copyright year-->
<FileUpdate
<FileUpdate
Files="..\src\SolutionInfo.cs"
Regex="AssemblyCopyright\(&quot;Copyright © Umbraco (\d{4})&quot;\)"
ReplacementText="AssemblyCopyright(&quot;Copyright © Umbraco $([System.DateTime]::Now.ToString(`yyyy`))&quot;)"/>
+41 -10
View File
@@ -3,21 +3,31 @@ SETLOCAL
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
git.exe --version
if %ERRORLEVEL%==9009 GOTO :trydefaultpath
IF %ERRORLEVEL%==9009 GOTO :trydefaultpath
REM OK, DONE
GOTO :EOF
:trydefaultpath
path=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
PATH=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
git.exe --version
if %ERRORLEVEL%==9009 GOTO :showerror
IF %ERRORLEVEL%==9009 GOTO :showerror
REM OK, DONE
GOTO :EOF
:showerror
ECHO Git is not in your path and could not be found in C:\Program Files (x86)\Git\cmd nor in C:\Program Files\Git\cmd
set /p install=" Do you want to install Git through Chocolatey [y/n]? " %=%
if %install%==y (
SET /p install=" Do you want to install Git through Chocolatey [y/n]? " %=%
IF %install%==y (
:: Create a temporary batch file to execute either after elevating to admin or as-is when the user is already admin
ECHO @ECHO OFF > "%temp%\ChocoInstallGit.cmd"
ECHO SETLOCAL >> "%temp%\ChocoInstallGit.cmd"
ECHO ECHO Installing Chocolatey first >> "%temp%\ChocoInstallGit.cmd"
ECHO @powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" >> "%temp%\ChocoInstallGit.cmd"
ECHO SET PATH=%%PATH%%;%%ALLUSERSPROFILE%%\chocolatey\bin >> "%temp%\ChocoInstallGit.cmd"
ECHO choco install git -y >> "%temp%\ChocoInstallGit.cmd"
GOTO :installgit
) else (
) ELSE (
GOTO :cantcontinue
)
@@ -26,7 +36,28 @@ ECHO Can't complete the build without Git being in the path. Please add it to be
GOTO :EOF
:installgit
ECHO Installing Chocolatey first
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
ECHO Installing Git through Chocolatey
choco install git
pushd %~dp0
:: Running prompt elevated
:: --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
:: --> If error flag set, we do not have admin.
IF '%errorlevel%' NEQ '0' (
GOTO UACPrompt
) ELSE ( GOTO gotAdmin )
:UACPrompt
ECHO You're not currently running this with admin privileges, we'll now try to execute the install of Git through Chocolatey after elevating to admin privileges
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
ECHO UAC.ShellExecute "%temp%\ChocoInstallGit.cmd", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
EXIT /B
:gotAdmin
IF EXIST "%temp%\getadmin.vbs" ( DEL "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
CALL "%temp%\ChocoInstallGit.cmd"
+8 -7
View File
@@ -27,18 +27,19 @@
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
<dependency id="MySql.Data" version="[6.9.8, 7.0.0)" />
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
<dependency id="ClientDependency" version="[1.9.0-beta4, 2.0.0)" />
<dependency id="ClientDependency" version="[1.9.2, 2.0.0)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0, 2.0.0)" />
<!-- AutoMapper can not be updated due to: https://github.com/AutoMapper/AutoMapper/issues/373#issuecomment-127644405 -->
<dependency id="AutoMapper" version="[3.0.0, 3.1.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 9.0.0)" />
<dependency id="Examine" version="[0.1.69-beta, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.4.3, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.6.3, 5.0.0)" />
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 10.0.0)" />
<dependency id="Examine" version="[0.1.70, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.4.5, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.6.6, 5.0.0)" />
<dependency id="semver" version="[1.1.2, 2.0.0)" />
<dependency id="UrlRewritingNet" version="[2.0.7, 3.0.0)" />
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
<dependency id="Markdown" version="[1.14.4, 2.0.0)" />
<dependency id="Markdown" version="[1.14.4, 2.0.0)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.6.0, 5.0.0)" />
</dependencies>
</metadata>
<files>
+4 -3
View File
@@ -16,8 +16,9 @@
<tags>umbraco</tags>
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 9.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.3, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 10.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.5, 4.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
</dependencies>
</metadata>
<files>
@@ -45,4 +46,4 @@
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" />
<file src="build\**" target="build" />
</files>
</package>
</package>
@@ -21,6 +21,12 @@
</section>
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<areas xdt:Transform="InsertIfMissing">
<area xdt:Transform="InsertIfMissing">developer</area>
</areas>
</section>
<section alias="StartupDeveloperDashboardSection">
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Replace">
<control showOnce="true" addPanel="true" panelCaption="">
views/dashboard/developer/developerdashboardvideos.html
@@ -30,16 +36,21 @@
</section>
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
<control>
views/dashboard/developer/examinemanagement.html
</control>
</tab>
<tab caption="Xml Data Integrity Report" xdt:Transform="InsertIfMissing">
</tab>
<tab caption="Health Check" xdt:Transform="InsertIfMissing" xdt:Locator="Match(caption)">
<control>
views/dashboard/developer/xmldataintegrityreport.html
views/dashboard/developer/healthcheck.html
</control>
</tab>
</tab>
<tab caption="Redirect URL Management" xdt:Transform="InsertIfMissing" xdt:Locator="Match(caption)">
<control>
views/dashboard/developer/redirecturls.html
</control>
</tab>
</section>
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
@@ -52,19 +63,6 @@
</tab>
</section>
<section alias="StartupDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Get Started" xdt:Transform="Insert">
<access>
<grant>admin</grant>
</access>
<control showOnce="true" addPanel="true" panelCaption="">
views/dashboard/default/startupdashboardintro.html
</control>
</tab>
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
</section>
<section alias="StartupMemberDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Get Started" xdt:Transform="Insert">
@@ -80,5 +78,6 @@
<section alias="StartupDashboardSection">
<tab caption="Change Password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
</section>
</dashBoard>
+8 -1
View File
@@ -292,6 +292,8 @@
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<remove fileExtension=".woff" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<mimeMap fileExtension=".woff" mimeType="application/x-font-woff" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<remove fileExtension=".woff2" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<mimeMap fileExtension=".woff2" mimeType="application/x-font-woff2" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<remove fileExtension=".less" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<mimeMap fileExtension=".less" mimeType="text/css" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
</staticContent>
@@ -317,6 +319,7 @@
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='HtmlAgilityPack')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='AutoMapper')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="Remove" />
@@ -332,10 +335,14 @@
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.9.0" newVersion="1.4.9.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.3.1.0" newVersion="3.3.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
+17 -9
View File
@@ -55,21 +55,29 @@
xdt:Transform="SetAttributes()" />
<!--Developer-->
<add alias="datatype" application="developer"
<add alias="packager" application="developer"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add initialize="true" sortOrder="0" alias="datatypes" application="developer" title="Data Types" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco"
<add alias="packagerPackages" application="developer"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
xdt:Transform="Remove" />
<add initialize="true" sortOrder="0" alias="packager" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.PackagesTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<!-- Before 7.4 this tree had the alias 'dataType', without the 's' on the end, this is here to rename it -->
<add sortOrder="1" alias="dataTypes" application="developer" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco"
xdt:Locator="Match(application,type)"
xdt:Transform="SetAttributes(alias,sortOrder)" />
<!-- Yes, set the sortOrder again, like above because.. sometimes apparently we already have a dataTypes node and we can't remove more than one.. if they're equal though (same alias,application and sortOrder) it doesn't throw an error -->
<add sortOrder="1" alias="dataTypes" application="developer"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes(sortOrder)" />
<add application="developer" alias="macros" title="Macros" type="umbraco.loadMacros, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="packager" title="Packages" type="umbraco.loadPackager, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="packagerPackages" title="Packager Packages" type="umbraco.loadPackages, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" initialize="false" sortOrder="3"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
+3 -3
View File
@@ -1,3 +1,3 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.5.0
beta2
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.6.0
alpha038
Binary file not shown.
+24 -11
View File
@@ -180,12 +180,16 @@ namespace SqlCE4Umbraco
/// <returns>The return value of the command.</returns>
protected override object ExecuteScalar(string commandText, SqlCeParameter[] parameters)
{
#if DEBUG && DebugDataLayer
#if DEBUG && DebugDataLayer
// Log Query Execution
Trace.TraceInformation(GetType().Name + " SQL ExecuteScalar: " + commandText);
#endif
return SqlCeApplicationBlock.ExecuteScalar(ConnectionString, CommandType.Text, commandText, parameters);
#endif
using (var cc = UseCurrentConnection)
{
return SqlCeApplicationBlock.ExecuteScalar(
(SqlCeConnection) cc.Connection, (SqlCeTransaction) cc.Transaction,
CommandType.Text, commandText, parameters);
}
}
/// <summary>
@@ -198,12 +202,17 @@ namespace SqlCE4Umbraco
/// </returns>
protected override int ExecuteNonQuery(string commandText, SqlCeParameter[] parameters)
{
#if DEBUG && DebugDataLayer
#if DEBUG && DebugDataLayer
// Log Query Execution
Trace.TraceInformation(GetType().Name + " SQL ExecuteNonQuery: " + commandText);
#endif
#endif
return SqlCeApplicationBlock.ExecuteNonQuery(ConnectionString, CommandType.Text, commandText, parameters);
using (var cc = UseCurrentConnection)
{
return SqlCeApplicationBlock.ExecuteNonQuery(
(SqlCeConnection) cc.Connection, (SqlCeTransaction) cc.Transaction,
CommandType.Text, commandText, parameters);
}
}
/// <summary>
@@ -216,13 +225,17 @@ namespace SqlCE4Umbraco
/// </returns>
protected override IRecordsReader ExecuteReader(string commandText, SqlCeParameter[] parameters)
{
#if DEBUG && DebugDataLayer
#if DEBUG && DebugDataLayer
// Log Query Execution
Trace.TraceInformation(GetType().Name + " SQL ExecuteReader: " + commandText);
#endif
#endif
return new SqlCeDataReaderHelper(SqlCeApplicationBlock.ExecuteReader(ConnectionString, CommandType.Text,
commandText, parameters));
using (var cc = UseCurrentConnection)
{
return new SqlCeDataReaderHelper(SqlCeApplicationBlock.ExecuteReader(
(SqlCeConnection) cc.Connection, (SqlCeTransaction) cc.Transaction,
CommandType.Text, commandText, parameters));
}
}
+24 -22
View File
@@ -21,15 +21,15 @@ namespace SqlCE4Umbraco
public class SqlCEInstaller : DefaultInstallerUtility<SqlCEHelper>
{
#region Private Constants
/// <summary>The latest database version this installer supports.</summary>
private const DatabaseVersion LatestVersionSupported = DatabaseVersion.Version4_8;
/// <summary>The specifications to determine the database version.</summary>
private static readonly VersionSpecs[] m_VersionSpecs = new VersionSpecs[] {
new VersionSpecs("SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS LEFT OUTER JOIN umbracoApp ON appAlias = appAlias WHERE CONSTRAINT_NAME = 'FK_umbracoUser2app_umbracoApp'", 0, DatabaseVersion.Version4_8),
new VersionSpecs("SELECT id FROM umbracoNode WHERE id = -21", 1, DatabaseVersion.Version4_1),
new VersionSpecs("SELECT action FROM umbracoAppTree",DatabaseVersion.Version4),
new VersionSpecs("SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS LEFT OUTER JOIN umbracoApp ON appAlias = appAlias WHERE CONSTRAINT_NAME = 'FK_umbracoUser2app_umbracoApp'", 0, DatabaseVersion.Version4_8),
new VersionSpecs("SELECT id FROM umbracoNode WHERE id = -21", 1, DatabaseVersion.Version4_1),
new VersionSpecs("SELECT action FROM umbracoAppTree",DatabaseVersion.Version4),
new VersionSpecs("SELECT description FROM cmsContentType",DatabaseVersion.Version3),
new VersionSpecs("SELECT id FROM sysobjects",DatabaseVersion.None) };
@@ -43,8 +43,9 @@ namespace SqlCE4Umbraco
public override bool CanConnect
{
get
{
SqlHelper.CreateEmptyDatabase();
{
using (var sqlHelper = SqlHelper)
sqlHelper.CreateEmptyDatabase();
return base.CanConnect;
}
}
@@ -93,22 +94,22 @@ namespace SqlCE4Umbraco
#region DefaultInstaller Members
/// <summary>
/// Returns the sql to do a full install
/// </summary>
protected override string FullInstallSql
{
get { return string.Empty; }
}
/// <summary>
/// Returns the sql to do a full install
/// </summary>
protected override string FullInstallSql
{
get { return string.Empty; }
}
/// <summary>
/// Returns the sql to do an upgrade
/// </summary>
protected override string UpgradeSql
{
get { return string.Empty; }
}
/// <summary>
/// Returns the sql to do an upgrade
/// </summary>
protected override string UpgradeSql
{
get { return string.Empty; }
}
// We need to override this as the default way of detection a db connection checks for systables that doesn't exist
// in a CE db
@@ -123,8 +124,9 @@ namespace SqlCE4Umbraco
// verify connection
try
{
if (SqlCeApplicationBlock.VerifyConnection(base.SqlHelper.ConnectionString))
return DatabaseVersion.None;
using (var sqlHelper = SqlHelper)
if (SqlCeApplicationBlock.VerifyConnection(sqlHelper.ConnectionString))
return DatabaseVersion.None;
}
catch (Exception e)
{
+17 -11
View File
@@ -37,13 +37,15 @@ namespace SqlCE4Umbraco
ITable table = null;
// get name in correct casing
name = SqlHelper.ExecuteScalar<string>("SELECT name FROM sys.tables WHERE name=@name",
SqlHelper.CreateParameter("name", name));
using (var sqlHelper = SqlHelper)
name = sqlHelper.ExecuteScalar<string>("SELECT name FROM sys.tables WHERE name=@name",
sqlHelper.CreateParameter("name", name));
if (name != null)
{
table = new DefaultTable(name);
using (IRecordsReader reader = SqlHelper.ExecuteReader(
using (var sqlHelper = SqlHelper)
using (IRecordsReader reader = sqlHelper.ExecuteReader(
@"SELECT c.name AS Name, st.name AS DataType, c.max_length, c.is_nullable, c.is_identity
FROM sys.tables AS t
JOIN sys.columns AS c ON t.object_id = c.object_id
@@ -51,7 +53,7 @@ namespace SqlCE4Umbraco
JOIN sys.types AS ty ON ty.user_type_id = c.user_type_id
JOIN sys.types st ON ty.system_type_id = st.user_type_id
WHERE t.name = @name
ORDER BY c.column_id", SqlHelper.CreateParameter("name", name)))
ORDER BY c.column_id", sqlHelper.CreateParameter("name", name)))
{
while (reader.Read())
{
@@ -112,7 +114,8 @@ namespace SqlCE4Umbraco
// create query
StringBuilder createTableQuery = new StringBuilder();
createTableQuery.AppendFormat("CREATE TABLE [{0}] (", SqlHelper.EscapeString(table.Name));
using (var sqlHelper = SqlHelper)
createTableQuery.AppendFormat("CREATE TABLE [{0}] (", sqlHelper.EscapeString(table.Name));
// add fields
while (hasNext)
@@ -136,7 +139,8 @@ namespace SqlCE4Umbraco
// execute query
try
{
SqlHelper.ExecuteNonQuery(createTableQuery.ToString());
using (var sqlHelper = SqlHelper)
sqlHelper.ExecuteNonQuery(createTableQuery.ToString());
}
catch (Exception executeException)
{
@@ -154,13 +158,15 @@ namespace SqlCE4Umbraco
Debug.Assert(table != null && field != null);
StringBuilder addColumnQuery = new StringBuilder();
addColumnQuery.AppendFormat("ALTER TABLE [{0}] ADD [{1}] {2}",
SqlHelper.EscapeString(table.Name),
SqlHelper.EscapeString(field.Name),
SqlHelper.EscapeString(GetDatabaseType(field)));
using (var sqlHelper = SqlHelper)
addColumnQuery.AppendFormat("ALTER TABLE [{0}] ADD [{1}] {2}",
sqlHelper.EscapeString(table.Name),
sqlHelper.EscapeString(field.Name),
sqlHelper.EscapeString(GetDatabaseType(field)));
try
{
SqlHelper.ExecuteNonQuery(addColumnQuery.ToString());
using (var sqlHelper = SqlHelper)
sqlHelper.ExecuteNonQuery(addColumnQuery.ToString());
}
catch (Exception executeException)
{
+173 -91
View File
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlServerCe;
using System.Data;
using System.Diagnostics;
@@ -26,30 +24,61 @@ namespace SqlCE4Umbraco
params SqlCeParameter[] commandParameters
)
{
object retVal;
try
{
using (SqlCeConnection conn = SqlCeContextGuardian.Open(connectionString))
using (var conn = SqlCeContextGuardian.Open(connectionString))
{
using (SqlCeCommand cmd = new SqlCeCommand(commandText, conn))
{
AttachParameters(cmd, commandParameters);
Debug.WriteLine("---------------------------------SCALAR-------------------------------------");
Debug.WriteLine(commandText);
Debug.WriteLine("----------------------------------------------------------------------------");
retVal = cmd.ExecuteScalar();
}
return ExecuteScalarTry(conn, null, commandText, commandParameters);
}
return retVal;
}
catch (Exception ee)
{
throw new SqlCeProviderException("Error running Scalar: \nSQL Statement:\n" + commandText + "\n\nException:\n" + ee.ToString());
throw new SqlCeProviderException("Error running Scalar: \nSQL Statement:\n" + commandText + "\n\nException:\n" + ee);
}
}
public static object ExecuteScalar(
SqlCeConnection conn, SqlCeTransaction trx,
CommandType commandType,
string commandText,
params SqlCeParameter[] commandParameters)
{
try
{
return ExecuteScalarTry(conn, trx, commandText, commandParameters);
}
catch (Exception ee)
{
throw new SqlCeProviderException("Error running Scalar: \nSQL Statement:\n" + commandText + "\n\nException:\n" + ee);
}
}
public static object ExecuteScalar(
SqlCeConnection conn,
CommandType commandType,
string commandText,
params SqlCeParameter[] commandParameters)
{
return ExecuteScalar(conn, null, commandType, commandText, commandParameters);
}
private static object ExecuteScalarTry(
SqlCeConnection conn, SqlCeTransaction trx,
string commandText,
params SqlCeParameter[] commandParameters)
{
object retVal;
using (var cmd = trx == null ? new SqlCeCommand(commandText, conn) : new SqlCeCommand(commandText, conn, trx))
{
AttachParameters(cmd, commandParameters);
Debug.WriteLine("---------------------------------SCALAR-------------------------------------");
Debug.WriteLine(commandText);
Debug.WriteLine("----------------------------------------------------------------------------");
retVal = cmd.ExecuteScalar();
}
return retVal;
}
/// <summary>
///
/// </summary>
@@ -66,49 +95,10 @@ namespace SqlCE4Umbraco
{
try
{
int rowsAffected;
using (SqlCeConnection conn = SqlCeContextGuardian.Open(connectionString))
using (var conn = SqlCeContextGuardian.Open(connectionString))
{
// this is for multiple queries in the installer
if (commandText.Trim().StartsWith("!!!"))
{
commandText = commandText.Trim().Trim('!');
string[] commands = commandText.Split('|');
string currentCmd = String.Empty;
foreach (string cmd in commands)
{
try
{
currentCmd = cmd;
if (!String.IsNullOrWhiteSpace(cmd))
{
SqlCeCommand c = new SqlCeCommand(cmd, conn);
c.ExecuteNonQuery();
}
}
catch (Exception e)
{
Debug.WriteLine("*******************************************************************");
Debug.WriteLine(currentCmd);
Debug.WriteLine(e);
Debug.WriteLine("*******************************************************************");
}
}
return 1;
}
else
{
Debug.WriteLine("----------------------------------------------------------------------------");
Debug.WriteLine(commandText);
Debug.WriteLine("----------------------------------------------------------------------------");
SqlCeCommand cmd = new SqlCeCommand(commandText, conn);
AttachParameters(cmd, commandParameters);
rowsAffected = cmd.ExecuteNonQuery();
}
return ExecuteNonQueryTry(conn, null, commandText, commandParameters);
}
return rowsAffected;
}
catch (Exception ee)
{
@@ -116,6 +106,74 @@ namespace SqlCE4Umbraco
}
}
public static int ExecuteNonQuery(
SqlCeConnection conn,
CommandType commandType,
string commandText,
params SqlCeParameter[] commandParameters
)
{
return ExecuteNonQuery(conn, null, commandType, commandText, commandParameters);
}
public static int ExecuteNonQuery(
SqlCeConnection conn, SqlCeTransaction trx,
CommandType commandType,
string commandText,
params SqlCeParameter[] commandParameters
)
{
try
{
return ExecuteNonQueryTry(conn, trx, commandText, commandParameters);
}
catch (Exception ee)
{
throw new SqlCeProviderException("Error running NonQuery: \nSQL Statement:\n" + commandText + "\n\nException:\n" + ee.ToString());
}
}
private static int ExecuteNonQueryTry(
SqlCeConnection conn, SqlCeTransaction trx,
string commandText,
params SqlCeParameter[] commandParameters)
{
// this is for multiple queries in the installer
if (commandText.Trim().StartsWith("!!!"))
{
commandText = commandText.Trim().Trim('!');
var commands = commandText.Split('|');
var currentCmd = string.Empty;
foreach (var command in commands)
{
try
{
currentCmd = command;
if (string.IsNullOrWhiteSpace(command)) continue;
var c = trx == null ? new SqlCeCommand(command, conn) : new SqlCeCommand(command, conn, trx);
c.ExecuteNonQuery();
}
catch (Exception e)
{
Debug.WriteLine("*******************************************************************");
Debug.WriteLine(currentCmd);
Debug.WriteLine(e);
Debug.WriteLine("*******************************************************************");
}
}
return 1;
}
Debug.WriteLine("----------------------------------------------------------------------------");
Debug.WriteLine(commandText);
Debug.WriteLine("----------------------------------------------------------------------------");
var cmd = new SqlCeCommand(commandText, conn);
AttachParameters(cmd, commandParameters);
var rowsAffected = cmd.ExecuteNonQuery();
return rowsAffected;
}
/// <summary>
///
/// </summary>
@@ -133,25 +191,8 @@ namespace SqlCE4Umbraco
{
try
{
Debug.WriteLine("---------------------------------READER-------------------------------------");
Debug.WriteLine(commandText);
Debug.WriteLine("----------------------------------------------------------------------------");
SqlCeDataReader reader;
SqlCeConnection conn = SqlCeContextGuardian.Open(connectionString);
try
{
SqlCeCommand cmd = new SqlCeCommand(commandText, conn);
AttachParameters(cmd, commandParameters);
reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch
{
conn.Close();
throw;
}
return reader;
var conn = SqlCeContextGuardian.Open(connectionString);
return ExecuteReaderTry(conn, null, commandText, commandParameters);
}
catch (Exception ee)
{
@@ -159,30 +200,71 @@ namespace SqlCE4Umbraco
}
}
public static bool VerifyConnection(string connectionString)
public static SqlCeDataReader ExecuteReader(
SqlCeConnection conn,
CommandType commandType,
string commandText,
params SqlCeParameter[] commandParameters
)
{
bool isConnected = false;
using (SqlCeConnection conn = SqlCeContextGuardian.Open(connectionString))
{
isConnected = conn.State == ConnectionState.Open;
}
return isConnected;
return ExecuteReader(conn, commandType, commandText, commandParameters);
}
private static void AttachParameters(SqlCeCommand command, SqlCeParameter[] commandParameters)
public static SqlCeDataReader ExecuteReader(
SqlCeConnection conn, SqlCeTransaction trx,
CommandType commandType,
string commandText,
params SqlCeParameter[] commandParameters
)
{
foreach (SqlCeParameter parameter in commandParameters)
try
{
return ExecuteReaderTry(conn, trx, commandText, commandParameters);
}
catch (Exception ee)
{
throw new SqlCeProviderException("Error running Reader: \nSQL Statement:\n" + commandText + "\n\nException:\n" + ee.ToString());
}
}
private static SqlCeDataReader ExecuteReaderTry(
SqlCeConnection conn, SqlCeTransaction trx,
string commandText,
params SqlCeParameter[] commandParameters)
{
Debug.WriteLine("---------------------------------READER-------------------------------------");
Debug.WriteLine(commandText);
Debug.WriteLine("----------------------------------------------------------------------------");
try
{
var cmd = trx == null ? new SqlCeCommand(commandText, conn) : new SqlCeCommand(commandText, conn, trx);
AttachParameters(cmd, commandParameters);
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch
{
conn.Close();
throw;
}
}
public static bool VerifyConnection(string connectionString)
{
using (var conn = SqlCeContextGuardian.Open(connectionString))
{
return conn.State == ConnectionState.Open;
}
}
private static void AttachParameters(SqlCeCommand command, IEnumerable<SqlCeParameter> commandParameters)
{
foreach (var parameter in commandParameters)
{
if ((parameter.Direction == ParameterDirection.InputOutput) && (parameter.Value == null))
{
parameter.Value = DBNull.Value;
}
command.Parameters.Add(parameter);
}
}
}
}
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.5.0")]
[assembly: AssemblyInformationalVersion("7.5.0-beta2")]
[assembly: AssemblyFileVersion("7.6.0")]
[assembly: AssemblyInformationalVersion("7.6.0-alpha038")]
+39
View File
@@ -0,0 +1,39 @@
namespace Umbraco.Core
{
public static class ByteArrayExtensions
{
private static readonly char[] BytesToHexStringLookup = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public static string ToHexString(this byte[] bytes)
{
int i = 0, p = 0, bytesLength = bytes.Length;
var chars = new char[bytesLength * 2];
while (i < bytesLength)
{
var b = bytes[i++];
chars[p++] = BytesToHexStringLookup[b / 0x10];
chars[p++] = BytesToHexStringLookup[b % 0x10];
}
return new string(chars, 0, chars.Length);
}
public static string ToHexString(this byte[] bytes, char separator, int blockSize, int blockCount)
{
int p = 0, bytesLength = bytes.Length, count = 0, size = 0;
var chars = new char[bytesLength * 2 + blockCount];
for (var i = 0; i < bytesLength; i++)
{
var b = bytes[i++];
chars[p++] = BytesToHexStringLookup[b / 0x10];
chars[p++] = BytesToHexStringLookup[b % 0x10];
if (count == blockCount) continue;
if (++size < blockSize) continue;
chars[p++] = '/';
size = 0;
count++;
}
return new string(chars, 0, chars.Length);
}
}
}
@@ -154,7 +154,7 @@ namespace Umbraco.Core.Cache
value = result.Value; // will not throw (safe lazy)
var eh = value as ExceptionHolder;
if (eh != null) throw eh.Exception; // throw once!
if (eh != null) throw new Exception("Exception while creating a value.", eh.Exception); // throw once!
return value;
}
@@ -291,7 +291,19 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
true);
}
}
[ConfigurationProperty("EnableInheritedMediaTypes")]
internal InnerTextConfigurationElement<bool> EnableInheritedMediaTypes
{
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["EnableInheritedMediaTypes"],
//set the default
true);
}
}
string IContentSection.NotificationEmailAddress
{
get { return Notifications.NotificationEmailAddress; }
@@ -431,5 +443,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return EnableInheritedDocumentTypes; }
}
bool IContentSection.EnableInheritedMediaTypes
{
get { return EnableInheritedMediaTypes; }
}
}
}
@@ -61,5 +61,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
string DefaultDocumentTypeProperty { get; }
bool EnableInheritedDocumentTypes { get; }
bool EnableInheritedMediaTypes { get; }
}
}
@@ -9,6 +9,8 @@
bool DisableAlternativeTemplates { get; }
bool DisableFindContentByIdPath { get; }
bool DisableRedirectUrlTracking { get; }
string UrlProviderMode { get; }
@@ -27,6 +27,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return (bool) base["disableFindContentByIdPath"]; }
}
[ConfigurationProperty("disableRedirectUrlTracking", DefaultValue = "false")]
public bool DisableRedirectUrlTracking
{
get { return (bool) base["disableRedirectUrlTracking"]; }
}
[ConfigurationProperty("urlProviderMode", DefaultValue = "AutoLegacy")]
public string UrlProviderMode
{
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.5.0");
private static readonly Version Version = new Version("7.6.0");
/// <summary>
/// Gets the current version of Umbraco.
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
/// Gets the version comment (like beta or RC).
/// </summary>
/// <value>The version comment.</value>
public static string CurrentComment { get { return "beta2"; } }
public static string CurrentComment { get { return "alpha038"; } }
// Get the version of the umbraco.dll by looking at a class in that dll
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
@@ -122,6 +122,11 @@ namespace Umbraco.Core
/// MediaType alias for an image.
/// </summary>
public const string Image = "Image";
/// <summary>
/// MediaType alias indicating allowing auto-selection.
/// </summary>
public const string AutoSelect = "umbracoAutoSelect";
}
/// <summary>
+20 -7
View File
@@ -1,15 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Core
namespace Umbraco.Core
{
public static partial class Constants
{
public static class Examine
{
/// <summary>
/// The alias of the internal member indexer
/// </summary>
public const string InternalMemberIndexer = "InternalMemberIndexer";
/// <summary>
/// The alias of the internal content indexer
/// </summary>
public const string InternalIndexer = "InternalIndexer";
/// <summary>
/// The alias of the external content indexer
/// </summary>
public const string ExternalIndexer = "ExternalIndexer";
/// <summary>
/// The alias of the internal member searcher
/// </summary>
@@ -19,6 +27,11 @@ namespace Umbraco.Core
/// The alias of the internal content searcher
/// </summary>
public const string InternalSearcher = "InternalSearcher";
/// <summary>
/// The alias of the external content searcher
/// </summary>
public const string ExternalSearcher = "ExternalSearcher";
}
}
}
@@ -69,6 +69,11 @@ namespace Umbraco.Core
/// </summary>
public const string Document = "C66BA18E-EAF3-4CFF-8A22-41B16D66A972";
/// <summary>
/// Guid for a Document object.
/// </summary>
public static readonly Guid DocumentGuid = new Guid(Document);
/// <summary>
/// Guid for a Document Type object.
/// </summary>
+28 -24
View File
@@ -1,33 +1,37 @@
namespace Umbraco.Core
{
public static partial class Constants
{
/// <summary>
/// Defines the identifiers for Umbraco system nodes.
/// </summary>
public static class System
{
/// <summary>
/// The integer identifier for global system root node.
/// </summary>
public const int Root = -1;
public static partial class Constants
{
/// <summary>
/// Defines the identifiers for Umbraco system nodes.
/// </summary>
public static class System
{
/// <summary>
/// The integer identifier for global system root node.
/// </summary>
public const int Root = -1;
/// <summary>
/// The integer identifier for content's recycle bin.
/// </summary>
public const int RecycleBinContent = -20;
/// <summary>
/// The integer identifier for content's recycle bin.
/// </summary>
public const int RecycleBinContent = -20;
/// <summary>
/// The integer identifier for media's recycle bin.
/// </summary>
public const int RecycleBinMedia = -21;
/// <summary>
/// The integer identifier for media's recycle bin.
/// </summary>
public const int RecycleBinMedia = -21;
public const int DefaultContentListViewDataTypeId = -95;
public const int DefaultContentListViewDataTypeId = -95;
public const int DefaultMediaListViewDataTypeId = -96;
public const int DefaultMembersListViewDataTypeId = -97;
}
// identifiers for lock objects
public const int ServersLock = -331;
}
}
public static class DatabaseProviders
{
public const string SqlCe = "System.Data.SqlServerCe.4.0";
public const string SqlServer = "System.Data.SqlClient";
public const string MySql = "MySql.Data.MySqlClient";
}
}
}
+16 -11
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Threading;
@@ -30,12 +31,13 @@ using Umbraco.Core.Manifest;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
using Umbraco.Core.Strings;
using IntegerValidator = Umbraco.Core.PropertyEditors.IntegerValidator;
using MigrationsVersionFourNineZero = Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero;
namespace Umbraco.Core
{
/// <summary>
/// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application
/// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application
/// </summary>
/// <remarks>
/// This does not provide any startup functionality relating to web objects
@@ -191,14 +193,14 @@ namespace Umbraco.Core
protected virtual CacheHelper CreateApplicationCache()
{
var cacheHelper = new CacheHelper(
//we need to have the dep clone runtime cache provider to ensure
//we need to have the dep clone runtime cache provider to ensure
//all entities are cached properly (cloned in and cloned out)
new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()),
new StaticCacheProvider(),
//we have no request based cache when not running in web-based context
new NullCacheProvider(),
new IsolatedRuntimeCache(type =>
//we need to have the dep clone runtime cache provider to ensure
//we need to have the dep clone runtime cache provider to ensure
//all entities are cached properly (cloned in and cloned out)
new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())));
@@ -251,18 +253,18 @@ namespace Umbraco.Core
}
/// <summary>
/// Special method to initialize the ApplicationEventsResolver and any modifications required for it such
/// Special method to initialize the ApplicationEventsResolver and any modifications required for it such
/// as adding custom types to the resolver.
/// </summary>
protected virtual void InitializeApplicationEventsResolver()
{
//find and initialize the application startup handlers, we need to initialize this resolver here because
//it is a special resolver where they need to be instantiated first before any other resolvers in order to bind to
//it is a special resolver where they need to be instantiated first before any other resolvers in order to bind to
//events and to call their events during bootup.
//ApplicationStartupHandler.RegisterHandlers();
//... and set the special flag to let us resolve before frozen resolution
ApplicationEventsResolver.Current = new ApplicationEventsResolver(
ServiceProvider,
ServiceProvider,
ProfilingLogger.Logger,
PluginManager.ResolveApplicationStartupHandlers())
{
@@ -282,7 +284,7 @@ namespace Umbraco.Core
}
/// <summary>
/// Fires after initialization and calls the callback to allow for customizations to occur &
/// Fires after initialization and calls the callback to allow for customizations to occur &
/// Ensure that the OnApplicationStarting methods of the IApplicationEvents are called
/// </summary>
/// <param name="afterStartup"></param>
@@ -334,7 +336,7 @@ namespace Umbraco.Core
{
if (_isComplete)
throw new InvalidOperationException("The boot manager has already been completed");
FreezeResolution();
//Here we need to make sure the db can be connected to
@@ -366,7 +368,7 @@ namespace Umbraco.Core
ProfilingLogger.Logger.Error<CoreBootManager>("An error occurred running OnApplicationStarted for handler " + x.GetType(), ex);
throw;
}
});
});
}
//Now, startup all of our legacy startup handler
@@ -455,6 +457,10 @@ namespace Umbraco.Core
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new ConfigServerRegistrar());
}
else if ("true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"]))
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new SingleServerRegistrar());
}
else
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
@@ -462,7 +468,6 @@ namespace Umbraco.Core
new Lazy<IServerRegistrationService>(() => ApplicationContext.Services.ServerRegistrationService),
new DatabaseServerRegistrarOptions()));
}
//by default we'll use the database server messenger with default options (no callbacks),
// this will be overridden in the web startup
@@ -473,7 +478,7 @@ namespace Umbraco.Core
ServiceProvider, ProfilingLogger.Logger,
() => PluginManager.ResolveAssignedMapperTypes());
//RepositoryResolver.Current = new RepositoryResolver(
// new RepositoryFactory(ApplicationCache));
+140 -108
View File
@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlServerCe;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Configuration;
using System.Xml.Linq;
using Semver;
using Umbraco.Core.Configuration;
@@ -30,17 +30,22 @@ namespace Umbraco.Core
private readonly ILogger _logger;
private readonly SqlSyntaxProviders _syntaxProviders;
private bool _configured;
private readonly object _locker = new object();
private string _connectionString;
private string _providerName;
private DatabaseSchemaResult _result;
private DateTime? _connectionLastChecked = null;
/// <summary>
/// The number of minutes to throttle the checks to CanConnect
/// </summary>
private const int ConnectionCheckMinutes = 1;
[Obsolete("Use the constructor specifying all dependencies instead")]
public DatabaseContext(IDatabaseFactory factory)
: this(factory, LoggerResolver.Current.Logger, new SqlSyntaxProviders(new ISqlSyntaxProvider[]
{
new MySqlSyntaxProvider(LoggerResolver.Current.Logger),
new SqlCeSyntaxProvider(),
new SqlCeSyntaxProvider(),
new SqlServerSyntaxProvider()
}))
{
@@ -80,21 +85,60 @@ namespace Umbraco.Core
_configured = true;
}
#if DEBUG_DATABASES
public List<UmbracoDatabase> Databases
{
get
{
var factory = _factory as DefaultDatabaseFactory;
if (factory == null) throw new NotSupportedException();
return factory.Databases;
}
}
#endif
public ISqlSyntaxProvider SqlSyntax { get; private set; }
/// <summary>
/// Gets the <see cref="Database"/> object for doing CRUD operations
/// against custom tables that resides in the Umbraco database.
/// Gets an "ambient" database for doing CRUD operations against custom tables that resides in the Umbraco database.
/// </summary>
/// <remarks>
/// This should not be used for CRUD operations or queries against the
/// standard Umbraco tables! Use the Public services for that.
/// <para>Should not be used for operation against standard Umbraco tables; as services should be used instead.</para>
/// <para>Gets or creates an "ambient" database that is either stored in http context + available for the whole
/// request + auto-disposed at the end of the request, or stored in call context if there is no http context - in which
/// case it *must* be explicitely disposed (which will remove it from call context).</para>
/// </remarks>
public virtual UmbracoDatabase Database
{
get { return _factory.CreateDatabase(); }
}
/// <summary>
/// Replaces the "ambient" database (if any) and by a new temp database.
/// </summary>
/// <remarks>
/// <para>The returned IDisposable *must* be diposed in order to properly dispose the temp database and
/// restore the original "ambient" database (if any).</para>
/// <para>This is to be used in background tasks to ensure that they have an "ambient" database which
/// will be properly removed from call context and does not interfere with anything else. In most case
/// it is not replacing anything, just temporarily installing a database in context.</para>
/// </remarks>
public virtual IDisposable UseSafeDatabase(bool force = false)
{
var factory = _factory as DefaultDatabaseFactory;
if (factory == null) throw new NotSupportedException();
if (DefaultDatabaseFactory.HasAmbientDatabase)
{
return force
? new UsingDatabase(DefaultDatabaseFactory.DetachAmbientDatabase(), factory.CreateDatabase())
: new UsingDatabase(null, null);
}
// create a new, temp, database (will be disposed with UsingDatabase)
return new UsingDatabase(null, factory.CreateDatabase());
}
/// <summary>
/// Boolean indicating whether the database has been configured
/// </summary>
@@ -110,13 +154,28 @@ namespace Umbraco.Core
{
get
{
if (IsDatabaseConfigured == false) return false;
var canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider);
LogHelper.Info<DatabaseContext>("CanConnect = " + canConnect);
return canConnect;
if (IsDatabaseConfigured == false)
return false;
//Don't check again if the timeout period hasn't elapsed
//this ensures we don't keep checking the connection too many times in a row like during startup.
//Do check if the _connectionLastChecked is null which means we're just initializing or it could
//not connect last time it was checked.
if ((_connectionLastChecked.HasValue && (DateTime.Now - _connectionLastChecked.Value).TotalMinutes > ConnectionCheckMinutes)
|| _connectionLastChecked.HasValue == false)
{
var canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider);
LogHelper.Info<DatabaseContext>("CanConnect = " + canConnect);
_connectionLastChecked = canConnect == false ? null : (DateTime?) DateTime.Now;
return canConnect;
}
return _connectionLastChecked.HasValue;
}
}
/// <summary>
/// Gets the configured umbraco db connection string.
/// </summary>
@@ -135,7 +194,7 @@ namespace Umbraco.Core
if (string.IsNullOrEmpty(_providerName) == false)
return _providerName;
_providerName = "System.Data.SqlClient";
_providerName = Constants.DatabaseProviders.SqlServer;
if (ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName] != null)
{
if (string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName) == false)
@@ -174,7 +233,7 @@ namespace Umbraco.Core
/// </summary>
public void ConfigureEmbeddedDatabaseConnection()
{
const string providerName = "System.Data.SqlServerCe.4.0";
const string providerName = Constants.DatabaseProviders.SqlCe;
var connectionString = GetEmbeddedDatabaseConnectionString();
SaveConnectionString(connectionString, providerName);
@@ -189,7 +248,7 @@ namespace Umbraco.Core
// since it's been like this for quite some time
//using (var engine = new SqlCeEngine(connectionString))
//{
// engine.CreateDatabase();
// engine.CreateDatabase();
//}
}
@@ -212,10 +271,10 @@ namespace Umbraco.Core
{
var provider = DbConnectionExtensions.DetectProviderFromConnectionString(connectionString);
var databaseProvider = provider.ToString();
var providerName = "System.Data.SqlClient";
var providerName = Constants.DatabaseProviders.SqlServer;
if (databaseProvider.ToLower().Contains("mysql"))
{
providerName = "MySql.Data.MySqlClient";
providerName = Constants.DatabaseProviders.MySql;
}
SaveConnectionString(connectionString, providerName);
Initialize(string.Empty);
@@ -230,20 +289,20 @@ namespace Umbraco.Core
/// <param name="password">Database Password</param>
/// <param name="databaseProvider">Type of the provider to be used (Sql, Sql Azure, Sql Ce, MySql)</param>
public void ConfigureDatabaseConnection(string server, string databaseName, string user, string password, string databaseProvider)
{
{
string providerName;
var connectionString = GetDatabaseConnectionString(server, databaseName, user, password, databaseProvider, out providerName);
SaveConnectionString(connectionString, providerName);
Initialize(providerName);
}
public string GetDatabaseConnectionString(string server, string databaseName, string user, string password, string databaseProvider, out string providerName)
{
providerName = "System.Data.SqlClient";
providerName = Constants.DatabaseProviders.SqlServer;
if (databaseProvider.ToLower().Contains("mysql"))
{
providerName = "MySql.Data.MySqlClient";
providerName = Constants.DatabaseProviders.MySql;
return string.Format("Server={0}; Database={1};Uid={2};Pwd={3}", server, databaseName, user, password);
}
if (databaseProvider.ToLower().Contains("azure"))
@@ -260,7 +319,7 @@ namespace Umbraco.Core
/// <param name="databaseName">Name of the database</param>
public void ConfigureIntegratedSecurityDatabaseConnection(string server, string databaseName)
{
const string providerName = "System.Data.SqlClient";
const string providerName = Constants.DatabaseProviders.SqlServer;
var connectionString = GetIntegratedSecurityDatabaseConnectionString(server, databaseName);
SaveConnectionString(connectionString, providerName);
Initialize(providerName);
@@ -268,18 +327,18 @@ namespace Umbraco.Core
public string GetIntegratedSecurityDatabaseConnectionString(string server, string databaseName)
{
return String.Format("Server={0};Database={1};Integrated Security=true", server, databaseName);
return String.Format("Server={0};Database={1};Integrated Security=true", server, databaseName);
}
internal string BuildAzureConnectionString(string server, string databaseName, string user, string password)
{
if (server.Contains(".") && ServerStartsWithTcp(server) == false)
server = string.Format("tcp:{0}", server);
if (server.Contains(".") == false && ServerStartsWithTcp(server))
{
string serverName = server.Contains(",")
? server.Substring(0, server.IndexOf(",", StringComparison.Ordinal))
string serverName = server.Contains(",")
? server.Substring(0, server.IndexOf(",", StringComparison.Ordinal))
: server;
var portAddition = string.Empty;
@@ -289,10 +348,10 @@ namespace Umbraco.Core
server = string.Format("{0}.database.windows.net{1}", serverName, portAddition);
}
if (ServerStartsWithTcp(server) == false)
server = string.Format("tcp:{0}.database.windows.net", server);
if (server.Contains(",") == false)
server = string.Format("{0},1433", server);
@@ -336,7 +395,7 @@ namespace Umbraco.Core
_connectionString = connectionString;
_providerName = providerName;
var fileName = IOHelper.MapPath(string.Format("{0}/web.config", SystemDirectories.Root));
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
var connectionstrings = xml.Root.DescendantsAndSelf("connectionStrings").Single();
@@ -373,7 +432,7 @@ namespace Umbraco.Core
var databaseSettings = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName];
if (databaseSettings != null && string.IsNullOrWhiteSpace(databaseSettings.ConnectionString) == false && string.IsNullOrWhiteSpace(databaseSettings.ProviderName) == false)
{
var providerName = "System.Data.SqlClient";
var providerName = Constants.DatabaseProviders.SqlServer;
string connString = null;
if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName))
{
@@ -382,7 +441,6 @@ namespace Umbraco.Core
}
Initialize(providerName, connString);
DetermineSqlServerVersion();
}
else if (ConfigurationManager.AppSettings.ContainsKey(GlobalSettings.UmbracoConnectionName) && string.IsNullOrEmpty(ConfigurationManager.AppSettings[GlobalSettings.UmbracoConnectionName]) == false)
{
@@ -395,8 +453,8 @@ namespace Umbraco.Core
else if (legacyConnString.ToLowerInvariant().Contains("tcp:"))
{
//Must be sql azure
SaveConnectionString(legacyConnString, "System.Data.SqlClient");
Initialize("System.Data.SqlClient");
SaveConnectionString(legacyConnString, Constants.DatabaseProviders.SqlServer);
Initialize(Constants.DatabaseProviders.SqlServer);
}
else if (legacyConnString.ToLowerInvariant().Contains("datalayer=mysql"))
{
@@ -407,20 +465,19 @@ namespace Umbraco.Core
foreach (var variable in legacyConnString.Split(';').Where(x => x.ToLowerInvariant().StartsWith("datalayer") == false))
connectionStringWithoutDatalayer = string.Format("{0}{1};", connectionStringWithoutDatalayer, variable);
SaveConnectionString(connectionStringWithoutDatalayer, "MySql.Data.MySqlClient");
Initialize("MySql.Data.MySqlClient");
SaveConnectionString(connectionStringWithoutDatalayer, Constants.DatabaseProviders.MySql);
Initialize(Constants.DatabaseProviders.MySql);
}
else
{
//Must be sql
SaveConnectionString(legacyConnString, "System.Data.SqlClient");
Initialize("System.Data.SqlClient");
SaveConnectionString(legacyConnString, Constants.DatabaseProviders.SqlServer);
Initialize(Constants.DatabaseProviders.SqlServer);
}
//Remove the legacy connection string, so we don't end up in a loop if something goes wrong.
GlobalSettings.RemoveSetting(GlobalSettings.UmbracoConnectionName);
DetermineSqlServerVersion();
}
else
{
@@ -439,15 +496,15 @@ namespace Umbraco.Core
{
if (_syntaxProviders != null)
{
SqlSyntax = _syntaxProviders.GetByProviderNameOrDefault(providerName);
SqlSyntax = _syntaxProviders.GetByProviderNameOrDefault(providerName);
}
else if (SqlSyntax == null)
{
throw new InvalidOperationException("No " + typeof(ISqlSyntaxProvider) + " specified or no " + typeof(SqlSyntaxProviders) + " instance specified");
}
SqlSyntaxContext.SqlSyntaxProvider = SqlSyntax;
_configured = true;
}
catch (Exception e)
@@ -465,49 +522,6 @@ namespace Umbraco.Core
Initialize(providerName);
}
/// <summary>
/// Set the lazy resolution of determining the SQL server version if that is the db type we're using
/// </summary>
private void DetermineSqlServerVersion()
{
var sqlServerSyntax = SqlSyntax as SqlServerSyntaxProvider;
if (sqlServerSyntax != null)
{
//this will not execute now, it is lazy so will only execute when we need to actually know
// the sql server version.
sqlServerSyntax.VersionName = new Lazy<SqlServerVersionName>(() =>
{
try
{
var database = this._factory.CreateDatabase();
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
var firstPart = version.Split('.')[0];
switch (firstPart)
{
case "11":
return SqlServerVersionName.V2012;
case "10":
return SqlServerVersionName.V2008;
case "9":
return SqlServerVersionName.V2005;
case "8":
return SqlServerVersionName.V2000;
case "7":
return SqlServerVersionName.V7;
default:
return SqlServerVersionName.Other;
}
}
catch (Exception)
{
return SqlServerVersionName.Invalid;
}
});
}
}
internal DatabaseSchemaResult ValidateDatabaseSchema()
{
if (_configured == false || (string.IsNullOrEmpty(_connectionString) || string.IsNullOrEmpty(ProviderName)))
@@ -517,7 +531,7 @@ namespace Umbraco.Core
{
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted
&& ProviderName == "MySql.Data.MySqlClient")
&& ProviderName == Constants.DatabaseProviders.MySql)
{
throw new InvalidOperationException("Cannot use MySql in Medium Trust configuration");
}
@@ -530,7 +544,7 @@ namespace Umbraco.Core
}
internal Result CreateDatabaseSchemaAndData(ApplicationContext applicationContext)
{
{
try
{
var readyForInstall = CheckReadyForInstall();
@@ -548,7 +562,7 @@ namespace Umbraco.Core
// If MySQL, we're going to ensure that database calls are maintaining proper casing as to remove the necessity for checks
// for case insensitive queries. In an ideal situation (which is what we're striving for), all calls would be case sensitive.
/*
/*
var supportsCaseInsensitiveQueries = SqlSyntax.SupportsCaseInsensitiveQueries(database);
if (supportsCaseInsensitiveQueries == false)
{
@@ -566,9 +580,9 @@ namespace Umbraco.Core
message = GetResultMessageForMySql();
var schemaResult = ValidateDatabaseSchema();
var installedSchemaVersion = schemaResult.DetermineInstalledVersion();
//If Configuration Status is empty and the determined version is "empty" its a new install - otherwise upgrade the existing
if (string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) && installedSchemaVersion.Equals(new Version(0, 0, 0)))
{
@@ -587,9 +601,9 @@ namespace Umbraco.Core
message = "<p>Upgrading database, this may take some time...</p>";
return new Result
{
RequiresUpgrade = true,
Message = message,
Success = true,
RequiresUpgrade = true,
Message = message,
Success = true,
Percentage = "30"
};
}
@@ -617,7 +631,7 @@ namespace Umbraco.Core
_logger.Info<DatabaseContext>("Database upgrade started");
var database = new UmbracoDatabase(_connectionString, ProviderName, _logger);
//var supportsCaseInsensitiveQueries = SqlSyntax.SupportsCaseInsensitiveQueries(database);
//var supportsCaseInsensitiveQueries = SqlSyntax.SupportsCaseInsensitiveQueries(database);
var message = GetResultMessageForMySql();
@@ -625,37 +639,32 @@ namespace Umbraco.Core
var installedSchemaVersion = new SemVersion(schemaResult.DetermineInstalledVersion());
var installedMigrationVersion = new SemVersion(0);
//we cannot check the migrations table if it doesn't exist, this will occur when upgrading to 7.3
if (schemaResult.ValidTables.Any(x => x.InvariantEquals("umbracoMigration")))
{
installedMigrationVersion = schemaResult.DetermineInstalledVersionByMigrations(migrationEntryService);
}
var installedMigrationVersion = schemaResult.DetermineInstalledVersionByMigrations(migrationEntryService);
var targetVersion = UmbracoVersion.Current;
//In some cases - like upgrading from 7.2.6 -> 7.3, there will be no migration information in the database and therefore it will
// return a version of 0.0.0 and we don't necessarily want to run all migrations from 0 -> 7.3, so we'll just ensure that the
// return a version of 0.0.0 and we don't necessarily want to run all migrations from 0 -> 7.3, so we'll just ensure that the
// migrations are run for the target version
if (installedMigrationVersion == new SemVersion(new Version(0, 0, 0)) && installedSchemaVersion > new SemVersion(new Version(0, 0, 0)))
{
//set the installedMigrationVersion to be one less than the target so the latest migrations are guaranteed to execute
installedMigrationVersion = new SemVersion(targetVersion.SubtractRevision());
}
//Figure out what our current installed version is. If the web.config doesn't have a version listed, then we'll use the minimum
// version detected between the schema installed and the migrations listed in the migration table.
// version detected between the schema installed and the migrations listed in the migration table.
// If there is a version in the web.config, we'll take the minimum between the listed migration in the db and what
// is declared in the web.config.
var currentInstalledVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus)
//Take the minimum version between the detected schema version and the installed migration version
? new[] {installedSchemaVersion, installedMigrationVersion}.Min()
//Take the minimum version between the installed migration version and the version specified in the config
: new[] { SemVersion.Parse(GlobalSettings.ConfigurationStatus), installedMigrationVersion }.Min();
//Ok, another edge case here. If the current version is a pre-release,
// then we want to ensure all migrations for the current release are executed.
//Ok, another edge case here. If the current version is a pre-release,
// then we want to ensure all migrations for the current release are executed.
if (currentInstalledVersion.Prerelease.IsNullOrWhiteSpace() == false)
{
currentInstalledVersion = new SemVersion(currentInstalledVersion.GetVersion().SubtractRevision());
@@ -731,7 +740,7 @@ namespace Umbraco.Core
private Attempt<Result> CheckReadyForInstall()
{
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted
&& ProviderName == "MySql.Data.MySqlClient")
&& ProviderName == Constants.DatabaseProviders.MySql)
{
throw new InvalidOperationException("Cannot use MySql in Medium Trust configuration");
}
@@ -780,7 +789,7 @@ namespace Umbraco.Core
{
var dbIsSqlCe = false;
if (databaseSettings != null && databaseSettings.ProviderName != null)
dbIsSqlCe = databaseSettings.ProviderName == "System.Data.SqlServerCe.4.0";
dbIsSqlCe = databaseSettings.ProviderName == Constants.DatabaseProviders.SqlCe;
var sqlCeDatabaseExists = false;
if (dbIsSqlCe)
{
@@ -790,7 +799,7 @@ namespace Umbraco.Core
{
var datasource = dataSourcePart.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString());
var filePath = datasource.Replace("Data Source=", string.Empty);
sqlCeDatabaseExists = File.Exists(filePath);
sqlCeDatabaseExists = File.Exists(filePath);
}
}
@@ -804,5 +813,28 @@ namespace Umbraco.Core
return true;
}
private class UsingDatabase : IDisposable
{
private readonly UmbracoDatabase _orig;
private readonly UmbracoDatabase _temp;
public UsingDatabase(UmbracoDatabase orig, UmbracoDatabase temp)
{
_orig = orig;
_temp = temp;
}
public void Dispose()
{
if (_temp != null)
{
_temp.Dispose();
if (_orig != null)
DefaultDatabaseFactory.AttachAmbientDatabase(_orig);
}
GC.SuppressFinalize(this);
}
}
}
}
+32 -1
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Umbraco.Core.Events
{
@@ -47,5 +48,35 @@ namespace Umbraco.Core.Events
if (eventHandler != null)
eventHandler(sender, args);
}
}
// moves the last handler that was added to an instance event, to first position
public static void PromoteLastHandler(object sender, string eventName)
{
var fieldInfo = sender.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo == null) throw new InvalidOperationException("No event named " + eventName + ".");
PromoteLastHandler(sender, fieldInfo);
}
// moves the last handler that was added to a static event, to first position
public static void PromoteLastHandler<TSender>(string eventName)
{
var fieldInfo = typeof(TSender).GetField(eventName, BindingFlags.Static | BindingFlags.NonPublic);
if (fieldInfo == null) throw new InvalidOperationException("No event named " + eventName + ".");
PromoteLastHandler(null, fieldInfo);
}
private static void PromoteLastHandler(object sender, FieldInfo fieldInfo)
{
var d = fieldInfo.GetValue(sender) as Delegate;
if (d == null) return;
var l = d.GetInvocationList();
var x = l[l.Length - 1];
for (var i = l.Length - 1; i > 0; i--)
l[i] = l[i - 1];
l[0] = x;
fieldInfo.SetValue(sender, Delegate.Combine(l));
}
}
}
@@ -128,8 +128,14 @@ namespace Umbraco.Core.Events
get { return TargetSemVersion.GetVersion(); }
}
/// <summary>
/// Gets the origin version of the migration, i.e. the one that is currently installed.
/// </summary>
public SemVersion ConfiguredSemVersion { get; private set; }
/// <summary>
/// Gets the target version of the migration.
/// </summary>
public SemVersion TargetSemVersion { get; private set; }
public string ProductName { get; private set; }
+9
View File
@@ -0,0 +1,9 @@
using System;
namespace Umbraco.Core
{
public interface ICompletable : IDisposable
{
void Complete();
}
}
+7 -5
View File
@@ -37,15 +37,17 @@ namespace Umbraco.Core.IO
throw new ArgumentException("Retries must be greater than zero");
}
// GetSize has been added to IFileSystem2 but not IFileSystem
// this is implementing GetSize for IFileSystem, the old way
public static long GetSize(this IFileSystem fs, string path)
{
// if we reach this point, fs is *not* IFileSystem2
// so it's not FileSystemWrapper nor shadow nor anything we know
// so... fall back to the old & inefficient method
using (var file = fs.OpenFile(path))
{
using (var sr = new StreamReader(file))
{
var str = sr.ReadToEnd();
return str.Length;
}
return file.Length;
}
}
+187 -55
View File
@@ -4,8 +4,6 @@ using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.Configuration;
namespace Umbraco.Core.IO
@@ -13,8 +11,27 @@ namespace Umbraco.Core.IO
public class FileSystemProviderManager
{
private readonly FileSystemProvidersSection _config;
private readonly WeakSet<ShadowWrapper> _wrappers = new WeakSet<ShadowWrapper>();
#region Singleton
// actual well-known filesystems returned by properties
private readonly IFileSystem2 _macroPartialFileSystem;
private readonly IFileSystem2 _partialViewsFileSystem;
private readonly IFileSystem2 _stylesheetsFileSystem;
private readonly IFileSystem2 _scriptsFileSystem;
private readonly IFileSystem2 _xsltFileSystem;
private readonly IFileSystem2 _masterPagesFileSystem;
private readonly IFileSystem2 _mvcViewsFileSystem;
// when shadowing is enabled, above filesystems, as wrappers
private readonly ShadowWrapper _macroPartialFileSystemWrapper;
private readonly ShadowWrapper _partialViewsFileSystemWrapper;
private readonly ShadowWrapper _stylesheetsFileSystemWrapper;
private readonly ShadowWrapper _scriptsFileSystemWrapper;
private readonly ShadowWrapper _xsltFileSystemWrapper;
private readonly ShadowWrapper _masterPagesFileSystemWrapper;
private readonly ShadowWrapper _mvcViewsFileSystemWrapper;
#region Singleton & Constructor
private static readonly FileSystemProviderManager Instance = new FileSystemProviderManager();
@@ -23,109 +40,224 @@ namespace Umbraco.Core.IO
get { return Instance; }
}
#endregion
#region Constructors
internal FileSystemProviderManager()
{
_config = (FileSystemProvidersSection)ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders");
_config = (FileSystemProvidersSection) ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders");
_macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
_partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
_stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
_scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts);
_xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
_masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
_mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
_macroPartialFileSystem = _macroPartialFileSystemWrapper = new ShadowWrapper(_macroPartialFileSystem, "Views/MacroPartials");
_partialViewsFileSystem = _partialViewsFileSystemWrapper = new ShadowWrapper(_partialViewsFileSystem, "Views/Partials");
_stylesheetsFileSystem = _stylesheetsFileSystemWrapper = new ShadowWrapper(_stylesheetsFileSystem, "css");
_scriptsFileSystem = _scriptsFileSystemWrapper = new ShadowWrapper(_scriptsFileSystem, "scripts");
_xsltFileSystem = _xsltFileSystemWrapper = new ShadowWrapper(_xsltFileSystem, "xslt");
_masterPagesFileSystem = _masterPagesFileSystemWrapper = new ShadowWrapper(_masterPagesFileSystem, "masterpages");
_mvcViewsFileSystem = _mvcViewsFileSystemWrapper = new ShadowWrapper(_mvcViewsFileSystem, "Views");
// filesystems obtained from GetFileSystemProvider are already wrapped and do not need to be wrapped again
MediaFileSystem = GetFileSystemProvider<MediaFileSystem>();
}
#endregion
/// <summary>
/// used to cache the lookup of how to construct this object so we don't have to reflect each time.
/// </summary>
private class ProviderConstructionInfo
#region Well-Known FileSystems
public IFileSystem2 MacroPartialsFileSystem { get { return _macroPartialFileSystem; } }
public IFileSystem2 PartialViewsFileSystem { get { return _partialViewsFileSystem; } }
public IFileSystem2 StylesheetsFileSystem { get { return _stylesheetsFileSystem; } }
public IFileSystem2 ScriptsFileSystem { get { return _scriptsFileSystem; } }
public IFileSystem2 XsltFileSystem { get { return _xsltFileSystem; } }
public IFileSystem2 MasterPagesFileSystem { get { return _masterPagesFileSystem; } }
public IFileSystem2 MvcViewsFileSystem { get { return _mvcViewsFileSystem; } }
public MediaFileSystem MediaFileSystem { get; private set; }
#endregion
#region Providers
/// <summary>
/// used to cache the lookup of how to construct this object so we don't have to reflect each time.
/// </summary>
private class ProviderConstructionInfo
{
public object[] Parameters { get; set; }
public ConstructorInfo Constructor { get; set; }
public string ProviderAlias { get; set; }
//public string ProviderAlias { get; set; }
}
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
private readonly ConcurrentDictionary<Type, string> _wrappedProviderLookup = new ConcurrentDictionary<Type, string>();
private readonly ConcurrentDictionary<Type, string> _aliases = new ConcurrentDictionary<Type, string>();
/// <summary>
/// Returns the underlying (non-typed) file system provider for the alias specified
/// Gets an underlying (non-typed) filesystem supporting a strongly-typed filesystem.
/// </summary>
/// <param name="alias"></param>
/// <returns></returns>
/// <remarks>
/// It is recommended to use the typed GetFileSystemProvider method instead to get a strongly typed provider instance.
/// </remarks>
/// <param name="alias">The alias of the strongly-typed filesystem.</param>
/// <returns>The non-typed filesystem supporting the strongly-typed filesystem with the specified alias.</returns>
/// <remarks>This method should not be used directly, used <see cref="GetFileSystemProvider{TFileSystem}"/> instead.</remarks>
public IFileSystem GetUnderlyingFileSystemProvider(string alias)
{
//either get the constructor info from cache or create it and add to cache
// either get the constructor info from cache or create it and add to cache
var ctorInfo = _providerLookup.GetOrAdd(alias, s =>
{
// get config
var providerConfig = _config.Providers[s];
if (providerConfig == null)
throw new ArgumentException(string.Format("No provider found with the alias '{0}'", s));
throw new ArgumentException(string.Format("No provider found with alias {0}.", s));
// get the filesystem type
var providerType = Type.GetType(providerConfig.Type);
if (providerType == null)
throw new InvalidOperationException(string.Format("Could not find type '{0}'", providerConfig.Type));
throw new InvalidOperationException(string.Format("Could not find type {0}.", providerConfig.Type));
// ensure it implements IFileSystem
if (providerType.IsAssignableFrom(typeof (IFileSystem)))
throw new InvalidOperationException(string.Format("The type '{0}' does not implement IFileSystem", providerConfig.Type));
throw new InvalidOperationException(string.Format("Type {0} does not implement IFileSystem.", providerType.FullName));
// find a ctor matching the config parameters
var paramCount = providerConfig.Parameters != null ? providerConfig.Parameters.Count : 0;
var constructor = providerType.GetConstructors()
.SingleOrDefault(x => x.GetParameters().Count() == paramCount
&& x.GetParameters().All(y => providerConfig.Parameters.AllKeys.Contains(y.Name)));
var constructor = providerType.GetConstructors().SingleOrDefault(x
=> x.GetParameters().Length == paramCount && x.GetParameters().All(y => providerConfig.Parameters.AllKeys.Contains(y.Name)));
if (constructor == null)
throw new InvalidOperationException(string.Format("Could not find constructor for type '{0}' which accepts {1} parameters", providerConfig.Type, paramCount));
throw new InvalidOperationException(string.Format("Type {0} has no ctor matching the {1} configuration parameter(s).", providerType.FullName, paramCount));
var parameters = new object[paramCount];
for (var i = 0; i < paramCount; i++)
parameters[i] = providerConfig.Parameters[providerConfig.Parameters.AllKeys[i]].Value;
if (providerConfig.Parameters != null) // keeps ReSharper happy
for (var i = 0; i < paramCount; i++)
parameters[i] = providerConfig.Parameters[providerConfig.Parameters.AllKeys[i]].Value;
//return the new constructor info class to cache so we don't have to do this again.
return new ProviderConstructionInfo()
return new ProviderConstructionInfo
{
Constructor = constructor,
Parameters = parameters,
ProviderAlias = s
//ProviderAlias = s
};
});
var fs = (IFileSystem)ctorInfo.Constructor.Invoke(ctorInfo.Parameters);
return fs;
// create the fs and return
return (IFileSystem) ctorInfo.Constructor.Invoke(ctorInfo.Parameters);
}
/// <summary>
/// Returns the strongly typed file system provider
/// Gets a strongly-typed filesystem.
/// </summary>
/// <typeparam name="TProviderTypeFilter"></typeparam>
/// <returns></returns>
public TProviderTypeFilter GetFileSystemProvider<TProviderTypeFilter>()
where TProviderTypeFilter : FileSystemWrapper
/// <typeparam name="TFileSystem">The type of the filesystem.</typeparam>
/// <returns>A strongly-typed filesystem of the specified type.</returns>
public TFileSystem GetFileSystemProvider<TFileSystem>()
where TFileSystem : FileSystemWrapper
{
//get the alias for the type from cache or look it up and add it to the cache, then we don't have to reflect each time
var alias = _wrappedProviderLookup.GetOrAdd(typeof (TProviderTypeFilter), fsType =>
// deal with known types - avoid infinite loops!
if (typeof(TFileSystem) == typeof(MediaFileSystem) && MediaFileSystem != null)
return MediaFileSystem as TFileSystem; // else create and return
// get/cache the alias for the filesystem type
var alias = _aliases.GetOrAdd(typeof (TFileSystem), fsType =>
{
//validate the ctor
var constructor = fsType.GetConstructors()
.SingleOrDefault(x =>
x.GetParameters().Count() == 1 && TypeHelper.IsTypeAssignableFrom<IFileSystem>(x.GetParameters().Single().ParameterType));
// validate the ctor
var constructor = fsType.GetConstructors().SingleOrDefault(x
=> x.GetParameters().Length == 1 && TypeHelper.IsTypeAssignableFrom<IFileSystem>(x.GetParameters().Single().ParameterType));
if (constructor == null)
throw new InvalidOperationException("The type of " + fsType + " must inherit from FileSystemWrapper and must have a constructor that accepts one parameter of type " + typeof(IFileSystem));
var attr =
(FileSystemProviderAttribute)fsType.GetCustomAttributes(typeof(FileSystemProviderAttribute), false).
SingleOrDefault();
throw new InvalidOperationException("Type " + fsType.FullName + " must inherit from FileSystemWrapper and have a constructor that accepts one parameter of type " + typeof(IFileSystem).FullName + ".");
// find the attribute and get the alias
var attr = (FileSystemProviderAttribute) fsType.GetCustomAttributes(typeof(FileSystemProviderAttribute), false).SingleOrDefault();
if (attr == null)
throw new InvalidOperationException(string.Format("The provider type filter '{0}' is missing the required FileSystemProviderAttribute", typeof(FileSystemProviderAttribute).FullName));
throw new InvalidOperationException("Type " + fsType.FullName + "is missing the required FileSystemProviderAttribute.");
return attr.Alias;
});
// gets the inner fs, create the strongly-typed fs wrapping the inner fs, register & return
// so we are double-wrapping here
// could be optimized by having FileSystemWrapper inherit from ShadowWrapper, maybe
var innerFs = GetUnderlyingFileSystemProvider(alias);
var outputFs = Activator.CreateInstance(typeof (TProviderTypeFilter), innerFs);
return (TProviderTypeFilter)outputFs;
var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias);
var fs = (TFileSystem) Activator.CreateInstance(typeof (TFileSystem), innerFs);
_wrappers.Add(shadowWrapper); // keeping a weak reference to the wrapper
return fs;
}
#endregion
#region Shadow
// note
// shadowing is thread-safe, but entering and exiting shadow mode is not, and there is only one
// global shadow for the entire application, so great care should be taken to ensure that the
// application is *not* doing anything else when using a shadow.
// shadow applies to well-known filesystems *only* - at the moment, any other filesystem that would
// be created directly (via ctor) or via GetFileSystemProvider<T> is *not* shadowed.
// shadow must be enabled in an app event handler before anything else ie before any filesystem
// is actually created and used - after, it is too late - enabling shadow has a neglictible perfs
// impact.
// NO! by the time an app event handler is instanciated it is already too late, see note in ctor.
//internal void EnableShadow()
//{
// if (_mvcViewsFileSystem != null) // test one of the fs...
// throw new InvalidOperationException("Cannot enable shadow once filesystems have been created.");
// _shadowEnabled = true;
//}
public ICompletable Shadow(Guid id)
{
var typed = _wrappers.ToArray();
var wrappers = new ShadowWrapper[typed.Length + 7];
var i = 0;
while (i < typed.Length) wrappers[i] = typed[i++];
wrappers[i++] = _macroPartialFileSystemWrapper;
wrappers[i++] = _partialViewsFileSystemWrapper;
wrappers[i++] = _stylesheetsFileSystemWrapper;
wrappers[i++] = _scriptsFileSystemWrapper;
wrappers[i++] = _xsltFileSystemWrapper;
wrappers[i++] = _masterPagesFileSystemWrapper;
wrappers[i] = _mvcViewsFileSystemWrapper;
return ShadowFileSystemsScope.CreateScope(id, wrappers);
}
#endregion
private class WeakSet<T>
where T : class
{
private readonly HashSet<WeakReference<T>> _set = new HashSet<WeakReference<T>>();
public void Add(T item)
{
lock (_set)
{
_set.Add(new WeakReference<T>(item));
CollectLocked();
}
}
public T[] ToArray()
{
lock (_set)
{
CollectLocked();
return _set.Select(x =>
{
T target;
return x.TryGetTarget(out target) ? target : null;
}).WhereNotNull().ToArray();
}
}
private void CollectLocked()
{
_set.RemoveWhere(x =>
{
T target;
return x.TryGetTarget(out target) == false;
});
}
}
}
}
+31 -24
View File
@@ -14,93 +14,100 @@ namespace Umbraco.Core.IO
///
/// This abstract class just wraps the 'real' IFileSystem object passed in to its constructor.
/// </remarks>
public abstract class FileSystemWrapper : IFileSystem
public abstract class FileSystemWrapper : IFileSystem2
{
private readonly IFileSystem _wrapped;
protected FileSystemWrapper(IFileSystem wrapped)
protected FileSystemWrapper(IFileSystem wrapped)
{
_wrapped = wrapped;
Wrapped = wrapped;
}
public IEnumerable<string> GetDirectories(string path)
internal IFileSystem Wrapped { get; set; }
public IEnumerable<string> GetDirectories(string path)
{
return _wrapped.GetDirectories(path);
return Wrapped.GetDirectories(path);
}
public void DeleteDirectory(string path)
{
_wrapped.DeleteDirectory(path);
Wrapped.DeleteDirectory(path);
}
public void DeleteDirectory(string path, bool recursive)
{
_wrapped.DeleteDirectory(path, recursive);
Wrapped.DeleteDirectory(path, recursive);
}
public bool DirectoryExists(string path)
{
return _wrapped.DirectoryExists(path);
return Wrapped.DirectoryExists(path);
}
public void AddFile(string path, Stream stream)
{
_wrapped.AddFile(path, stream);
Wrapped.AddFile(path, stream);
}
public void AddFile(string path, Stream stream, bool overrideIfExists)
public void AddFile(string path, Stream stream, bool overrideExisting)
{
_wrapped.AddFile(path, stream, overrideIfExists);
Wrapped.AddFile(path, stream, overrideExisting);
}
public IEnumerable<string> GetFiles(string path)
{
return _wrapped.GetFiles(path);
return Wrapped.GetFiles(path);
}
public IEnumerable<string> GetFiles(string path, string filter)
{
return _wrapped.GetFiles(path, filter);
return Wrapped.GetFiles(path, filter);
}
public Stream OpenFile(string path)
{
return _wrapped.OpenFile(path);
return Wrapped.OpenFile(path);
}
public void DeleteFile(string path)
{
_wrapped.DeleteFile(path);
Wrapped.DeleteFile(path);
}
public bool FileExists(string path)
{
return _wrapped.FileExists(path);
return Wrapped.FileExists(path);
}
public string GetRelativePath(string fullPathOrUrl)
{
return _wrapped.GetRelativePath(fullPathOrUrl);
return Wrapped.GetRelativePath(fullPathOrUrl);
}
public string GetFullPath(string path)
{
return _wrapped.GetFullPath(path);
return Wrapped.GetFullPath(path);
}
public string GetUrl(string path)
{
return _wrapped.GetUrl(path);
return Wrapped.GetUrl(path);
}
public DateTimeOffset GetLastModified(string path)
{
return _wrapped.GetLastModified(path);
return Wrapped.GetLastModified(path);
}
public DateTimeOffset GetCreated(string path)
{
return _wrapped.GetCreated(path);
return Wrapped.GetCreated(path);
}
}
// explicitely implementing - not breaking
long IFileSystem2.GetSize(string path)
{
var wrapped2 = Wrapped as IFileSystem2;
return wrapped2 == null ? Wrapped.GetSize(path) : wrapped2.GetSize(path);
}
}
}
+14 -5
View File
@@ -4,9 +4,6 @@ using System.IO;
namespace Umbraco.Core.IO
{
//TODO: There is no way to create a directory here without creating a file in a directory and then deleting it
//TODO: Should probably implement a rename?
public interface IFileSystem
{
IEnumerable<string> GetDirectories(string path);
@@ -16,7 +13,7 @@ namespace Umbraco.Core.IO
void DeleteDirectory(string path, bool recursive);
bool DirectoryExists(string path);
void AddFile(string path, Stream stream);
void AddFile(string path, Stream stream, bool overrideIfExists);
@@ -31,7 +28,6 @@ namespace Umbraco.Core.IO
bool FileExists(string path);
string GetRelativePath(string fullPathOrUrl);
string GetFullPath(string path);
@@ -42,4 +38,17 @@ namespace Umbraco.Core.IO
DateTimeOffset GetCreated(string path);
}
// this should be part of IFileSystem but we don't want to change the interface
public interface IFileSystem2 : IFileSystem
{
long GetSize(string path);
// TODO: implement these
//
//void CreateDirectory(string path);
//
//// move or rename, directory or file
//void Move(string source, string target);
}
}
+644 -32
View File
@@ -1,9 +1,18 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Media;
using Umbraco.Core.Media.Exif;
using Umbraco.Core.Models;
namespace Umbraco.Core.IO
{
@@ -14,59 +23,662 @@ namespace Umbraco.Core.IO
public class MediaFileSystem : FileSystemWrapper
{
private readonly IContentSection _contentConfig;
private readonly UploadAutoFillProperties _uploadAutoFillProperties;
public MediaFileSystem(IFileSystem wrapped)
: this(wrapped, UmbracoConfig.For.UmbracoSettings().Content)
{
}
private readonly object _folderCounterLock = new object();
private long _folderCounter;
private bool _folderCounterInitialized;
public MediaFileSystem(IFileSystem wrapped, IContentSection contentConfig) : base(wrapped)
private static readonly Dictionary<int, string> DefaultSizes = new Dictionary<int, string>
{
{ 100, "thumb" },
{ 500, "big-thumb" }
};
public MediaFileSystem(IFileSystem wrapped)
: this(wrapped, UmbracoConfig.For.UmbracoSettings().Content, ApplicationContext.Current.ProfilingLogger.Logger)
{ }
public MediaFileSystem(IFileSystem wrapped, IContentSection contentConfig, ILogger logger)
: base(wrapped)
{
_contentConfig = contentConfig;
_uploadAutoFillProperties = new UploadAutoFillProperties(this, logger, contentConfig);
}
public string GetRelativePath(int propertyId, string fileName)
internal UploadAutoFillProperties UploadAutoFillProperties { get { return _uploadAutoFillProperties; } }
// note - this is currently experimental / being developed
//public static bool UseTheNewMediaPathScheme { get; set; }
public const bool UseTheNewMediaPathScheme = false;
// none of the methods below are used in Core anymore
[Obsolete("This low-level method should NOT exist.")]
public string GetRelativePath(int propertyId, string fileName)
{
var seperator = _contentConfig.UploadAllowDirectories
var sep = _contentConfig.UploadAllowDirectories
? Path.DirectorySeparatorChar
: '-';
return propertyId.ToString(CultureInfo.InvariantCulture) + seperator + fileName;
return propertyId.ToString(CultureInfo.InvariantCulture) + sep + fileName;
}
[Obsolete("This low-level method should NOT exist.", false)]
public string GetRelativePath(string subfolder, string fileName)
{
var seperator = _contentConfig.UploadAllowDirectories
var sep = _contentConfig.UploadAllowDirectories
? Path.DirectorySeparatorChar
: '-';
return subfolder + seperator + fileName;
return subfolder + sep + fileName;
}
public IEnumerable<string> GetThumbnails(string path)
{
var parentDirectory = Path.GetDirectoryName(path);
var extension = Path.GetExtension(path);
#region Media Path
return GetFiles(parentDirectory)
.Where(x => x.StartsWith(path.TrimEnd(extension) + "_thumb") || x.StartsWith(path.TrimEnd(extension) + "_big-thumb"))
.ToList();
}
/// <summary>
/// Gets the file path of a media file.
/// </summary>
/// <param name="filename">The file name.</param>
/// <param name="cuid">The unique identifier of the content/media owning the file.</param>
/// <param name="puid">The unique identifier of the property type owning the file.</param>
/// <returns>The filesystem-relative path to the media file.</returns>
/// <remarks>With the old media path scheme, this CREATES a new media path each time it is invoked.</remarks>
public string GetMediaPath(string filename, Guid cuid, Guid puid)
{
filename = Path.GetFileName(filename);
if (filename == null) throw new ArgumentException("Cannot become a safe filename.", "filename");
filename = IOHelper.SafeFileName(filename.ToLowerInvariant());
public void DeleteFile(string path, bool deleteThumbnails)
{
DeleteFile(path);
string folder;
if (UseTheNewMediaPathScheme == false)
{
// old scheme: filepath is "<int>/<filename>" OR "<int>-<filename>"
// default media filesystem maps to "~/media/<filepath>"
folder = GetNextFolder();
}
else
{
// new scheme: path is "<cuid>-<puid>/<filename>" OR "<cuid>-<puid>-<filename>"
// default media filesystem maps to "~/media/<filepath>"
// assumes that cuid and puid keys can be trusted - and that a single property type
// for a single content cannot store two different files with the same name
folder = Combine(cuid, puid).ToHexString(/*'/', 2, 4*/); // could use ext to fragment path eg 12/e4/f2/...
}
if (deleteThumbnails == false)
return;
var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
? Path.Combine(folder, filename)
: folder + "-" + filename;
DeleteThumbnails(path);
}
return filepath;
}
public void DeleteThumbnails(string path)
{
GetThumbnails(path)
.ForEach(DeleteFile);
}
}
private static byte[] Combine(Guid guid1, Guid guid2)
{
var bytes1 = guid1.ToByteArray();
var bytes2 = guid2.ToByteArray();
var bytes = new byte[bytes1.Length];
for (var i = 0; i < bytes1.Length; i++)
bytes[i] = (byte)(bytes1[i] ^ bytes2[i]);
return bytes;
}
/// <summary>
/// Gets the file path of a media file.
/// </summary>
/// <param name="filename">The file name.</param>
/// <param name="prevpath">A previous file path.</param>
/// <param name="cuid">The unique identifier of the content/media owning the file.</param>
/// <param name="puid">The unique identifier of the property type owning the file.</param>
/// <returns>The filesystem-relative path to the media file.</returns>
/// <remarks>In the old, legacy, number-based scheme, we try to re-use the media folder
/// specified by <paramref name="prevpath"/>. Else, we CREATE a new one. Each time we are invoked.</remarks>
public string GetMediaPath(string filename, string prevpath, Guid cuid, Guid puid)
{
if (UseTheNewMediaPathScheme || string.IsNullOrWhiteSpace(prevpath))
return GetMediaPath(filename, cuid, puid);
filename = Path.GetFileName(filename);
if (filename == null) throw new ArgumentException("Cannot become a safe filename.", "filename");
filename = IOHelper.SafeFileName(filename.ToLowerInvariant());
// old scheme, with a previous path
// prevpath should be "<int>/<filename>" OR "<int>-<filename>"
// and we want to reuse the "<int>" part, so try to find it
var sep = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories ? "/" : "-";
var pos = prevpath.IndexOf(sep, StringComparison.Ordinal);
var s = pos > 0 ? prevpath.Substring(0, pos) : null;
int ignored;
var folder = (pos > 0 && int.TryParse(s, out ignored)) ? s : GetNextFolder();
// ReSharper disable once AssignNullToNotNullAttribute
var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
? Path.Combine(folder, filename)
: folder + "-" + filename;
return filepath;
}
/// <summary>
/// Gets the next media folder in the original number-based scheme.
/// </summary>
/// <returns></returns>
/// <remarks>Should be private, is internal for legacy FileHandlerData which is obsolete.</remarks>
internal string GetNextFolder()
{
EnsureFolderCounterIsInitialized();
return Interlocked.Increment(ref _folderCounter).ToString(CultureInfo.InvariantCulture);
}
private void EnsureFolderCounterIsInitialized()
{
lock (_folderCounterLock)
{
if (_folderCounterInitialized) return;
_folderCounter = 1000; // seed
var directories = GetDirectories("");
foreach (var directory in directories)
{
long folderNumber;
if (long.TryParse(directory, out folderNumber) && folderNumber > _folderCounter)
_folderCounter = folderNumber;
}
// note: not multi-domains ie LB safe as another domain could create directories
// while we read and parse them - don't fix, move to new scheme eventually
_folderCounterInitialized = true;
}
}
#endregion
#region Associated Media Files
/// <summary>
/// Stores a media file.
/// </summary>
/// <param name="content">The content item owning the media file.</param>
/// <param name="propertyType">The property type owning the media file.</param>
/// <param name="filename">The media file name.</param>
/// <param name="filestream">A stream containing the media bytes.</param>
/// <param name="oldpath">An optional filesystem-relative filepath to the previous media file.</param>
/// <returns>The filesystem-relative filepath to the media file.</returns>
/// <remarks>
/// <para>The file is considered "owned" by the content/propertyType.</para>
/// <para>If an <paramref name="oldpath"/> is provided then that file (and thumbnails) is deleted
/// before the new file is saved, and depending on the media path scheme, the folder
/// may be reused for the new file.</para>
/// </remarks>
public string StoreFile(IContentBase content, PropertyType propertyType, string filename, Stream filestream, string oldpath)
{
if (content == null) throw new ArgumentNullException("content");
if (propertyType == null) throw new ArgumentNullException("propertyType");
if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentException("Null or empty.", "filename");
if (filestream == null) throw new ArgumentNullException("filestream");
// clear the old file, if any
if (string.IsNullOrWhiteSpace(oldpath) == false)
DeleteFile(oldpath, true);
// get the filepath, store the data
// use oldpath as "prevpath" to try and reuse the folder, in original number-based scheme
var filepath = GetMediaPath(filename, oldpath, content.Key, propertyType.Key);
AddFile(filepath, filestream);
return filepath;
}
/// <summary>
/// Clears a media file.
/// </summary>
/// <param name="filepath">The filesystem-relative path to the media file.</param>
public new void DeleteFile(string filepath)
{
DeleteFile(filepath, true);
}
/// <summary>
/// Copies a media file.
/// </summary>
/// <param name="content">The content item owning the copy of the media file.</param>
/// <param name="propertyType">The property type owning the copy of the media file.</param>
/// <param name="sourcepath">The filesystem-relative path to the source media file.</param>
/// <returns>The filesystem-relative path to the copy of the media file.</returns>
public string CopyFile(IContentBase content, PropertyType propertyType, string sourcepath)
{
if (content == null) throw new ArgumentNullException("content");
if (propertyType == null) throw new ArgumentNullException("propertyType");
if (string.IsNullOrWhiteSpace(sourcepath)) throw new ArgumentException("Null or empty.", "sourcepath");
// ensure we have a file to copy
if (FileExists(sourcepath) == false) return null;
// get the filepath
var filename = Path.GetFileName(sourcepath);
var filepath = GetMediaPath(filename, content.Key, propertyType.Key);
this.CopyFile(sourcepath, filepath);
CopyThumbnails(sourcepath, filepath);
return filepath;
}
/// <summary>
/// Gets or creates a property for a content item.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="propertyTypeAlias">The property type alias.</param>
/// <returns>The property.</returns>
private static Property GetProperty(IContentBase content, string propertyTypeAlias)
{
var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (property != null) return property;
var propertyType = content.GetContentType().CompositionPropertyTypes
.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (propertyType == null)
throw new Exception("No property type exists with alias " + propertyTypeAlias + ".");
property = new Property(propertyType);
content.Properties.Add(property);
return property;
}
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filename, Stream filestream)
{
var property = GetProperty(content, propertyTypeAlias);
var svalue = property.Value as string;
var oldpath = svalue == null ? null : GetRelativePath(svalue);
var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath);
property.Value = GetUrl(filepath);
SetUploadFile(content, property, filepath, filestream);
}
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filepath)
{
var property = GetProperty(content, propertyTypeAlias);
var svalue = property.Value as string;
var oldpath = svalue == null ? null : GetRelativePath(svalue); // FIXME DELETE?
if (string.IsNullOrWhiteSpace(oldpath) == false && oldpath != filepath)
DeleteFile(oldpath, true);
property.Value = GetUrl(filepath);
using (var filestream = OpenFile(filepath))
{
SetUploadFile(content, property, filepath, filestream);
}
}
// sets a file for the FileUpload property editor
// ie generates thumbnails and populates autofill properties
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream)
{
// check if file is an image (and supports resizing and thumbnails etc)
var extension = Path.GetExtension(filepath);
var isImage = IsImageFile(extension);
// specific stuff for images (thumbnails etc)
if (isImage)
{
using (var image = Image.FromStream(filestream))
{
// use one image for all
GenerateThumbnails(image, filepath, property.PropertyType);
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, image);
}
}
else
{
// will use filepath for extension, and filestream for length
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
}
}
#endregion
#region Image
/// <summary>
/// Gets a value indicating whether the file extension corresponds to an image.
/// </summary>
/// <param name="extension">The file extension.</param>
/// <returns>A value indicating whether the file extension corresponds to an image.</returns>
public bool IsImageFile(string extension)
{
if (extension == null) return false;
extension = extension.TrimStart('.');
return UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes.InvariantContains(extension);
}
/// <summary>
/// Gets the dimensions of an image.
/// </summary>
/// <param name="stream">A stream containing the image bytes.</param>
/// <returns>The dimension of the image.</returns>
/// <remarks>First try with EXIF as it is faster and does not load the entire image
/// in memory. Fallback to GDI which means loading the image in memory and thus
/// use potentially large amounts of memory.</remarks>
public Size GetDimensions(Stream stream)
{
//Try to load with exif
try
{
var jpgInfo = ImageFile.FromStream(stream);
if (jpgInfo.Format != ImageFileFormat.Unknown
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension)
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension))
{
var height = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelYDimension].Value);
var width = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelXDimension].Value);
if (height > 0 && width > 0)
{
return new Size(width, height);
}
}
}
catch (Exception)
{
//We will just swallow, just means we can't read exif data, we don't want to log an error either
}
//we have no choice but to try to read in via GDI
using (var image = Image.FromStream(stream))
{
var fileWidth = image.Width;
var fileHeight = image.Height;
return new Size(fileWidth, fileHeight);
}
}
#endregion
#region Manage thumbnails
// note: this does not find 'custom' thumbnails?
// will find _thumb and _big-thumb but NOT _custom?
public IEnumerable<string> GetThumbnails(string path)
{
var parentDirectory = Path.GetDirectoryName(path);
var extension = Path.GetExtension(path);
return GetFiles(parentDirectory)
.Where(x => x.StartsWith(path.TrimEnd(extension) + "_thumb") || x.StartsWith(path.TrimEnd(extension) + "_big-thumb"))
.ToList();
}
public void DeleteFile(string path, bool deleteThumbnails)
{
base.DeleteFile(path);
if (deleteThumbnails == false)
return;
DeleteThumbnails(path);
}
public void DeleteThumbnails(string path)
{
GetThumbnails(path)
.ForEach(x => base.DeleteFile(x));
}
public void CopyThumbnails(string sourcePath, string targetPath)
{
var targetPathBase = Path.GetDirectoryName(targetPath) ?? "";
foreach (var sourceThumbPath in GetThumbnails(sourcePath))
{
var sourceThumbFilename = Path.GetFileName(sourceThumbPath) ?? "";
var targetThumbPath = Path.Combine(targetPathBase, sourceThumbFilename);
this.CopyFile(sourceThumbPath, targetThumbPath);
}
}
#endregion
#region GenerateThumbnails
public IEnumerable<ResizedImage> GenerateThumbnails(
Image image,
string filepath,
string preValue)
{
if (string.IsNullOrWhiteSpace(preValue))
return GenerateThumbnails(image, filepath);
var additionalSizes = new List<int>();
var sep = preValue.Contains(",") ? "," : ";";
var values = preValue.Split(new[] { sep }, StringSplitOptions.RemoveEmptyEntries);
foreach (var value in values)
{
int size;
if (int.TryParse(value, out size))
additionalSizes.Add(size);
}
return GenerateThumbnails(image, filepath, additionalSizes);
}
public IEnumerable<ResizedImage> GenerateThumbnails(
Image image,
string filepath,
IEnumerable<int> additionalSizes = null)
{
var w = image.Width;
var h = image.Height;
var sizes = additionalSizes == null ? DefaultSizes.Keys : DefaultSizes.Keys.Concat(additionalSizes);
// start with default sizes,
// add additional sizes,
// filter out duplicates,
// filter out those that would be larger that the original image
// and create the thumbnail
return sizes
.Distinct()
.Where(x => w >= x && h >= x)
.Select(x => GenerateResized(image, filepath, DefaultSizes.ContainsKey(x) ? DefaultSizes[x] : "", x))
.ToList(); // now
}
public IEnumerable<ResizedImage> GenerateThumbnails(
Stream filestream,
string filepath,
PropertyType propertyType)
{
// get the original image from the original stream
if (filestream.CanSeek) filestream.Seek(0, 0); // fixme - what if we cannot seek?
using (var image = Image.FromStream(filestream))
{
return GenerateThumbnails(image, filepath, propertyType);
}
}
public IEnumerable<ResizedImage> GenerateThumbnails(
Image image,
string filepath,
PropertyType propertyType)
{
// if the editor is an upload field, check for additional thumbnail sizes
// that can be defined in the prevalue for the property data type. otherwise,
// just use the default sizes.
var sizes = propertyType.PropertyEditorAlias == Constants.PropertyEditors.UploadFieldAlias
? ApplicationContext.Current.Services.DataTypeService
.GetPreValuesByDataTypeId(propertyType.DataTypeDefinitionId)
.FirstOrDefault()
: string.Empty;
return GenerateThumbnails(image, filepath, sizes);
}
#endregion
#region GenerateResized - Generate at resized filepath derived from origin filepath
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight)
{
return GenerateResized(originImage, originFilepath, sizeName, maxWidthHeight, -1, -1);
}
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int fixedWidth, int fixedHeight)
{
return GenerateResized(originImage, originFilepath, sizeName, -1, fixedWidth, fixedHeight);
}
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight, int fixedWidth, int fixedHeight)
{
if (string.IsNullOrWhiteSpace(sizeName))
sizeName = "UMBRACOSYSTHUMBNAIL";
var extension = Path.GetExtension(originFilepath) ?? string.Empty;
var filebase = originFilepath.TrimEnd(extension);
var resizedFilepath = filebase + "_" + sizeName + extension;
return GenerateResizedAt(originImage, resizedFilepath, maxWidthHeight, fixedWidth, fixedHeight);
}
#endregion
#region GenerateResizedAt - Generate at specified resized filepath
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight)
{
return GenerateResizedAt(originImage, resizedFilepath, maxWidthHeight, -1, -1);
}
public ResizedImage GenerateResizedAt(Image originImage, int fixedWidth, int fixedHeight, string resizedFilepath)
{
return GenerateResizedAt(originImage, resizedFilepath, -1, fixedWidth, fixedHeight);
}
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight, int fixedWidth, int fixedHeight)
{
// target dimensions
int width, height;
// if maxWidthHeight then get ratio
if (maxWidthHeight > 0)
{
var fx = (float)originImage.Size.Width / maxWidthHeight;
var fy = (float)originImage.Size.Height / maxWidthHeight;
var f = Math.Max(fx, fy); // fit in thumbnail size
width = (int)Math.Round(originImage.Size.Width / f);
height = (int)Math.Round(originImage.Size.Height / f);
if (width == 0) width = 1;
if (height == 0) height = 1;
}
else if (fixedWidth > 0 && fixedHeight > 0)
{
width = fixedWidth;
height = fixedHeight;
}
else
{
width = height = 1;
}
// create new image with best quality settings
using (var bitmap = new Bitmap(width, height))
using (var graphics = Graphics.FromImage(bitmap))
{
// if the image size is rather large we cannot use the best quality interpolation mode
// because we'll get out of mem exceptions. So we detect how big the image is and use
// the mid quality interpolation mode when the image size exceeds our max limit.
graphics.InterpolationMode = originImage.Width > 5000 || originImage.Height > 5000
? InterpolationMode.Bilinear // mid quality
: InterpolationMode.HighQualityBicubic; // best quality
// everything else is best-quality
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
// copy the old image to the new and resize
var rect = new Rectangle(0, 0, width, height);
graphics.DrawImage(originImage, rect, 0, 0, originImage.Width, originImage.Height, GraphicsUnit.Pixel);
// copy metadata
// fixme - er... no?
// get an encoder - based upon the file type
var extension = (Path.GetExtension(resizedFilepath) ?? "").TrimStart('.').ToLowerInvariant();
var encoders = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo encoder;
switch (extension)
{
case "png":
encoder = encoders.Single(t => t.MimeType.Equals("image/png"));
break;
case "gif":
encoder = encoders.Single(t => t.MimeType.Equals("image/gif"));
break;
case "tif":
case "tiff":
encoder = encoders.Single(t => t.MimeType.Equals("image/tiff"));
break;
case "bmp":
encoder = encoders.Single(t => t.MimeType.Equals("image/bmp"));
break;
// TODO: this is dirty, defaulting to jpg but the return value of this thing is used all over the
// place so left it here, but it needs to not set a codec if it doesn't know which one to pick
// Note: when fixing this: both .jpg and .jpeg should be handled as extensions
default:
encoder = encoders.Single(t => t.MimeType.Equals("image/jpeg"));
break;
}
// set compresion ratio to 90%
var encoderParams = new EncoderParameters();
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
// save the new image
using (var stream = new MemoryStream())
{
bitmap.Save(stream, encoder, encoderParams);
stream.Seek(0, 0);
if (resizedFilepath.Contains("UMBRACOSYSTHUMBNAIL"))
{
var filepath = resizedFilepath.Replace("UMBRACOSYSTHUMBNAIL", maxWidthHeight.ToInvariantString());
AddFile(filepath, stream);
if (extension != "jpg")
{
filepath = filepath.TrimEnd(extension) + "jpg";
stream.Seek(0, 0);
AddFile(filepath, stream);
}
// TODO: Remove this, this is ONLY here for backwards compatibility but it is essentially completely unusable see U4-5385
stream.Seek(0, 0);
resizedFilepath = resizedFilepath.Replace("UMBRACOSYSTHUMBNAIL", width + "x" + height);
}
AddFile(resizedFilepath, stream);
}
return new ResizedImage(resizedFilepath, width, height);
}
}
#endregion
#region Inner classes
public class ResizedImage
{
public ResizedImage()
{ }
public ResizedImage(string filepath, int width, int height)
{
Filepath = filepath;
Width = width;
Height = height;
}
public string Filepath { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}
#endregion
}
}
+146 -56
View File
@@ -6,29 +6,32 @@ using Umbraco.Core.Logging;
namespace Umbraco.Core.IO
{
public class PhysicalFileSystem : IFileSystem
public class PhysicalFileSystem : IFileSystem2
{
// the rooted, filesystem path, using directory separator chars, NOT ending with a separator
// eg "c:" or "c:\path\to\site" or "\\server\path"
private readonly string _rootPath;
// the ??? url, using url separator chars, NOT ending with a separator
// eg "" (?) or "/Scripts" or ???
// _rootPath, but with separators replaced by forward-slashes
// eg "c:" or "c:/path/to/site" or "//server/path"
// (is used in GetRelativePath)
private readonly string _rootPathFwd;
// the relative url, using url separator chars, NOT ending with a separator
// eg "" or "/Views" or "/Media" or "/<vpath>/Media" in case of a virtual path
private readonly string _rootUrl;
// virtualRoot should be "~/path/to/root" eg "~/Views"
// the "~/" is mandatory.
public PhysicalFileSystem(string virtualRoot)
{
if (virtualRoot == null) throw new ArgumentNullException("virtualRoot");
if (virtualRoot.StartsWith("~/") == false)
throw new ArgumentException("The virtualRoot argument must be a virtual path and start with '~/'");
_rootPath = IOHelper.MapPath(virtualRoot);
_rootPath = EnsureDirectorySeparatorChar(_rootPath);
_rootPath = _rootPath.TrimEnd(Path.DirectorySeparatorChar);
_rootUrl = IOHelper.ResolveUrl(virtualRoot);
_rootUrl = EnsureUrlSeparatorChar(_rootUrl);
_rootUrl = _rootUrl.TrimEnd('/');
_rootPath = EnsureDirectorySeparatorChar(IOHelper.MapPath(virtualRoot)).TrimEnd(Path.DirectorySeparatorChar);
_rootPathFwd = EnsureUrlSeparatorChar(_rootPath);
_rootUrl = EnsureUrlSeparatorChar(IOHelper.ResolveUrl(virtualRoot)).TrimEnd('/');
}
public PhysicalFileSystem(string rootPath, string rootUrl)
@@ -43,22 +46,24 @@ namespace Umbraco.Core.IO
throw new ArgumentException("The rootPath argument cannot be a virtual path and cannot start with '~/'");
// rootPath should be... rooted, as in, it's a root path!
// but the test suite App.config cannot really "root" anything so we'll have to do it here
//var localRoot = AppDomain.CurrentDomain.BaseDirectory;
var localRoot = IOHelper.GetRootDirectorySafe();
if (Path.IsPathRooted(rootPath) == false)
{
// but the test suite App.config cannot really "root" anything so we have to do it here
var localRoot = IOHelper.GetRootDirectorySafe();
rootPath = Path.Combine(localRoot, rootPath);
}
rootPath = EnsureDirectorySeparatorChar(rootPath);
rootUrl = EnsureUrlSeparatorChar(rootUrl);
_rootPath = rootPath.TrimEnd(Path.DirectorySeparatorChar);
_rootUrl = rootUrl.TrimEnd('/');
_rootPath = EnsureDirectorySeparatorChar(rootPath).TrimEnd(Path.DirectorySeparatorChar);
_rootPathFwd = EnsureUrlSeparatorChar(_rootPath);
_rootUrl = EnsureUrlSeparatorChar(rootUrl).TrimEnd('/');
}
/// <summary>
/// Gets directories in a directory.
/// </summary>
/// <param name="path">The filesystem-relative path to the directory.</param>
/// <returns>The filesystem-relative path to the directories in the directory.</returns>
/// <remarks>Filesystem-relative paths use forward-slashes as directory separators.</remarks>
public IEnumerable<string> GetDirectories(string path)
{
var fullPath = GetFullPath(path);
@@ -80,11 +85,20 @@ namespace Umbraco.Core.IO
return Enumerable.Empty<string>();
}
/// <summary>
/// Deletes a directory.
/// </summary>
/// <param name="path">The filesystem-relative path of the directory.</param>
public void DeleteDirectory(string path)
{
DeleteDirectory(path, false);
}
/// <summary>
/// Deletes a directory.
/// </summary>
/// <param name="path">The filesystem-relative path of the directory.</param>
/// <param name="recursive">A value indicating whether to recursively delete sub-directories.</param>
public void DeleteDirectory(string path, bool recursive)
{
var fullPath = GetFullPath(path);
@@ -101,38 +115,71 @@ namespace Umbraco.Core.IO
}
}
/// <summary>
/// Gets a value indicating whether a directory exists.
/// </summary>
/// <param name="path">The filesystem-relative path of the directory.</param>
/// <returns>A value indicating whether a directory exists.</returns>
public bool DirectoryExists(string path)
{
var fullPath = GetFullPath(path);
return Directory.Exists(fullPath);
}
/// <summary>
/// Saves a file.
/// </summary>
/// <param name="path">The filesystem-relative path of the file.</param>
/// <param name="stream">A stream containing the file data.</param>
/// <remarks>Overrides the existing file, if any.</remarks>
public void AddFile(string path, Stream stream)
{
AddFile(path, stream, true);
}
public void AddFile(string path, Stream stream, bool overrideIfExists)
/// <summary>
/// Saves a file.
/// </summary>
/// <param name="path">The filesystem-relative path of the file.</param>
/// <param name="stream">A stream containing the file data.</param>
/// <param name="overrideExisting">A value indicating whether to override the existing file, if any.</param>
/// <remarks>If a file exists and <paramref name="overrideExisting"/> is false, an exception is thrown.</remarks>
public void AddFile(string path, Stream stream, bool overrideExisting)
{
var fullPath = GetFullPath(path);
var exists = File.Exists(fullPath);
if (exists && overrideIfExists == false)
if (exists && overrideExisting == false)
throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); // ensure it exists
var directory = Path.GetDirectoryName(fullPath);
if (directory == null) throw new InvalidOperationException("Could not get directory.");
Directory.CreateDirectory(directory); // ensure it exists
if (stream.CanSeek)
if (stream.CanSeek) // fixme - what else?
stream.Seek(0, 0);
using (var destination = (Stream)File.Create(fullPath))
using (var destination = (Stream) File.Create(fullPath))
stream.CopyTo(destination);
}
/// <summary>
/// Gets files in a directory.
/// </summary>
/// <param name="path">The filesystem-relative path of the directory.</param>
/// <returns>The filesystem-relative path to the files in the directory.</returns>
/// <remarks>Filesystem-relative paths use forward-slashes as directory separators.</remarks>
public IEnumerable<string> GetFiles(string path)
{
return GetFiles(path, "*.*");
}
/// <summary>
/// Gets files in a directory.
/// </summary>
/// <param name="path">The filesystem-relative path of the directory.</param>
/// <param name="filter">A filter.</param>
/// <returns>The filesystem-relative path to the matching files in the directory.</returns>
/// <remarks>Filesystem-relative paths use forward-slashes as directory separators.</remarks>
public IEnumerable<string> GetFiles(string path, string filter)
{
var fullPath = GetFullPath(path);
@@ -154,12 +201,21 @@ namespace Umbraco.Core.IO
return Enumerable.Empty<string>();
}
/// <summary>
/// Opens a file.
/// </summary>
/// <param name="path">The filesystem-relative path to the file.</param>
/// <returns></returns>
public Stream OpenFile(string path)
{
var fullPath = GetFullPath(path);
return File.OpenRead(fullPath);
}
/// <summary>
/// Deletes a file.
/// </summary>
/// <param name="path">The filesystem-relative path to the file.</param>
public void DeleteFile(string path)
{
var fullPath = GetFullPath(path);
@@ -176,52 +232,53 @@ namespace Umbraco.Core.IO
}
}
/// <summary>
/// Gets a value indicating whether a file exists.
/// </summary>
/// <param name="path">The filesystem-relative path to the file.</param>
/// <returns>A value indicating whether the file exists.</returns>
public bool FileExists(string path)
{
var fullpath = GetFullPath(path);
return File.Exists(fullpath);
}
// beware, many things depend on how the GetRelative/AbsolutePath methods work!
/// <summary>
/// Gets the relative path.
/// Gets the filesystem-relative path of a full path or of an url.
/// </summary>
/// <param name="fullPathOrUrl">The full path or url.</param>
/// <returns>The path, relative to this filesystem's root.</returns>
/// <remarks>
/// <para>The relative path is relative to this filesystem's root, not starting with any
/// directory separator. If input was recognized as a url (path), then output uses url (path) separator
/// chars.</para>
/// directory separator. All separators are forward-slashes.</para>
/// </remarks>
public string GetRelativePath(string fullPathOrUrl)
{
// test url
var path = fullPathOrUrl.Replace('\\', '/'); // ensure url separator char
if (IOHelper.PathStartsWith(path, _rootUrl, '/')) // if it starts with the root url...
return path.Substring(_rootUrl.Length) // strip it
.TrimStart('/'); // it's relative
// if it starts with the root url, strip it and trim the starting slash to make it relative
// eg "/Media/1234/img.jpg" => "1234/img.jpg"
if (IOHelper.PathStartsWith(path, _rootUrl, '/'))
return path.Substring(_rootUrl.Length).TrimStart('/');
// test path
path = EnsureDirectorySeparatorChar(fullPathOrUrl);
// if it starts with the root path, strip it and trim the starting slash to make it relative
// eg "c:/websites/test/root/Media/1234/img.jpg" => "1234/img.jpg"
if (IOHelper.PathStartsWith(path, _rootPathFwd, '/'))
return path.Substring(_rootPathFwd.Length).TrimStart('/');
if (IOHelper.PathStartsWith(path, _rootPath, Path.DirectorySeparatorChar)) // if it starts with the root path
return path.Substring(_rootPath.Length) // strip it
.TrimStart(Path.DirectorySeparatorChar); // it's relative
// unchanged - including separators
return fullPathOrUrl;
// unchanged - what else?
return path;
}
/// <summary>
/// Gets the full path.
/// </summary>
/// <param name="path">The full or relative path.</param>
/// <param name="path">The full or filesystem-relative path.</param>
/// <returns>The full path.</returns>
/// <remarks>
/// <para>On the physical filesystem, the full path is the rooted (ie non-relative), safe (ie within this
/// filesystem's root) path. All separators are converted to Path.DirectorySeparatorChar.</para>
/// filesystem's root) path. All separators are Path.DirectorySeparatorChar.</para>
/// </remarks>
public string GetFullPath(string path)
{
@@ -229,49 +286,82 @@ namespace Umbraco.Core.IO
var opath = path;
path = EnsureDirectorySeparatorChar(path);
// fixme - this part should go!
// not sure what we are doing here - so if input starts with a (back) slash,
// we assume it's not a FS relative path and we try to convert it... but it
// really makes little sense?
if (path.StartsWith(Path.DirectorySeparatorChar.ToString()))
path = GetRelativePath(path);
// if already a full path, return
if (IOHelper.PathStartsWith(path, _rootPath, Path.DirectorySeparatorChar))
return path;
// if not already rooted, combine with the root path
if (IOHelper.PathStartsWith(path, _rootPath, Path.DirectorySeparatorChar) == false)
path = Path.Combine(_rootPath, path);
// else combine and sanitize, ie GetFullPath will take care of any relative
// sanitize - GetFullPath will take care of any relative
// segments in path, eg '../../foo.tmp' - it may throw a SecurityException
// if the combined path reaches illegal parts of the filesystem
var fpath = Path.Combine(_rootPath, path);
fpath = Path.GetFullPath(fpath);
path = Path.GetFullPath(path);
// at that point, path is within legal parts of the filesystem, ie we have
// permissions to reach that path, but it may nevertheless be outside of
// our root path, due to relative segments, so better check
if (IOHelper.PathStartsWith(fpath, _rootPath, Path.DirectorySeparatorChar))
return fpath;
if (IOHelper.PathStartsWith(path, _rootPath, Path.DirectorySeparatorChar))
return path;
// nothing prevents us to reach the file, security-wise, yet it is outside
// this filesystem's root - throw
throw new FileSecurityException("File '" + opath + "' is outside this filesystem's root.");
}
/// <summary>
/// Gets the url.
/// </summary>
/// <param name="path">The filesystem-relative path.</param>
/// <returns>The url.</returns>
/// <remarks>All separators are forward-slashes.</remarks>
public string GetUrl(string path)
{
path = EnsureUrlSeparatorChar(path).Trim('/');
return _rootUrl + "/" + path;
}
/// <summary>
/// Gets the last-modified date of a directory or file.
/// </summary>
/// <param name="path">The filesystem-relative path to the directory or the file.</param>
/// <returns>The last modified date of the directory or the file.</returns>
public DateTimeOffset GetLastModified(string path)
{
return DirectoryExists(path)
? new DirectoryInfo(GetFullPath(path)).LastWriteTimeUtc
: new FileInfo(GetFullPath(path)).LastWriteTimeUtc;
var fullpath = GetFullPath(path);
return DirectoryExists(fullpath)
? new DirectoryInfo(fullpath).LastWriteTimeUtc
: new FileInfo(fullpath).LastWriteTimeUtc;
}
/// <summary>
/// Gets the created date of a directory or file.
/// </summary>
/// <param name="path">The filesystem-relative path to the directory or the file.</param>
/// <returns>The created date of the directory or the file.</returns>
public DateTimeOffset GetCreated(string path)
{
return DirectoryExists(path)
? Directory.GetCreationTimeUtc(GetFullPath(path))
: File.GetCreationTimeUtc(GetFullPath(path));
var fullpath = GetFullPath(path);
return DirectoryExists(fullpath)
? Directory.GetCreationTimeUtc(fullpath)
: File.GetCreationTimeUtc(fullpath);
}
/// <summary>
/// Gets the size of a file.
/// </summary>
/// <param name="path">The filesystem-relative path to the file.</param>
/// <returns>The file of the size, in bytes.</returns>
/// <remarks>If the file does not exist, returns -1.</remarks>
public long GetSize(string path)
{
var fullPath = GetFullPath(path);
var file = new FileInfo(fullPath);
return file.Exists ? file.Length : -1;
}
#region Helper Methods
-20
View File
@@ -1,20 +0,0 @@
namespace Umbraco.Core.IO
{
internal class ResizedImage
{
public ResizedImage()
{
}
public ResizedImage(int width, int height, string fileName)
{
Width = width;
Height = height;
FileName = fileName;
}
public int Width { get; set; }
public int Height { get; set; }
public string FileName { get; set; }
}
}
+286
View File
@@ -0,0 +1,286 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Umbraco.Core.IO
{
internal class ShadowFileSystem : IFileSystem2
{
private readonly IFileSystem _fs;
private readonly IFileSystem2 _sfs;
public ShadowFileSystem(IFileSystem fs, IFileSystem2 sfs)
{
_fs = fs;
_sfs = sfs;
}
public IFileSystem Inner
{
get { return _fs; }
}
public void Complete()
{
if (_nodes == null) return;
var exceptions = new List<Exception>();
foreach (var kvp in _nodes)
{
if (kvp.Value.IsExist)
{
if (kvp.Value.IsFile)
{
try
{
using (var stream = _sfs.OpenFile(kvp.Key))
_fs.AddFile(kvp.Key, stream, true);
}
catch (Exception e)
{
exceptions.Add(new Exception("Could not save file \"" + kvp.Key + "\".", e));
}
}
}
else
{
try
{
if (kvp.Value.IsDir)
_fs.DeleteDirectory(kvp.Key, true);
else
_fs.DeleteFile(kvp.Key);
}
catch (Exception e)
{
exceptions.Add(new Exception("Could not delete " + (kvp.Value.IsDir ? "directory": "file") + " \"" + kvp.Key + "\".", e));
}
}
}
_nodes.Clear();
if (exceptions.Count == 0) return;
throw new AggregateException("Failed to apply all changes (see exceptions).", exceptions);
}
private Dictionary<string, ShadowNode> _nodes;
private Dictionary<string, ShadowNode> Nodes { get { return _nodes ?? (_nodes = new Dictionary<string, ShadowNode>()); } }
private class ShadowNode
{
public ShadowNode(bool isDelete, bool isdir)
{
IsDelete = isDelete;
IsDir = isdir;
}
public bool IsDelete { get; private set; }
public bool IsDir { get; private set; }
public bool IsExist { get { return IsDelete == false; } }
public bool IsFile { get { return IsDir == false; } }
}
private static string NormPath(string path)
{
return path.ToLowerInvariant().Replace("\\", "/");
}
// values can be "" (root), "foo", "foo/bar"...
private static bool IsChild(string path, string input)
{
if (input.StartsWith(path) == false || input.Length < path.Length + 2)
return false;
if (path.Length > 0 && input[path.Length] != '/') return false;
var pos = input.IndexOf("/", path.Length + 1, StringComparison.OrdinalIgnoreCase);
return pos < 0;
}
private static bool IsDescendant(string path, string input)
{
if (input.StartsWith(path) == false || input.Length < path.Length + 2)
return false;
return path.Length == 0 || input[path.Length] == '/';
}
public IEnumerable<string> GetDirectories(string path)
{
var normPath = NormPath(path);
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
var directories = _fs.GetDirectories(path);
return directories
.Except(shadows.Where(kvp => (kvp.Value.IsDir && kvp.Value.IsDelete) || (kvp.Value.IsFile && kvp.Value.IsExist))
.Select(kvp => kvp.Key))
.Union(shadows.Where(kvp => kvp.Value.IsDir && kvp.Value.IsExist).Select(kvp => kvp.Key))
.Distinct();
}
public void DeleteDirectory(string path)
{
DeleteDirectory(path, false);
}
public void DeleteDirectory(string path, bool recursive)
{
if (DirectoryExists(path) == false) return;
var normPath = NormPath(path);
if (recursive)
{
Nodes[normPath] = new ShadowNode(true, true);
var remove = Nodes.Where(x => IsDescendant(normPath, x.Key)).ToList();
foreach (var kvp in remove) Nodes.Remove(kvp.Key);
Delete(path, true);
}
else
{
if (Nodes.Any(x => IsChild(normPath, x.Key) && x.Value.IsExist) // shadow content
|| _fs.GetDirectories(path).Any() || _fs.GetFiles(path).Any()) // actual content
throw new InvalidOperationException("Directory is not empty.");
Nodes[path] = new ShadowNode(true, true);
var remove = Nodes.Where(x => IsChild(normPath, x.Key)).ToList();
foreach (var kvp in remove) Nodes.Remove(kvp.Key);
Delete(path, false);
}
}
private void Delete(string path, bool recurse)
{
foreach (var file in _fs.GetFiles(path))
{
Nodes[NormPath(file)] = new ShadowNode(true, false);
}
foreach (var dir in _fs.GetDirectories(path))
{
Nodes[NormPath(dir)] = new ShadowNode(true, true);
if (recurse) Delete(dir, true);
}
}
public bool DirectoryExists(string path)
{
ShadowNode sf;
if (Nodes.TryGetValue(NormPath(path), out sf))
return sf.IsDir && sf.IsExist;
return _fs.DirectoryExists(path);
}
public void AddFile(string path, Stream stream)
{
AddFile(path, stream, true);
}
public void AddFile(string path, Stream stream, bool overrideIfExists)
{
ShadowNode sf;
var normPath = NormPath(path);
if (Nodes.TryGetValue(normPath, out sf) && sf.IsExist && (sf.IsDir || overrideIfExists == false))
throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
var parts = normPath.Split('/');
for (var i = 0; i < parts.Length - 1; i++)
{
var dirPath = string.Join("/", parts.Take(i + 1));
ShadowNode sd;
if (Nodes.TryGetValue(dirPath, out sd))
{
if (sd.IsFile) throw new InvalidOperationException("Invalid path.");
if (sd.IsDelete) Nodes[dirPath] = new ShadowNode(false, true);
}
else
{
if (_fs.DirectoryExists(dirPath)) continue;
if (_fs.FileExists(dirPath)) throw new InvalidOperationException("Invalid path.");
Nodes[dirPath] = new ShadowNode(false, true);
}
}
_sfs.AddFile(path, stream, overrideIfExists);
Nodes[normPath] = new ShadowNode(false, false);
}
public IEnumerable<string> GetFiles(string path)
{
var normPath = NormPath(path);
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
var files = _fs.GetFiles(path);
return files
.Except(shadows.Where(kvp => (kvp.Value.IsFile && kvp.Value.IsDelete) || kvp.Value.IsDir)
.Select(kvp => kvp.Key))
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist).Select(kvp => kvp.Key))
.Distinct();
}
public IEnumerable<string> GetFiles(string path, string filter)
{
return _fs.GetFiles(path, filter);
}
public Stream OpenFile(string path)
{
ShadowNode sf;
if (Nodes.TryGetValue(NormPath(path), out sf))
return sf.IsDir || sf.IsDelete ? null : _sfs.OpenFile(path);
return _fs.OpenFile(path);
}
public void DeleteFile(string path)
{
if (FileExists(path) == false) return;
Nodes[NormPath(path)] = new ShadowNode(true, false);
}
public bool FileExists(string path)
{
ShadowNode sf;
if (Nodes.TryGetValue(NormPath(path), out sf))
return sf.IsFile && sf.IsExist;
return _fs.FileExists(path);
}
public string GetRelativePath(string fullPathOrUrl)
{
return _fs.GetRelativePath(fullPathOrUrl);
}
public string GetFullPath(string path)
{
return _fs.GetFullPath(path);
}
public string GetUrl(string path)
{
return _fs.GetUrl(path);
}
public DateTimeOffset GetLastModified(string path)
{
ShadowNode sf;
if (Nodes.TryGetValue(NormPath(path), out sf) == false) return _fs.GetLastModified(path);
if (sf.IsDelete) throw new InvalidOperationException("Invalid path.");
return _sfs.GetLastModified(path);
}
public DateTimeOffset GetCreated(string path)
{
ShadowNode sf;
if (Nodes.TryGetValue(NormPath(path), out sf) == false) return _fs.GetCreated(path);
if (sf.IsDelete) throw new InvalidOperationException("Invalid path.");
return _sfs.GetCreated(path);
}
public long GetSize(string path)
{
ShadowNode sf;
if (Nodes.TryGetValue(NormPath(path), out sf) == false)
{
// the inner filesystem (_fs) can be IFileSystem2... or just IFileSystem
// figure it out and use the most effective GetSize method
var fs2 = _fs as IFileSystem2;
return fs2 == null ? _fs.GetSize(path) : fs2.GetSize(path);
}
if (sf.IsDelete || sf.IsDir) throw new InvalidOperationException("Invalid path.");
return _sfs.GetSize(path);
}
}
}
@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;
using Umbraco.Core.Logging;
namespace Umbraco.Core.IO
{
internal class ShadowFileSystemsScope : ICompletable
{
// note: taking a reference to the _manager instead of using manager.Current
// to avoid using Current everywhere but really, we support only 1 scope at
// a time, not multiple scopes in case of multiple managers (not supported)
private const string ItemKey = "Umbraco.Core.IO.ShadowFileSystemsScope";
private static readonly object Locker = new object();
private readonly Guid _id;
private readonly ShadowWrapper[] _wrappers;
static ShadowFileSystemsScope()
{
SafeCallContext.Register(
() =>
{
var scope = CallContext.LogicalGetData(ItemKey);
CallContext.FreeNamedDataSlot(ItemKey);
return scope;
},
o =>
{
if (CallContext.LogicalGetData(ItemKey) != null) throw new InvalidOperationException();
if (o != null) CallContext.LogicalSetData(ItemKey, o);
});
}
private ShadowFileSystemsScope(Guid id, ShadowWrapper[] wrappers)
{
LogHelper.Debug<ShadowFileSystemsScope>("Shadow " + id + ".");
_id = id;
_wrappers = wrappers;
foreach (var wrapper in _wrappers)
wrapper.Shadow(id);
}
// internal for tests + FileSystemProviderManager
// do NOT use otherwise
internal static ShadowFileSystemsScope CreateScope(Guid id, ShadowWrapper[] wrappers)
{
lock (Locker)
{
if (CallContext.LogicalGetData(ItemKey) != null) throw new InvalidOperationException("Already shadowing.");
CallContext.LogicalSetData(ItemKey, ItemKey); // value does not matter
}
return new ShadowFileSystemsScope(id, wrappers);
}
internal static bool InScope
{
get { return NoScope == false; }
}
internal static bool NoScope
{
get { return CallContext.LogicalGetData(ItemKey) == null; }
}
public void Complete()
{
lock (Locker)
{
LogHelper.Debug<ShadowFileSystemsScope>("UnShadow " + _id + " (complete).");
var exceptions = new List<Exception>();
foreach (var wrapper in _wrappers)
{
try
{
// this may throw an AggregateException if some of the changes could not be applied
wrapper.UnShadow(true);
}
catch (AggregateException ae)
{
exceptions.Add(ae);
}
}
if (exceptions.Count > 0)
throw new AggregateException("Failed to apply all changes (see exceptions).", exceptions);
// last, & *only* if successful (otherwise we'll unshadow & cleanup as best as we can)
CallContext.FreeNamedDataSlot(ItemKey);
}
}
public void Dispose()
{
lock (Locker)
{
if (CallContext.LogicalGetData(ItemKey) == null) return;
try
{
LogHelper.Debug<ShadowFileSystemsScope>("UnShadow " + _id + " (abort)");
foreach (var wrapper in _wrappers)
wrapper.UnShadow(false); // should not throw
}
finally
{
// last, & always
CallContext.FreeNamedDataSlot(ItemKey);
}
}
}
}
}
+158
View File
@@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Umbraco.Core.IO
{
internal class ShadowWrapper : IFileSystem2
{
private readonly IFileSystem _innerFileSystem;
private readonly string _shadowPath;
private ShadowFileSystem _shadowFileSystem;
private string _shadowDir;
public ShadowWrapper(IFileSystem innerFileSystem, string shadowPath)
{
_innerFileSystem = innerFileSystem;
_shadowPath = shadowPath;
}
internal void Shadow(Guid id)
{
// note: no thread-safety here, because ShadowFs is thread-safe due to the check
// on ShadowFileSystemsScope.None - and if None is false then we should be running
// in a single thread anyways
var virt = "~/App_Data/Shadow/" + id + "/" + _shadowPath;
_shadowDir = IOHelper.MapPath(virt);
Directory.CreateDirectory(_shadowDir);
var tempfs = new PhysicalFileSystem(virt);
_shadowFileSystem = new ShadowFileSystem(_innerFileSystem, tempfs);
}
internal void UnShadow(bool complete)
{
var shadowFileSystem = _shadowFileSystem;
var dir = _shadowDir;
_shadowFileSystem = null;
_shadowDir = null;
try
{
// this may throw an AggregateException if some of the changes could not be applied
if (complete) shadowFileSystem.Complete();
}
finally
{
// in any case, cleanup
try
{
Directory.Delete(dir, true);
dir = dir.Substring(0, dir.Length - _shadowPath.Length - 1);
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
Directory.Delete(dir, true);
}
catch
{
// ugly, isn't it? but if we cannot cleanup, bah, just leave it there
}
}
}
private IFileSystem FileSystem
{
get { return ShadowFileSystemsScope.NoScope ? _innerFileSystem : _shadowFileSystem; }
}
public IEnumerable<string> GetDirectories(string path)
{
return FileSystem.GetDirectories(path);
}
public void DeleteDirectory(string path)
{
FileSystem.DeleteDirectory(path);
}
public void DeleteDirectory(string path, bool recursive)
{
FileSystem.DeleteDirectory(path, recursive);
}
public bool DirectoryExists(string path)
{
return FileSystem.DirectoryExists(path);
}
public void AddFile(string path, Stream stream)
{
FileSystem.AddFile(path, stream);
}
public void AddFile(string path, Stream stream, bool overrideExisting)
{
FileSystem.AddFile(path, stream, overrideExisting);
}
public IEnumerable<string> GetFiles(string path)
{
return FileSystem.GetFiles(path);
}
public IEnumerable<string> GetFiles(string path, string filter)
{
return FileSystem.GetFiles(path, filter);
}
public Stream OpenFile(string path)
{
return FileSystem.OpenFile(path);
}
public void DeleteFile(string path)
{
FileSystem.DeleteFile(path);
}
public bool FileExists(string path)
{
return FileSystem.FileExists(path);
}
public string GetRelativePath(string fullPathOrUrl)
{
return FileSystem.GetRelativePath(fullPathOrUrl);
}
public string GetFullPath(string path)
{
return FileSystem.GetFullPath(path);
}
public string GetUrl(string path)
{
return FileSystem.GetUrl(path);
}
public DateTimeOffset GetLastModified(string path)
{
return FileSystem.GetLastModified(path);
}
public DateTimeOffset GetCreated(string path)
{
return FileSystem.GetCreated(path);
}
public long GetSize(string path)
{
var filesystem = FileSystem; // will be either a ShadowFileSystem OR the actual underlying IFileSystem
// and the underlying filesystem can be IFileSystem2... or just IFileSystem
// figure it out and use the most effective GetSize method
var filesystem2 = filesystem as IFileSystem2;
return filesystem2 == null ? filesystem.GetSize(path) : filesystem2.GetSize(path);
}
}
}
+17 -1
View File
@@ -96,7 +96,23 @@ namespace Umbraco.Core.IO
}
}
public static string PartialViews
{
get
{
return MvcViews + "/Partials/";
}
}
public static string MacroPartials
{
get
{
return MvcViews + "/MacroPartials/";
}
}
public static string Media
{
get
+31 -69
View File
@@ -1,13 +1,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Media;
@@ -86,15 +80,15 @@ namespace Umbraco.Core.IO
private void Initialize()
{
Filename = _fs.GetFileName(Path);
Extension = _fs.GetExtension(Path) != null
? _fs.GetExtension(Path).Substring(1).ToLowerInvariant()
var ext = _fs.GetExtension(Path);
Extension = string.IsNullOrEmpty(ext) == false
? ext.TrimStart('.').ToLowerInvariant()
: "";
Url = _fs.GetUrl(Path);
Exists = _fs.FileExists(Path);
if (Exists == false)
{
LogHelper.Warn<UmbracoMediaFile>("The media file doesn't exist: " + Path);
}
}
public bool Exists { get; private set; }
@@ -117,27 +111,15 @@ namespace Umbraco.Core.IO
{
get
{
if (_length == null)
{
if (Exists)
{
_length = _fs.GetSize(Path);
}
else
{
_length = -1;
}
}
if (_length.HasValue) return _length.Value;
_length = Exists ? _fs.GetSize(Path) : -1;
return _length.Value;
}
}
public bool SupportsResizing
{
get
{
return UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes.InvariantContains(Extension);
}
get { return _fs.IsImageFile(Extension); }
}
public string GetFriendlyName()
@@ -147,67 +129,49 @@ namespace Umbraco.Core.IO
public Size GetDimensions()
{
if (_size == null)
{
if (_fs.FileExists(Path))
{
EnsureFileSupportsResizing();
if (_size.HasValue) return _size.Value;
using (var fs = _fs.OpenFile(Path))
{
_size = ImageHelper.GetDimensions(fs);
}
}
else
if (_fs.FileExists(Path))
{
EnsureFileSupportsResizing();
using (var fs = _fs.OpenFile(Path))
{
_size = new Size(-1, -1);
_size = _fs.GetDimensions(fs);
}
}
else
{
_size = new Size(-1, -1);
}
return _size.Value;
}
public string Resize(int width, int height)
{
if (Exists)
{
EnsureFileSupportsResizing();
if (Exists == false) return string.Empty;
var fileNameThumb = DoResize(width, height, -1, string.Empty);
return _fs.GetUrl(fileNameThumb);
}
return string.Empty;
EnsureFileSupportsResizing();
var filepath = Resize(width, height, -1, string.Empty);
return _fs.GetUrl(filepath);
}
public string Resize(int maxWidthHeight, string fileNameAddition)
{
if (Exists)
{
EnsureFileSupportsResizing();
if (Exists == false) return string.Empty;
var fileNameThumb = DoResize(-1, -1, maxWidthHeight, fileNameAddition);
return _fs.GetUrl(fileNameThumb);
}
return string.Empty;
EnsureFileSupportsResizing();
var filepath = Resize(-1, -1, maxWidthHeight, fileNameAddition);
return _fs.GetUrl(filepath);
}
private string DoResize(int width, int height, int maxWidthHeight, string fileNameAddition)
private string Resize(int width, int height, int maxWidthHeight, string sizeName)
{
using (var fs = _fs.OpenFile(Path))
using (var filestream = _fs.OpenFile(Path))
using (var image = Image.FromStream(filestream))
{
using (var image = Image.FromStream(fs))
{
var fileNameThumb = string.IsNullOrWhiteSpace(fileNameAddition)
? string.Format("{0}_UMBRACOSYSTHUMBNAIL." + Extension, Path.Substring(0, Path.LastIndexOf(".", StringComparison.Ordinal)))
: string.Format("{0}_{1}." + Extension, Path.Substring(0, Path.LastIndexOf(".", StringComparison.Ordinal)), fileNameAddition);
var thumbnail = maxWidthHeight == -1
? ImageHelper.GenerateThumbnail(image, width, height, fileNameThumb, Extension, _fs)
: ImageHelper.GenerateThumbnail(image, maxWidthHeight, fileNameThumb, Extension, _fs);
return thumbnail.FileName;
}
return _fs.GenerateResized(image, Path, sizeName, maxWidthHeight, width, height).Filepath;
}
}
@@ -216,7 +180,5 @@ namespace Umbraco.Core.IO
if (SupportsResizing == false)
throw new InvalidOperationException(string.Format("The file {0} is not an image, so can't get dimensions", Filename));
}
}
}
@@ -3,7 +3,11 @@ using System.Linq;
namespace Umbraco.Core.Logging
{
internal class DebugDiagnosticsLogger : ILogger
/// <summary>
/// Implements <see cref="ILogger"/> on top of System.Diagnostics.Debug.
/// </summary>
/// <remarks>Useful for tests.</remarks>
public class DebugDiagnosticsLogger : ILogger
{
public void Error(Type callingType, string message, Exception exception)
{
+60 -22
View File
@@ -1,18 +1,21 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.MemoryMappedFiles;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Core
{
// represents the main domain
class MainDom : IRegisteredObject
/// <summary>
/// Represents the main AppDomain running for a given application.
/// </summary>
/// <remarks>
/// <para>There can be only one "main" AppDomain running for a given application at a time.</para>
/// <para>When an AppDomain starts, it tries to acquire the main domain status.</para>
/// <para>When an AppDomain stops (eg the application is restarting) it should release the main domain status.</para>
/// <para>It is possible to register against the MainDom and be notified when it is released.</para>
/// </remarks>
internal class MainDom : IRegisteredObject
{
#region Vars
@@ -25,7 +28,7 @@ namespace Umbraco.Core
private readonly AsyncLock _asyncLock;
private IDisposable _asyncLocker;
// event wait handle used to notify current main domain that it should
// event wait handle used to notify current main domain that it should
// release the lock because a new domain wants to be the main domain
private readonly EventWaitHandle _signal;
@@ -34,16 +37,26 @@ namespace Umbraco.Core
private volatile bool _signaled; // we have been signaled
// actions to run before releasing the main domain
private readonly SortedList<int, Action> _callbacks = new SortedList<int, Action>();
private readonly SortedList<int, Action> _callbacks = new SortedList<int, Action>(new WeightComparer());
private const int LockTimeoutMilliseconds = 90000; // (1.5 * 60 * 1000) == 1 min 30 seconds
private class WeightComparer : IComparer<int>
{
public int Compare(int x, int y)
{
var result = x.CompareTo(y);
// return "equal" as "greater than"
return result == 0 ? 1 : result;
}
}
#endregion
#region Ctor
// initializes a new instance of MainDom
public MainDom(ILogger logger)
internal MainDom(ILogger logger)
{
_logger = logger;
@@ -52,22 +65,47 @@ namespace Umbraco.Core
if (HostingEnvironment.ApplicationID != null)
appId = HostingEnvironment.ApplicationID.ReplaceNonAlphanumericChars(string.Empty);
var lockName = "UMBRACO-" + appId + "-MAINDOM-LCK";
// combining with the physical path because if running on eg IIS Express,
// two sites could have the same appId even though they are different.
//
// now what could still collide is... two sites, running in two different processes
// and having the same appId, and running on the same app physical path
//
// we *cannot* use the process ID here because when an AppPool restarts it is
// a new process for the same application path
var appPath = HostingEnvironment.ApplicationPhysicalPath;
var hash = (appId + ":::" + appPath).ToSHA1();
var lockName = "UMBRACO-" + hash + "-MAINDOM-LCK";
_asyncLock = new AsyncLock(lockName);
var eventName = "UMBRACO-" + appId + "-MAINDOM-EVT";
var eventName = "UMBRACO-" + hash + "-MAINDOM-EVT";
_signal = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
}
#endregion
// register a main domain consumer
/// <summary>
/// Registers a resource that requires the current AppDomain to be the main domain to function.
/// </summary>
/// <param name="release">An action to execute before the AppDomain releases the main domain status.</param>
/// <param name="weight">An optional weight (lower goes first).</param>
/// <returns>A value indicating whether it was possible to register.</returns>
public bool Register(Action release, int weight = 100)
{
return Register(null, release, weight);
}
// register a main domain consumer
/// <summary>
/// Registers a resource that requires the current AppDomain to be the main domain to function.
/// </summary>
/// <param name="install">An action to execute when registering.</param>
/// <param name="release">An action to execute before the AppDomain releases the main domain status.</param>
/// <param name="weight">An optional weight (lower goes first).</param>
/// <returns>A value indicating whether it was possible to register.</returns>
/// <remarks>If registering is successful, then the <paramref name="install"/> action
/// is guaranteed to execute before the AppDomain releases the main domain status.</remarks>
public bool Register(Action install, Action release, int weight = 100)
{
lock (_locko)
@@ -97,7 +135,7 @@ namespace Umbraco.Core
try
{
_logger.Debug<MainDom>("Stopping...");
_logger.Info<MainDom>("Stopping...");
foreach (var callback in _callbacks.Values)
{
try
@@ -109,7 +147,7 @@ namespace Umbraco.Core
_logger.Error<MainDom>("Error while running callback, remaining callbacks will not run.", e);
throw;
}
}
_logger.Debug<MainDom>("Stopped.");
}
@@ -118,12 +156,12 @@ namespace Umbraco.Core
// in any case...
_isMainDom = false;
_asyncLocker.Dispose();
_logger.Debug<MainDom>("Released MainDom.");
_logger.Info<MainDom>("Released MainDom.");
}
}
// acquires the main domain
public bool Acquire()
internal bool Acquire()
{
lock (_locko) // we don't want the hosting environment to interfere by signaling
{
@@ -131,11 +169,11 @@ namespace Umbraco.Core
// the handler is not installed so that would be the hosting environment
if (_signaled)
{
_logger.Debug<MainDom>("Cannot acquire MainDom (signaled).");
_logger.Info<MainDom>("Cannot acquire MainDom (signaled).");
return false;
}
_logger.Debug<MainDom>("Acquiring MainDom...");
_logger.Info<MainDom>("Acquiring MainDom...");
// signal other instances that we want the lock, then wait one the lock,
// which may timeout, and this is accepted - see comments below
@@ -162,7 +200,7 @@ namespace Umbraco.Core
HostingEnvironment.RegisterObject(this);
_logger.Debug<MainDom>("Acquired MainDom.");
_logger.Info<MainDom>("Acquired MainDom.");
return true;
}
}
@@ -174,7 +212,7 @@ namespace Umbraco.Core
}
// IRegisteredObject
public void Stop(bool immediate)
void IRegisteredObject.Stop(bool immediate)
{
try
{
+21
View File
@@ -0,0 +1,21 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
namespace Umbraco.Core.Media
{
public static class ImageExtensions
{
/// <summary>
/// Gets the MIME type of an image.
/// </summary>
/// <param name="image">The image.</param>
/// <returns>The MIME type of the image.</returns>
public static string GetMimeType(this Image image)
{
var format = image.RawFormat;
var codec = ImageCodecInfo.GetImageDecoders().First(c => c.FormatID == format.Guid);
return codec.MimeType;
}
}
}
-261
View File
@@ -1,261 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using Umbraco.Core.IO;
using Umbraco.Core.Media.Exif;
namespace Umbraco.Core.Media
{
/// <summary>
/// A helper class used for imaging
/// </summary>
internal static class ImageHelper
{
/// <summary>
/// Gets the dimensions of an image based on a stream
/// </summary>
/// <param name="imageStream"></param>
/// <returns></returns>
/// <remarks>
/// First try with EXIF, this is because it is insanely faster and doesn't use any memory to read exif data than to load in the entire
/// image via GDI. Otherwise loading an image into GDI consumes a crazy amount of memory on large images.
///
/// Of course EXIF data might not exist in every file and can only exist in JPGs
/// </remarks>
public static Size GetDimensions(Stream imageStream)
{
//Try to load with exif
try
{
var jpgInfo = ImageFile.FromStream(imageStream);
if (jpgInfo.Format != ImageFileFormat.Unknown
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension)
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension))
{
var height = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelYDimension].Value);
var width = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelXDimension].Value);
if (height > 0 && width > 0)
{
return new Size(width, height);
}
}
}
catch (Exception)
{
//We will just swallow, just means we can't read exif data, we don't want to log an error either
}
//we have no choice but to try to read in via GDI
using (var image = Image.FromStream(imageStream))
{
var fileWidth = image.Width;
var fileHeight = image.Height;
return new Size(fileWidth, fileHeight);
}
}
public static string GetMimeType(this Image image)
{
var format = image.RawFormat;
var codec = ImageCodecInfo.GetImageDecoders().First(c => c.FormatID == format.Guid);
return codec.MimeType;
}
/// <summary>
/// Creates the thumbnails if the image is larger than all of the specified ones.
/// </summary>
/// <param name="fs"></param>
/// <param name="fileName"></param>
/// <param name="extension"></param>
/// <param name="originalImage"></param>
/// <param name="additionalThumbSizes"></param>
/// <returns></returns>
internal static IEnumerable<ResizedImage> GenerateMediaThumbnails(
IFileSystem fs,
string fileName,
string extension,
Image originalImage,
IEnumerable<int> additionalThumbSizes)
{
var result = new List<ResizedImage>();
var allSizesDictionary = new Dictionary<int, string> { { 100, "thumb" }, { 500, "big-thumb" } };
//combine the static dictionary with the additional sizes with only unique values
var allSizes = allSizesDictionary.Select(kv => kv.Key)
.Union(additionalThumbSizes.Where(x => x > 0).Distinct());
var sizesDictionary = allSizes.ToDictionary(s => s, s => allSizesDictionary.ContainsKey(s) ? allSizesDictionary[s] : "");
foreach (var s in sizesDictionary)
{
var size = s.Key;
var name = s.Value;
if (originalImage.Width >= size && originalImage.Height >= size)
{
result.Add(Resize(fs, fileName, extension, size, name, originalImage));
}
}
return result;
}
/// <summary>
/// Performs an image resize
/// </summary>
/// <param name="fileSystem"></param>
/// <param name="path"></param>
/// <param name="extension"></param>
/// <param name="maxWidthHeight"></param>
/// <param name="fileNameAddition"></param>
/// <param name="originalImage"></param>
/// <returns></returns>
private static ResizedImage Resize(IFileSystem fileSystem, string path, string extension, int maxWidthHeight, string fileNameAddition, Image originalImage)
{
var fileNameThumb = string.IsNullOrWhiteSpace(fileNameAddition)
? string.Format("{0}_UMBRACOSYSTHUMBNAIL." + extension, path.Substring(0, path.LastIndexOf(".", StringComparison.Ordinal)))
: string.Format("{0}_{1}." + extension, path.Substring(0, path.LastIndexOf(".", StringComparison.Ordinal)), fileNameAddition);
var thumb = GenerateThumbnail(
originalImage,
maxWidthHeight,
fileNameThumb,
extension,
fileSystem);
return thumb;
}
internal static ResizedImage GenerateThumbnail(Image image, int maxWidthHeight, string thumbnailFileName, string extension, IFileSystem fs)
{
return GenerateThumbnail(image, maxWidthHeight, -1, -1, thumbnailFileName, extension, fs);
}
internal static ResizedImage GenerateThumbnail(Image image, int fixedWidth, int fixedHeight, string thumbnailFileName, string extension, IFileSystem fs)
{
return GenerateThumbnail(image, -1, fixedWidth, fixedHeight, thumbnailFileName, extension, fs);
}
private static ResizedImage GenerateThumbnail(Image image, int maxWidthHeight, int fixedWidth, int fixedHeight, string thumbnailFileName, string extension, IFileSystem fs)
{
// Generate thumbnail
float f = 1;
if (maxWidthHeight >= 0)
{
var fx = (float)image.Size.Width / maxWidthHeight;
var fy = (float)image.Size.Height / maxWidthHeight;
// must fit in thumbnail size
f = Math.Max(fx, fy);
}
//depending on if we are doing fixed width resizing or not.
fixedWidth = (maxWidthHeight > 0) ? image.Width : fixedWidth;
fixedHeight = (maxWidthHeight > 0) ? image.Height : fixedHeight;
var widthTh = (int)Math.Round(fixedWidth / f);
var heightTh = (int)Math.Round(fixedHeight / f);
// fixes for empty width or height
if (widthTh == 0)
widthTh = 1;
if (heightTh == 0)
heightTh = 1;
// Create new image with best quality settings
using (var bp = new Bitmap(widthTh, heightTh))
{
using (var g = Graphics.FromImage(bp))
{
//if the image size is rather large we cannot use the best quality interpolation mode
// because we'll get out of mem exceptions. So we'll detect how big the image is and use
// the mid quality interpolation mode when the image size exceeds our max limit.
if (image.Width > 5000 || image.Height > 5000)
{
//use mid quality
g.InterpolationMode = InterpolationMode.Bilinear;
}
else
{
//use best quality
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
}
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
// Copy the old image to the new and resized
var rect = new Rectangle(0, 0, widthTh, heightTh);
g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
// Copy metadata
var imageEncoders = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo codec;
switch (extension.ToLower())
{
case "png":
codec = imageEncoders.Single(t => t.MimeType.Equals("image/png"));
break;
case "gif":
codec = imageEncoders.Single(t => t.MimeType.Equals("image/gif"));
break;
case "tif":
case "tiff":
codec = imageEncoders.Single(t => t.MimeType.Equals("image/tiff"));
break;
case "bmp":
codec = imageEncoders.Single(t => t.MimeType.Equals("image/bmp"));
break;
// TODO: this is dirty, defaulting to jpg but the return value of this thing is used all over the
// place so left it here, but it needs to not set a codec if it doesn't know which one to pick
// Note: when fixing this: both .jpg and .jpeg should be handled as extensions
default:
codec = imageEncoders.Single(t => t.MimeType.Equals("image/jpeg"));
break;
}
// Set compresion ratio to 90%
var ep = new EncoderParameters();
ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
// Save the new image using the dimensions of the image
var predictableThumbnailName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", maxWidthHeight.ToString(CultureInfo.InvariantCulture));
var predictableThumbnailNameJpg = predictableThumbnailName.Substring(0, predictableThumbnailName.LastIndexOf(".", StringComparison.Ordinal)) + ".jpg";
using (var ms = new MemoryStream())
{
bp.Save(ms, codec, ep);
ms.Seek(0, 0);
fs.AddFile(predictableThumbnailName, ms);
fs.AddFile(predictableThumbnailNameJpg, ms);
}
// TODO: Remove this, this is ONLY here for backwards compatibility but it is essentially completely unusable see U4-5385
var newFileName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", string.Format("{0}x{1}", widthTh, heightTh));
using (var ms = new MemoryStream())
{
bp.Save(ms, codec, ep);
ms.Seek(0, 0);
fs.AddFile(newFileName, ms);
}
return new ResizedImage(widthTh, heightTh, newFileName);
}
}
}
}
}
@@ -1,58 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Umbraco.Core.IO;
namespace Umbraco.Core.Media
{
/// <summary>
/// Internal singleton to handle the numbering of subfolders within the Media-folder.
/// When this class is initiated it will look for numbered subfolders and select the highest number,
/// which will be the start point for the naming of the next subfolders. If no subfolders exists
/// then the starting point will be 1000, ie. /media/1000/koala.jpg
/// </summary>
internal class MediaSubfolderCounter
{
#region Singleton
private long _numberedFolder = 1000;//Default starting point
private static readonly ReaderWriterLockSlim ClearLock = new ReaderWriterLockSlim();
private static readonly Lazy<MediaSubfolderCounter> Lazy = new Lazy<MediaSubfolderCounter>(() => new MediaSubfolderCounter());
public static MediaSubfolderCounter Current { get { return Lazy.Value; } }
private MediaSubfolderCounter()
{
var folders = new List<long>();
var fs = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
var directories = fs.GetDirectories("");
foreach (var directory in directories)
{
long dirNum;
if (long.TryParse(directory, out dirNum))
{
folders.Add(dirNum);
}
}
var last = folders.OrderBy(x => x).LastOrDefault();
if(last != default(long))
_numberedFolder = last;
}
#endregion
/// <summary>
/// Returns an increment of the numbered media subfolders.
/// </summary>
/// <returns>A <see cref="System.Int64"/> value</returns>
public long Increment()
{
using (new ReadLock(ClearLock))
{
_numberedFolder = _numberedFolder + 1;
return _numberedFolder;
}
}
}
}
@@ -0,0 +1,220 @@
using System;
using System.Drawing;
using System.IO;
using System.Linq;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
namespace Umbraco.Core.Media
{
/// <summary>
/// Provides methods to manage auto-fill properties for upload fields.
/// </summary>
internal class UploadAutoFillProperties
{
private readonly ILogger _logger;
private readonly MediaFileSystem _mediaFileSystem;
private readonly IContentSection _contentSettings;
public UploadAutoFillProperties(MediaFileSystem mediaFileSystem, ILogger logger, IContentSection contentSettings)
{
_mediaFileSystem = mediaFileSystem;
_logger = logger;
_contentSettings = contentSettings;
}
/// <summary>
/// Gets the auto-fill configuration for a specified property alias.
/// </summary>
/// <param name="propertyTypeAlias">The property type alias.</param>
/// <returns>The auto-fill configuration for the specified property alias, or null.</returns>
public IImagingAutoFillUploadField GetConfig(string propertyTypeAlias)
{
var autoFillConfigs = _contentSettings.ImageAutoFillProperties;
return autoFillConfigs == null ? null : autoFillConfigs.FirstOrDefault(x => x.Alias == propertyTypeAlias);
}
/// <summary>
/// Resets the auto-fill properties of a content item, for a specified property alias.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="propertyTypeAlias">The property type alias.</param>
public void Reset(IContentBase content, string propertyTypeAlias)
{
if (content == null) throw new ArgumentNullException("content");
if (propertyTypeAlias == null) throw new ArgumentNullException("propertyTypeAlias");
// get the config, no config = nothing to do
var autoFillConfig = GetConfig(propertyTypeAlias);
if (autoFillConfig == null) return; // nothing
// reset
Reset(content, autoFillConfig);
}
/// <summary>
/// Resets the auto-fill properties of a content item, for a specified auto-fill configuration.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="autoFillConfig">The auto-fill configuration.</param>
public void Reset(IContentBase content, IImagingAutoFillUploadField autoFillConfig)
{
if (content == null) throw new ArgumentNullException("content");
if (autoFillConfig == null) throw new ArgumentNullException("autoFillConfig");
ResetProperties(content, autoFillConfig);
}
/// <summary>
/// Populates the auto-fill properties of a content item.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="propertyTypeAlias">The property type alias.</param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
public void Populate(IContentBase content, string propertyTypeAlias, string filepath)
{
if (content == null) throw new ArgumentNullException("content");
if (propertyTypeAlias == null) throw new ArgumentNullException("propertyTypeAlias");
// no property = nothing to do
if (content.Properties.Contains(propertyTypeAlias) == false) return;
// get the config, no config = nothing to do
var autoFillConfig = GetConfig(propertyTypeAlias);
if (autoFillConfig == null) return; // nothing
// populate
Populate(content, autoFillConfig, filepath);
}
/// <summary>
/// Populates the auto-fill properties of a content item.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="propertyTypeAlias">The property type alias.</param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
/// <param name="filestream">The stream containing the file data.</param>
/// <param name="image">The file data as an image object.</param>
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream, Image image = null)
{
if (content == null) throw new ArgumentNullException("content");
if (propertyTypeAlias == null) throw new ArgumentNullException("propertyTypeAlias");
// no property = nothing to do
if (content.Properties.Contains(propertyTypeAlias) == false) return;
// get the config, no config = nothing to do
var autoFillConfig = GetConfig(propertyTypeAlias);
if (autoFillConfig == null) return; // nothing
// populate
Populate(content, autoFillConfig, filepath, filestream, image);
}
/// <summary>
/// Populates the auto-fill properties of a content item, for a specified auto-fill configuration.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="autoFillConfig">The auto-fill configuration.</param>
/// <param name="filepath">The filesystem path to the uploaded file.</param>
/// <remarks>The <paramref name="filepath"/> parameter is the path relative to the filesystem.</remarks>
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath)
{
if (content == null) throw new ArgumentNullException("content");
if (autoFillConfig == null) throw new ArgumentNullException("autoFillConfig");
// no file = reset, file = auto-fill
if (filepath.IsNullOrWhiteSpace())
{
ResetProperties(content, autoFillConfig);
}
else
{
// if anything goes wrong, just reset the properties
try
{
using (var filestream = _mediaFileSystem.OpenFile(filepath))
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
var size = _mediaFileSystem.IsImageFile(extension) ? (Size?) _mediaFileSystem.GetDimensions(filestream) : null;
SetProperties(content, autoFillConfig, size, filestream.Length, extension);
}
}
catch (Exception ex)
{
_logger.Error(typeof(UploadAutoFillProperties), "Could not populate upload auto-fill properties for file \""
+ filepath + "\".", ex);
ResetProperties(content, autoFillConfig);
}
}
}
/// <summary>
/// Populates the auto-fill properties of a content item.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="autoFillConfig"></param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
/// <param name="filestream">The stream containing the file data.</param>
/// <param name="image">The file data as an image object.</param>
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream, Image image = null)
{
if (content == null) throw new ArgumentNullException("content");
if (autoFillConfig == null) throw new ArgumentNullException("autoFillConfig");
// no file = reset, file = auto-fill
if (filepath.IsNullOrWhiteSpace() || filestream == null)
{
ResetProperties(content, autoFillConfig);
}
else
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
Size? size;
if (image == null)
size = _mediaFileSystem.IsImageFile(extension) ? (Size?) _mediaFileSystem.GetDimensions(filestream) : null;
else
size = new Size(image.Width, image.Height);
SetProperties(content, autoFillConfig, size, filestream.Length, extension);
}
}
private static void SetProperties(IContentBase content, IImagingAutoFillUploadField autoFillConfig, Size? size, long length, string extension)
{
if (content == null) throw new ArgumentNullException("content");
if (autoFillConfig == null) throw new ArgumentNullException("autoFillConfig");
if (content.Properties.Contains(autoFillConfig.WidthFieldAlias))
content.Properties[autoFillConfig.WidthFieldAlias].Value = size.HasValue ? size.Value.Width.ToInvariantString() : string.Empty;
if (content.Properties.Contains(autoFillConfig.HeightFieldAlias))
content.Properties[autoFillConfig.HeightFieldAlias].Value = size.HasValue ? size.Value.Height.ToInvariantString() : string.Empty;
if (content.Properties.Contains(autoFillConfig.LengthFieldAlias))
content.Properties[autoFillConfig.LengthFieldAlias].Value = length;
if (content.Properties.Contains(autoFillConfig.ExtensionFieldAlias))
content.Properties[autoFillConfig.ExtensionFieldAlias].Value = extension;
}
private static void ResetProperties(IContentBase content, IImagingAutoFillUploadField autoFillConfig)
{
if (content == null) throw new ArgumentNullException("content");
if (autoFillConfig == null) throw new ArgumentNullException("autoFillConfig");
if (content.Properties.Contains(autoFillConfig.WidthFieldAlias))
content.Properties[autoFillConfig.WidthFieldAlias].Value = string.Empty;
if (content.Properties.Contains(autoFillConfig.HeightFieldAlias))
content.Properties[autoFillConfig.HeightFieldAlias].Value = string.Empty;
if (content.Properties.Contains(autoFillConfig.LengthFieldAlias))
content.Properties[autoFillConfig.LengthFieldAlias].Value = string.Empty;
if (content.Properties.Contains(autoFillConfig.ExtensionFieldAlias))
content.Properties[autoFillConfig.ExtensionFieldAlias].Value = string.Empty;
}
}
}
+80 -128
View File
@@ -1,25 +1,15 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml;
using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Media;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Strings;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
namespace Umbraco.Core.Models
@@ -329,7 +319,7 @@ namespace Umbraco.Core.Models
{
if (property.Value is string)
{
var value = (string)property.Value;
var value = (string) property.Value;
property.Value = value.ToValidXmlString();
}
}
@@ -444,154 +434,116 @@ namespace Umbraco.Core.Models
}
}
public static IContentTypeComposition GetContentType(this IContentBase contentBase)
{
if (contentBase == null) throw new ArgumentNullException("contentBase");
var content = contentBase as IContent;
if (content != null) return content.ContentType;
var media = contentBase as IMedia;
if (media != null) return media.ContentType;
var member = contentBase as IMember;
if (member != null) return member.ContentType;
throw new NotSupportedException("Unsupported IContentBase implementation: " + contentBase.GetType().FullName + ".");
}
#region SetValue for setting file contents
/// <summary>
/// Sets and uploads the file from a HttpPostedFileBase object as the property value
/// Stores and sets an uploaded HttpPostedFileBase as a property value.
/// </summary>
/// <param name="content"><see cref="IContentBase"/> to add property value to</param>
/// <param name="propertyTypeAlias">Alias of the property to save the value on</param>
/// <param name="value">The <see cref="HttpPostedFileBase"/> containing the file that will be uploaded</param>
/// <param name="content"><see cref="IContentBase"/>A content item.</param>
/// <param name="propertyTypeAlias">The property alias.</param>
/// <param name="value">The uploaded <see cref="HttpPostedFileBase"/>.</param>
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value)
{
// Ensure we get the filename without the path in IE in intranet mode
// ensure we get the filename without the path in IE in intranet mode
// http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie
var fileName = value.FileName;
if (fileName.LastIndexOf(@"\") > 0)
fileName = fileName.Substring(fileName.LastIndexOf(@"\") + 1);
var filename = value.FileName;
var pos = filename.LastIndexOf(@"\", StringComparison.InvariantCulture);
if (pos > 0)
filename = filename.Substring(pos + 1);
var name =
IOHelper.SafeFileName(
fileName.Substring(fileName.LastIndexOf(IOHelper.DirSepChar) + 1,
fileName.Length - fileName.LastIndexOf(IOHelper.DirSepChar) - 1)
.ToLower());
// strip any directory info
pos = filename.LastIndexOf(IOHelper.DirSepChar);
if (pos > 0)
filename = filename.Substring(pos + 1);
if (string.IsNullOrEmpty(name) == false)
SetFileOnContent(content, propertyTypeAlias, name, value.InputStream);
// get a safe filename - should this be done by MediaHelper?
filename = IOHelper.SafeFileName(filename);
if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower(); // fixme - er... why?
FileSystemProviderManager.Current.MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, value.InputStream);
}
/// <summary>
/// Sets and uploads the file from a HttpPostedFile object as the property value
/// Stores and sets an uploaded HttpPostedFile as a property value.
/// </summary>
/// <param name="content"><see cref="IContentBase"/> to add property value to</param>
/// <param name="propertyTypeAlias">Alias of the property to save the value on</param>
/// <param name="value">The <see cref="HttpPostedFile"/> containing the file that will be uploaded</param>
/// <param name="content"><see cref="IContentBase"/>A content item.</param>
/// <param name="propertyTypeAlias">The property alias.</param>
/// <param name="value">The uploaded <see cref="HttpPostedFile"/>.</param>
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFile value)
{
SetValue(content, propertyTypeAlias, (HttpPostedFileBase)new HttpPostedFileWrapper(value));
SetValue(content, propertyTypeAlias, (HttpPostedFileBase) new HttpPostedFileWrapper(value));
}
/// <summary>
/// Sets and uploads the file from a HttpPostedFileWrapper object as the property value
/// Stores and sets an uploaded HttpPostedFileWrapper as a property value.
/// </summary>
/// <param name="content"><see cref="IContentBase"/> to add property value to</param>
/// <param name="propertyTypeAlias">Alias of the property to save the value on</param>
/// <param name="value">The <see cref="HttpPostedFileWrapper"/> containing the file that will be uploaded</param>
/// <param name="content"><see cref="IContentBase"/>A content item.</param>
/// <param name="propertyTypeAlias">The property alias.</param>
/// <param name="value">The uploaded <see cref="HttpPostedFileWrapper"/>.</param>
[Obsolete("There is no reason for this overload since HttpPostedFileWrapper inherits from HttpPostedFileBase")]
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileWrapper value)
{
SetValue(content, propertyTypeAlias, (HttpPostedFileBase)value);
SetValue(content, propertyTypeAlias, (HttpPostedFileBase) value);
}
/// <summary>
/// Sets and uploads the file from a <see cref="Stream"/> as the property value
/// Stores and sets a file as a property value.
/// </summary>
/// <param name="content"><see cref="IContentBase"/> to add property value to</param>
/// <param name="propertyTypeAlias">Alias of the property to save the value on</param>
/// <param name="fileName">Name of the file</param>
/// <param name="fileStream"><see cref="Stream"/> to save to disk</param>
public static void SetValue(this IContentBase content, string propertyTypeAlias, string fileName, Stream fileStream)
/// <param name="content"><see cref="IContentBase"/>A content item.</param>
/// <param name="propertyTypeAlias">The property alias.</param>
/// <param name="filename">The name of the file.</param>
/// <param name="filestream">A stream containing the file data.</param>
/// <remarks>This really is for FileUpload fields only, and should be obsoleted. For anything else,
/// you need to store the file by yourself using Store and then figure out
/// how to deal with auto-fill properties (if any) and thumbnails (if any) by yourself.</remarks>
public static void SetValue(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream)
{
var name = IOHelper.SafeFileName(fileName);
if (filename == null || filestream == null) return;
if (string.IsNullOrEmpty(name) == false && fileStream != null)
SetFileOnContent(content, propertyTypeAlias, name, fileStream);
// get a safe filename - should this be done by MediaHelper?
filename = IOHelper.SafeFileName(filename);
if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower(); // fixme - er... why?
FileSystemProviderManager.Current.MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream);
}
private static void SetFileOnContent(IContentBase content, string propertyTypeAlias, string filename, Stream fileStream)
/// <summary>
/// Stores a file.
/// </summary>
/// <param name="content"><see cref="IContentBase"/>A content item.</param>
/// <param name="propertyTypeAlias">The property alias.</param>
/// <param name="filename">The name of the file.</param>
/// <param name="filestream">A stream containing the file data.</param>
/// <param name="filepath">The original file path, if any.</param>
/// <returns>The path to the file, relative to the media filesystem.</returns>
/// <remarks>
/// <para>Does NOT set the property value, so one should probably store the file and then do
/// something alike: property.Value = MediaHelper.FileSystem.GetUrl(filepath).</para>
/// <para>The original file path is used, in the old media file path scheme, to try and reuse
/// the "folder number" that was assigned to the previous file referenced by the property,
/// if any.</para>
/// </remarks>
public static string StoreFile(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string filepath)
{
var property = content.Properties.FirstOrDefault(x => x.Alias == propertyTypeAlias);
if (property == null)
return;
//TODO: ALl of this naming logic needs to be put into the ImageHelper and then we need to change FileUploadPropertyValueEditor to do the same!
var numberedFolder = MediaSubfolderCounter.Current.Increment();
var fileName = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
? Path.Combine(numberedFolder.ToString(CultureInfo.InvariantCulture), filename)
: numberedFolder + "-" + filename;
var extension = Path.GetExtension(filename).Substring(1).ToLowerInvariant();
//the file size is the length of the stream in bytes
var fileSize = fileStream.Length;
var fs = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
fs.AddFile(fileName, fileStream);
//Check if file supports resizing and create thumbnails
var supportsResizing = UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes.InvariantContains(extension);
//the config section used to auto-fill properties
IImagingAutoFillUploadField uploadFieldConfigNode = null;
//Check for auto fill of additional properties
if (UmbracoConfig.For.UmbracoSettings().Content.ImageAutoFillProperties != null)
{
uploadFieldConfigNode = UmbracoConfig.For.UmbracoSettings().Content.ImageAutoFillProperties
.FirstOrDefault(x => x.Alias == propertyTypeAlias);
}
if (supportsResizing)
{
//get the original image from the original stream
if (fileStream.CanSeek) fileStream.Seek(0, 0);
using (var originalImage = Image.FromStream(fileStream))
{
var additionalSizes = new List<int>();
//Look up Prevalues for this upload datatype - if it is an upload datatype - get additional configured sizes
if (property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.UploadFieldAlias)
{
//Get Prevalues by the DataType's Id: property.PropertyType.DataTypeId
var values = ApplicationContext.Current.Services.DataTypeService.GetPreValuesByDataTypeId(property.PropertyType.DataTypeDefinitionId);
var thumbnailSizes = values.FirstOrDefault();
//Additional thumbnails configured as prevalues on the DataType
if (thumbnailSizes != null)
{
foreach (var thumb in thumbnailSizes.Split(new[] { ";", "," }, StringSplitOptions.RemoveEmptyEntries))
{
int thumbSize;
if (thumb != "" && int.TryParse(thumb, out thumbSize))
{
additionalSizes.Add(thumbSize);
}
}
}
}
ImageHelper.GenerateMediaThumbnails(fs, fileName, extension, originalImage, additionalSizes);
//while the image is still open, we'll check if we need to auto-populate the image properties
if (uploadFieldConfigNode != null)
{
content.SetValue(uploadFieldConfigNode.WidthFieldAlias, originalImage.Width.ToString(CultureInfo.InvariantCulture));
content.SetValue(uploadFieldConfigNode.HeightFieldAlias, originalImage.Height.ToString(CultureInfo.InvariantCulture));
}
}
}
//if auto-fill is true, then fill the remaining, non-image properties
if (uploadFieldConfigNode != null)
{
content.SetValue(uploadFieldConfigNode.LengthFieldAlias, fileSize.ToString(CultureInfo.InvariantCulture));
content.SetValue(uploadFieldConfigNode.ExtensionFieldAlias, extension);
}
//Set the value of the property to that of the uploaded file's url
property.Value = fs.GetUrl(fileName);
var propertyType = content.GetContentType()
.CompositionPropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (propertyType == null) throw new ArgumentException("Invalid property type alias " + propertyTypeAlias + ".");
return FileSystemProviderManager.Current.MediaFileSystem.StoreFile(content, propertyType, filename, filestream, filepath);
}
#endregion
+1 -1
View File
@@ -326,7 +326,7 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// <summary>
/// A boolean flag indicating if a property type has been removed from this instance.
/// </summary>
/// <remarks>
@@ -16,6 +16,11 @@ namespace Umbraco.Core.Models.Editors
/// </remarks>
public class ContentPropertyData
{
public ContentPropertyData(object value, PreValueCollection preValues)
: this(value, preValues, new Dictionary<string, object>())
{
}
public ContentPropertyData(object value, PreValueCollection preValues, IDictionary<string, object> additionalData)
{
Value = value;
@@ -28,6 +33,9 @@ namespace Umbraco.Core.Models.Editors
/// </summary>
public object Value { get; private set; }
/// <summary>
/// The pre-value collection for the content property
/// </summary>
public PreValueCollection PreValues { get; private set; }
/// <summary>
+6 -3
View File
@@ -113,8 +113,10 @@ namespace Umbraco.Core.Models.EntityBase
/// </summary>
internal virtual void AddingEntity()
{
CreateDate = DateTime.Now;
UpdateDate = DateTime.Now;
if (IsPropertyDirty("CreateDate") == false || _createDate == default(DateTime))
CreateDate = DateTime.Now;
if (IsPropertyDirty("UpdateDate") == false || _updateDate == default(DateTime))
UpdateDate = CreateDate;
}
/// <summary>
@@ -122,7 +124,8 @@ namespace Umbraco.Core.Models.EntityBase
/// </summary>
internal virtual void UpdatingEntity()
{
UpdateDate = DateTime.Now;
if (IsPropertyDirty("UpdateDate") == false || _updateDate == default(DateTime))
UpdateDate = DateTime.Now;
}
/// <summary>
@@ -1,3 +1,4 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
@@ -11,6 +12,9 @@ namespace Umbraco.Core.Models
[DataMember]
int Id { get; set; }
[DataMember]
Guid Key { get; set; }
/// <summary>
/// Gets or sets the Alias of the Property
/// </summary>
+7
View File
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Models
{
public interface IXsltFile : IFile
{
}
}
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Models.Identity
Culture = Configuration.GlobalSettings.DefaultUILanguage;
}
public virtual async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeUserManager manager)
public virtual async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeUserManager<BackOfficeIdentityUser> manager)
{
// NOTE the authenticationType must match the umbraco one
// defined in CookieAuthenticationOptions.AuthenticationType
+4 -5
View File
@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using Umbraco.Core.IO;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Strings;
@@ -27,11 +24,12 @@ namespace Umbraco.Core.Models
_addedProperties = new List<string>();
_removedProperties = new List<string>();
}
/// <summary>
/// Creates an item with pre-filled properties
/// </summary>
/// <param name="id"></param>
/// <param name="key"></param>
/// <param name="useInEditor"></param>
/// <param name="cacheDuration"></param>
/// <param name="alias"></param>
@@ -43,10 +41,11 @@ namespace Umbraco.Core.Models
/// <param name="cacheByMember"></param>
/// <param name="dontRender"></param>
/// <param name="scriptPath"></param>
public Macro(int id, bool useInEditor, int cacheDuration, string @alias, string name, string controlType, string controlAssembly, string xsltPath, bool cacheByPage, bool cacheByMember, bool dontRender, string scriptPath)
public Macro(int id, Guid key, bool useInEditor, int cacheDuration, string @alias, string name, string controlType, string controlAssembly, string xsltPath, bool cacheByPage, bool cacheByMember, bool dontRender, string scriptPath)
: this()
{
Id = id;
Key = key;
UseInEditor = useInEditor;
CacheDuration = cacheDuration;
Alias = alias.ToCleanString(CleanStringType.Alias);
+17 -2
View File
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Models
{
public MacroProperty()
{
_key = Guid.NewGuid();
}
/// <summary>
@@ -30,6 +30,7 @@ namespace Umbraco.Core.Models
_alias = alias;
_name = name;
_sortOrder = sortOrder;
_key = Guid.NewGuid();
//try to get the new mapped parameter editor
var mapped = LegacyParameterEditorAliasConverter.GetNewAliasFromLegacyAlias(editorAlias, false);
@@ -45,16 +46,18 @@ namespace Umbraco.Core.Models
/// Ctor for creating an existing property
/// </summary>
/// <param name="id"></param>
/// <param name="key"></param>
/// <param name="alias"></param>
/// <param name="name"></param>
/// <param name="sortOrder"></param>
/// <param name="editorAlias"></param>
internal MacroProperty(int id, string @alias, string name, int sortOrder, string editorAlias)
internal MacroProperty(int id, Guid key, string @alias, string name, int sortOrder, string editorAlias)
{
_id = id;
_alias = alias;
_name = name;
_sortOrder = sortOrder;
_key = key;
//try to get the new mapped parameter editor
var mapped = LegacyParameterEditorAliasConverter.GetNewAliasFromLegacyAlias(editorAlias, false);
@@ -66,6 +69,7 @@ namespace Umbraco.Core.Models
_editorAlias = editorAlias;
}
private Guid _key;
private string _alias;
private string _name;
private int _sortOrder;
@@ -76,6 +80,7 @@ namespace Umbraco.Core.Models
private class PropertySelectors
{
public readonly PropertyInfo KeySelector = ExpressionHelper.GetPropertyInfo<MacroProperty, Guid>(x => x.Key);
public readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.Alias);
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.Name);
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, int>(x => x.SortOrder);
@@ -83,6 +88,16 @@ namespace Umbraco.Core.Models
public readonly PropertyInfo PropertyTypeSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.EditorAlias);
}
/// <summary>
/// Gets or sets the Key of the Property
/// </summary>
[DataMember]
public Guid Key
{
get { return _key; }
set { SetPropertyValueAndDetectChanges(value, ref _key, Ps.Value.KeySelector); }
}
/// <summary>
/// Gets or sets the Alias of the Property
/// </summary>
+33 -51
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -9,73 +8,56 @@ using Umbraco.Core.PropertyEditors.ValueConverters;
namespace Umbraco.Core.Models
{
internal static class MediaExtensions
public static class MediaExtensions
{
/// <summary>
/// Hack: we need to put this in a real place, this is currently just used to render the urls for a media item in the back office
/// Gets the url of a media item.
/// </summary>
/// <returns></returns>
public static string GetUrl(this IMedia media, string propertyAlias, ILogger logger)
{
var propertyType = media.PropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyAlias));
if (propertyType != null)
if (propertyType == null) return string.Empty;
var val = media.Properties[propertyType];
if (val == null) return string.Empty;
var jsonString = val.Value as string;
if (jsonString == null) return string.Empty;
if (propertyType.PropertyEditorAlias == Constants.PropertyEditors.UploadFieldAlias)
return jsonString;
if (propertyType.PropertyEditorAlias == Constants.PropertyEditors.ImageCropperAlias)
{
var val = media.Properties[propertyType];
if (val != null)
if (jsonString.DetectIsJson() == false)
return jsonString;
try
{
var jsonString = val.Value as string;
if (jsonString != null)
{
if (propertyType.PropertyEditorAlias == Constants.PropertyEditors.ImageCropperAlias)
{
if (jsonString.DetectIsJson())
{
try
{
var json = JsonConvert.DeserializeObject<JObject>(jsonString);
if (json["src"] != null)
{
return json["src"].Value<string>();
}
}
catch (Exception ex)
{
logger.Error<ImageCropperValueConverter>("Could not parse the string " + jsonString + " to a json object", ex);
return string.Empty;
}
}
else
{
return jsonString;
}
}
else if (propertyType.PropertyEditorAlias == Constants.PropertyEditors.UploadFieldAlias)
{
return jsonString;
}
//hrm, without knowing what it is, just adding a string here might not be very nice
}
var json = JsonConvert.DeserializeObject<JObject>(jsonString);
if (json["src"] != null)
return json["src"].Value<string>();
}
catch (Exception ex)
{
logger.Error<ImageCropperValueConverter>("Could not parse the string " + jsonString + " to a json object", ex);
return string.Empty;
}
}
// hrm, without knowing what it is, just adding a string here might not be very nice
return string.Empty;
}
/// <summary>
/// Hack: we need to put this in a real place, this is currently just used to render the urls for a media item in the back office
/// Gets the urls of a media item.
/// </summary>
/// <returns></returns>
public static string[] GetUrls(this IMedia media, IContentSection contentSection, ILogger logger)
{
var links = new List<string>();
var autoFillProperties = contentSection.ImageAutoFillProperties.ToArray();
if (autoFillProperties.Any())
{
links.AddRange(
autoFillProperties
.Select(field => media.GetUrl(field.Alias, logger))
.Where(link => link.IsNullOrWhiteSpace() == false));
}
return links.ToArray();
return contentSection.ImageAutoFillProperties
.Select(field => media.GetUrl(field.Alias, logger))
.Where(link => string.IsNullOrWhiteSpace(link) == false)
.ToArray();
}
}
}
+1 -1
View File
@@ -135,7 +135,7 @@ namespace Umbraco.Core.Models
private static void ThrowTypeException(object value, Type expected, string alias)
{
throw new Exception(string.Format("Value \"{0}\" of type \"{1}\" could not be converted"
throw new InvalidOperationException(string.Format("Value \"{0}\" of type \"{1}\" could not be converted"
+ " to type \"{2}\" which is expected by property type \"{3}\".",
value, value.GetType(), expected, alias));
}
+4 -7
View File
@@ -25,7 +25,7 @@ namespace Umbraco.Core.Models
NoAccessNodeId = noAccessNode.Id;
_protectedNodeId = protectedNode.Id;
_ruleCollection = new ObservableCollection<PublicAccessRule>(ruleCollection);
_ruleCollection = new ObservableCollection<PublicAccessRule>(ruleCollection);
_ruleCollection.CollectionChanged += _ruleCollection_CollectionChanged;
}
@@ -81,7 +81,7 @@ namespace Umbraco.Core.Models
internal IEnumerable<Guid> RemovedRules
{
get { return _removedRules; }
}
}
public IEnumerable<PublicAccessRule> Rules
{
@@ -107,10 +107,7 @@ namespace Umbraco.Core.Models
public void ClearRules()
{
foreach (var rule in _ruleCollection)
{
RemoveRule(rule);
}
_ruleCollection.Clear();
}
[DataMember]
@@ -126,7 +123,7 @@ namespace Umbraco.Core.Models
get { return _noAccessNodeId; }
set { SetPropertyValueAndDetectChanges(value, ref _noAccessNodeId, Ps.Value.NoAccessNodeIdSelector); }
}
[DataMember]
public int ProtectedNodeId
{
+29
View File
@@ -0,0 +1,29 @@
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("umbracoLock")]
[PrimaryKey("id")]
[ExplicitColumns]
internal class LockDto
{
public LockDto()
{
Value = 1;
}
[Column("id")]
[PrimaryKeyColumn(Name = "PK_umbracoLock")]
public int Id { get; set; }
[Column("value")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int Value { get; set; }
[Column("name")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Length(64)]
public string Name { get; set; }
}
}
+6 -1
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
@@ -13,6 +14,10 @@ namespace Umbraco.Core.Models.Rdbms
[PrimaryKeyColumn]
public int Id { get; set; }
[Column("uniqueId")]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsMacro_UniqueId")]
public Guid UniqueId { get; set; }
[Column("macroUseInEditor")]
[Constraint(Default = "0")]
public bool UseInEditor { get; set; }
@@ -1,4 +1,5 @@
using Umbraco.Core.Persistence;
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
@@ -11,7 +12,12 @@ namespace Umbraco.Core.Models.Rdbms
[Column("id")]
[PrimaryKeyColumn]
public int Id { get; set; }
// important to use column name != cmsMacro.uniqueId (fix in v8)
[Column("uniquePropertyId")]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsMacroProperty_UniquePropertyId")]
public Guid UniqueId { get; set; }
[Column("editorAlias")]
public string EditorAlias { get; set; }
@@ -11,7 +11,6 @@ namespace Umbraco.Core.Models.Rdbms
{
[Column("id")]
[PrimaryKeyColumn]
[Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyData")]
public int Id { get; set; }
[Column("contentNodeId")]
@@ -5,7 +5,7 @@ using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("umbracoRedirectUrl")]
[PrimaryKey("id")]
[PrimaryKey("id", autoIncrement = false)]
[ExplicitColumns]
class RedirectUrlDto
{
@@ -22,8 +22,8 @@ namespace Umbraco.Core.Models.Rdbms
// inserts, and much faster on reads, so... we have an index on a hash.
[Column("id")]
[PrimaryKeyColumn(IdentitySeed = 1, Name = "PK_umbracoRedirectUrl")]
public int Id { get; set; }
[PrimaryKeyColumn(Name = "PK_umbracoRedirectUrl", AutoIncrement = false)]
public Guid Id { get; set; }
[ResultColumn]
public int ContentId { get; set; }
@@ -39,12 +39,12 @@ namespace Umbraco.Core.Models.Rdbms
[Column("url")]
[NullSetting(NullSetting = NullSettings.NotNull)]
//[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoRedirectUrl", ForColumns = "url, createDateUtc")]
public string Url { get; set; }
[Column("urlHash")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoRedirectUrl", ForColumns = "urlHash, contentKey, createDateUtc")]
[Length(40)]
public string UrlHash { get; set; }
}
}
@@ -1,43 +0,0 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("umbracoDeployChecksum")]
[PrimaryKey("id")]
[ExplicitColumns]
internal class UmbracoDeployChecksumDto
{
[Column("id")]
[PrimaryKeyColumn(Name = "PK_umbracoDeployChecksum")]
public int Id { get; set; }
[Column("entityType")]
[Length(32)]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoDeployChecksum", ForColumns = "entityType,entityGuid,entityPath")]
public string EntityType { get; set; }
[Column("entityGuid")]
[NullSetting(NullSetting = NullSettings.Null)]
public Guid EntityGuid { get; set; }
[Column("entityPath")]
[Length(256)]
[NullSetting(NullSetting = NullSettings.Null)]
public string EntityPath { get; set; }
[Column("localChecksum")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Length(32)]
public string LocalChecksum { get; set; }
[Column("compositeChecksum")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(32)]
public string CompositeChecksum { get; set; }
}
}
@@ -1,26 +0,0 @@
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("umbracoDeployDependency")]
[ExplicitColumns]
internal class UmbracoDeployDependencyDto
{
[Column("sourceId")]
[PrimaryKeyColumn(AutoIncrement = false, Clustered = true, Name = "PK_umbracoDeployDependency", OnColumns = "sourceId, targetId")]
[ForeignKey(typeof(UmbracoDeployChecksumDto), Name = "FK_umbracoDeployDependency_umbracoDeployChecksum_id1")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int SourceId { get; set; }
[Column("targetId")]
[ForeignKey(typeof(UmbracoDeployChecksumDto), Name = "FK_umbracoDeployDependency_umbracoDeployChecksum_id2")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int TargetId { get; set; }
[Column("mode")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int Mode { get; set; }
}
}
+1 -1
View File
@@ -15,7 +15,7 @@ using Umbraco.Core.Strings;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a Template file
/// Represents a Template file.
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
+51
View File
@@ -0,0 +1,51 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a Template file that can have its content on disk.
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class TemplateOnDisk : Template
{
/// <summary>
/// Initializes a new instance of the <see cref="TemplateOnDisk"/> class.
/// </summary>
/// <param name="name">The name of the template.</param>
/// <param name="alias">The alias of the template.</param>
public TemplateOnDisk(string name, string alias)
: base(name, alias)
{
IsOnDisk = true;
}
/// <summary>
/// Gets or sets a value indicating whether the content is on disk already.
/// </summary>
public bool IsOnDisk { get; set; }
/// <summary>
/// Gets or sets the content.
/// </summary>
/// <remarks>
/// <para>Getting the content while the template is "on disk" throws,
/// the template must be saved before its content can be retrieved.</para>
/// <para>Setting the content means it is not "on disk" anymore, and the
/// template becomes (and behaves like) a normal template.</para>
/// </remarks>
public override string Content
{
get
{
return IsOnDisk ? string.Empty : base.Content;
}
set
{
base.Content = value;
IsOnDisk = false;
}
}
}
}
+14 -3
View File
@@ -1,8 +1,5 @@
using System;
using System.Globalization;
using System.Linq;
using System.Threading;
using Umbraco.Core.Models.Identity;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
@@ -83,5 +80,19 @@ namespace Umbraco.Core.Models
if (media == null) throw new ArgumentNullException("media");
return HasPathAccess(media.Path, user.StartMediaId, Constants.System.RecycleBinMedia);
}
/// <summary>
/// Determines whether this user is an admin.
/// </summary>
/// <param name="user"></param>
/// <returns>
/// <c>true</c> if this user is admin; otherwise, <c>false</c>.
/// </returns>
public static bool IsAdmin(this IUser user)
{
if (user == null) throw new ArgumentNullException("user");
return user.UserType.Alias == "admin";
}
}
}
+32
View File
@@ -0,0 +1,32 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a XSLT file
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class XsltFile : File, IXsltFile
{
public XsltFile(string path)
: this(path, (Func<File, string>) null)
{ }
internal XsltFile(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; }
}
}
}
@@ -7,15 +7,20 @@ using umbraco.interfaces;
namespace Umbraco.Core.ObjectResolution
{
/// <summary>
/// <summary>
/// A resolver to return all IApplicationEvents objects
/// </summary>
/// <remarks>
/// This is disposable because after the app has started it should be disposed to release any memory being occupied by instances.
/// <para>This is disposable because after the app has started it should be disposed to release any memory being occupied by instances.</para>
/// <para>Ordering handlers: handlers are ordered by (ascending) weight. By default, handlers from the Umbraco.* or Concorde.*
/// assemblies have a -100 weight whereas any other handler has a weight of +100. A custom weight can be assigned to a handler
/// by marking the class with the WeightAttribute. For example, the CacheRefresherEventHandler is marked with [Weight(int.MinValue)]
/// because its events need to run before anything else. Positive weights are considered "user-space" while negative weights are
/// "core". Finally, users can register a filter to process the list (after it has been ordered) and re-order it, or remove handlers.</para>
/// <para>BEWARE! handlers order is an important thing, and removing handlers or reordering handlers can have unexpected consequences.</para>
/// </remarks>
internal sealed class ApplicationEventsResolver : ManyObjectsResolverBase<ApplicationEventsResolver, IApplicationEventHandler>, IDisposable
public sealed class ApplicationEventsResolver : ManyObjectsResolverBase<ApplicationEventsResolver, IApplicationEventHandler>, IDisposable
{
private readonly LegacyStartupHandlerResolver _legacyResolver;
/// <summary>
@@ -23,18 +28,18 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <param name="logger"></param>
/// <param name="applicationEventHandlers"></param>
/// <param name="serviceProvider"></param>
/// <param name="serviceProvider"></param>
internal ApplicationEventsResolver(IServiceProvider serviceProvider, ILogger logger, IEnumerable<Type> applicationEventHandlers)
: base(serviceProvider, logger, applicationEventHandlers)
{
{
//create the legacy resolver and only include the legacy types
_legacyResolver = new LegacyStartupHandlerResolver(
_legacyResolver = new LegacyStartupHandlerResolver(
serviceProvider, logger,
applicationEventHandlers.Where(x => !TypeHelper.IsTypeAssignableFrom<IApplicationEventHandler>(x)));
applicationEventHandlers.Where(x => TypeHelper.IsTypeAssignableFrom<IApplicationEventHandler>(x) == false));
}
/// <summary>
/// Override in order to only return types of IApplicationEventHandler and above,
/// Override in order to only return types of IApplicationEventHandler and above,
/// do not include the legacy types of IApplicationStartupHandler
/// </summary>
protected override IEnumerable<Type> InstanceTypes
@@ -42,14 +47,60 @@ namespace Umbraco.Core.ObjectResolution
get { return base.InstanceTypes.Where(TypeHelper.IsTypeAssignableFrom<IApplicationEventHandler>); }
}
/// <summary>
/// Gets the <see cref="IApplicationEventHandler"/> implementations.
/// </summary>
public IEnumerable<IApplicationEventHandler> ApplicationEventHandlers
private List<IApplicationEventHandler> _orderedAndFiltered;
/// <summary>
/// Gets the <see cref="IApplicationEventHandler"/> implementations.
/// </summary>
public IEnumerable<IApplicationEventHandler> ApplicationEventHandlers
{
get { return Values; }
get
{
if (_orderedAndFiltered == null)
{
_orderedAndFiltered = GetSortedValues().ToList();
if (FilterCollection != null)
FilterCollection(_orderedAndFiltered);
}
return _orderedAndFiltered;
}
}
/// <summary>
/// Gets or sets a delegate to filter the event handler list (EXPERT!).
/// </summary>
/// <remarks>
/// <para>This can be set on startup in the pre-boot process in either a custom boot manager or global.asax (UmbracoApplication).</para>
/// <para>Allows custom logic to execute in order to filter and/or re-order the event handlers prior to executing.</para>
/// <para>To be used by custom boot sequences where the boot loader needs to remove some handlers, or raise their priority.</para>
/// <para>Filtering the event handler collection can have ugly consequences. Use with care.</para>
/// </remarks>
public Action<IList<IApplicationEventHandler>> FilterCollection
{
get { return _filterCollection; }
set
{
if (_orderedAndFiltered != null)
throw new InvalidOperationException("Cannot set the FilterCollection delegate once the ApplicationEventHandlers are resolved");
if (_filterCollection != null)
throw new InvalidOperationException("Cannot set the FilterCollection delegate once it's already been specified");
_filterCollection = value;
}
}
protected override int GetObjectWeight(object o)
{
var type = o.GetType();
var attr = type.GetCustomAttribute<WeightAttribute>(true);
if (attr != null) return attr.Weight;
var name = type.Assembly.FullName;
// we should really attribute all our Core handlers, so this is temp
var core = name.InvariantStartsWith("Umbraco.") || name.InvariantStartsWith("Concorde.");
return core ? -DefaultPluginWeight : DefaultPluginWeight;
}
/// <summary>
/// Create instances of all of the legacy startup handlers
/// </summary>
@@ -62,11 +113,11 @@ namespace Umbraco.Core.ObjectResolution
protected override bool SupportsClear
{
get { return false; }
}
}
protected override bool SupportsInsert
{
get { return false; }
get { return false; }
}
private class LegacyStartupHandlerResolver : ManyObjectsResolverBase<ApplicationEventsResolver, IApplicationStartupHandler>, IDisposable
@@ -90,8 +141,9 @@ namespace Umbraco.Core.ObjectResolution
private bool _disposed;
private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim();
private Action<IList<IApplicationEventHandler>> _filterCollection;
/// <summary>
/// <summary>
/// Gets a value indicating whether this instance is disposed.
/// </summary>
/// <value>
@@ -146,7 +198,8 @@ namespace Umbraco.Core.ObjectResolution
{
_legacyResolver.Dispose();
ResetCollections();
_orderedAndFiltered.Clear();
_orderedAndFiltered = null;
}
}
}
}
@@ -17,7 +17,7 @@ namespace Umbraco.Core.ObjectResolution
/// for when there is some processing overhead (i.e. Type finding in assemblies) to return the Types used to instantiate the instances.
/// In some these cases we don't want to have to type-find during application startup, only when we need to resolve the instances.</para>
/// <para>Important notes about this resolver: it does not support Insert or Remove and therefore does not support any ordering unless
/// the types are marked with the WeightedPluginAttribute.</para>
/// the types are marked with the WeightAttribute.</para>
/// </remarks>
public abstract class LazyManyObjectsResolverBase<TResolver, TResolved> : ManyObjectsResolverBase<TResolver, TResolved>
where TResolved : class
@@ -14,18 +14,18 @@ namespace Umbraco.Core.ObjectResolution
/// <typeparam name="TResolver">The type of the concrete resolver class.</typeparam>
/// <typeparam name="TResolved">The type of the resolved objects.</typeparam>
public abstract class ManyObjectsResolverBase<TResolver, TResolved> : ResolverBase<TResolver>
where TResolved : class
where TResolved : class
where TResolver : ResolverBase
{
private Lazy<IEnumerable<TResolved>> _applicationInstances;
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private readonly string _httpContextKey;
private readonly List<Type> _instanceTypes = new List<Type>();
private IEnumerable<TResolved> _sortedValues;
{
private Lazy<IEnumerable<TResolved>> _applicationInstances;
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private readonly string _httpContextKey;
private readonly List<Type> _instanceTypes = new List<Type>();
private IEnumerable<TResolved> _sortedValues;
private int _defaultPluginWeight = 10;
private int _defaultPluginWeight = 100;
#region Constructors
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an empty list of objects,
@@ -61,11 +61,11 @@ namespace Umbraco.Core.ObjectResolution
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use ctor specifying IServiceProvider instead")]
protected ManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
protected ManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, scope)
{
}
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an empty list of objects,
@@ -76,19 +76,19 @@ namespace Umbraco.Core.ObjectResolution
/// <param name="httpContext">The HttpContextBase corresponding to the HttpRequest.</param>
/// <exception cref="ArgumentNullException"><paramref name="httpContext"/> is <c>null</c>.</exception>
protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, HttpContextBase httpContext)
{
{
if (serviceProvider == null) throw new ArgumentNullException("serviceProvider");
if (httpContext == null) throw new ArgumentNullException("httpContext");
CanResolveBeforeFrozen = false;
Logger = logger;
LifetimeScope = ObjectLifetimeScope.HttpRequest;
_httpContextKey = GetType().FullName;
LifetimeScope = ObjectLifetimeScope.HttpRequest;
_httpContextKey = GetType().FullName;
ServiceProvider = serviceProvider;
CurrentHttpContext = httpContext;
_instanceTypes = new List<Type>();
_instanceTypes = new List<Type>();
InitializeAppInstances();
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use ctor specifying IServiceProvider instead")]
@@ -110,57 +110,57 @@ namespace Umbraco.Core.ObjectResolution
/// <exception cref="InvalidOperationException"><paramref name="scope"/> is per HttpRequest but the current HttpContext is null.</exception>
protected ManyObjectsResolverBase(IServiceProvider serviceProvider, ILogger logger, IEnumerable<Type> value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(serviceProvider, logger, scope)
{
_instanceTypes = value.ToList();
}
{
_instanceTypes = value.ToList();
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use ctor specifying IServiceProvider instead")]
protected ManyObjectsResolverBase(IEnumerable<Type> value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, value, scope)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list of objects,
/// with creation of objects based on an HttpRequest lifetime scope.
/// </summary>
/// <param name="httpContext">The HttpContextBase corresponding to the HttpRequest.</param>
/// <param name="value">The list of object types.</param>
/// <exception cref="ArgumentNullException"><paramref name="httpContext"/> is <c>null</c>.</exception>
/// <summary>
/// Initializes a new instance of the <see cref="ManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list of objects,
/// with creation of objects based on an HttpRequest lifetime scope.
/// </summary>
/// <param name="httpContext">The HttpContextBase corresponding to the HttpRequest.</param>
/// <param name="value">The list of object types.</param>
/// <exception cref="ArgumentNullException"><paramref name="httpContext"/> is <c>null</c>.</exception>
[Obsolete("Use ctor specifying IServiceProvider instead")]
protected ManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Type> value)
: this(new ActivatorServiceProvider(), LoggerResolver.Current.Logger, httpContext)
{
_instanceTypes = value.ToList();
}
#endregion
{
_instanceTypes = value.ToList();
}
#endregion
private void InitializeAppInstances()
{
_applicationInstances = new Lazy<IEnumerable<TResolved>>(() => CreateInstances().ToArray());
}
/// <summary>
/// Gets or sets a value indicating whether the resolver can resolve objects before resolution is frozen.
/// </summary>
/// <remarks>This is false by default and is used for some special internal resolvers.</remarks>
internal bool CanResolveBeforeFrozen { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the resolver can resolve objects before resolution is frozen.
/// </summary>
/// <remarks>This is false by default and is used for some special internal resolvers.</remarks>
internal bool CanResolveBeforeFrozen { get; set; }
/// <summary>
/// Gets the list of types to create instances from.
/// </summary>
protected virtual IEnumerable<Type> InstanceTypes
{
get { return _instanceTypes; }
}
/// <summary>
/// Gets the list of types to create instances from.
/// </summary>
protected virtual IEnumerable<Type> InstanceTypes
{
get { return _instanceTypes; }
}
/// <summary>
/// Gets or sets the <see cref="HttpContextBase"/> used to initialize this object, if any.
/// </summary>
/// <remarks>If not null, then <c>LifetimeScope</c> will be <c>ObjectLifetimeScope.HttpRequest</c>.</remarks>
protected HttpContextBase CurrentHttpContext { get; private set; }
/// <summary>
/// Gets or sets the <see cref="HttpContextBase"/> used to initialize this object, if any.
/// </summary>
/// <remarks>If not null, then <c>LifetimeScope</c> will be <c>ObjectLifetimeScope.HttpRequest</c>.</remarks>
protected HttpContextBase CurrentHttpContext { get; private set; }
/// <summary>
/// Returns the service provider used to instantiate objects
@@ -174,16 +174,16 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
protected ObjectLifetimeScope LifetimeScope { get; private set; }
/// <summary>
/// Gets the resolved object instances, sorted by weight.
/// </summary>
/// <returns>The sorted resolved object instances.</returns>
/// <remarks>
/// <para>The order is based upon the <c>WeightedPluginAttribute</c> and <c>DefaultPluginWeight</c>.</para>
/// <para>Weights are sorted ascendingly (lowest weights come first).</para>
/// </remarks>
protected IEnumerable<TResolved> GetSortedValues()
{
/// <summary>
/// Gets the resolved object instances, sorted by weight.
/// </summary>
/// <returns>The sorted resolved object instances.</returns>
/// <remarks>
/// <para>The order is based upon the <c>WeightAttribute</c> and <c>DefaultPluginWeight</c>.</para>
/// <para>Weights are sorted ascendingly (lowest weights come first).</para>
/// </remarks>
protected IEnumerable<TResolved> GetSortedValues()
{
if (_sortedValues == null)
{
var values = Values.ToList();
@@ -191,18 +191,18 @@ namespace Umbraco.Core.ObjectResolution
_sortedValues = values;
}
return _sortedValues;
}
}
/// <summary>
/// Gets or sets the default type weight.
/// </summary>
/// <remarks>Determines the weight of types that do not have a <c>WeightedPluginAttribute</c> set on
/// them, when calling <c>GetSortedValues</c>.</remarks>
protected virtual int DefaultPluginWeight
{
get { return _defaultPluginWeight; }
set { _defaultPluginWeight = value; }
}
/// <summary>
/// Gets or sets the default type weight.
/// </summary>
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
/// them, when calling <c>GetSortedValues</c>.</remarks>
protected virtual int DefaultPluginWeight
{
get { return _defaultPluginWeight; }
set { _defaultPluginWeight = value; }
}
/// <summary>
/// Returns the weight of an object for user with GetSortedValues
@@ -210,22 +210,22 @@ namespace Umbraco.Core.ObjectResolution
/// <param name="o"></param>
/// <returns></returns>
protected virtual int GetObjectWeight(object o)
{
var type = o.GetType();
var attr = type.GetCustomAttribute<WeightedPluginAttribute>(true);
return attr == null ? DefaultPluginWeight : attr.Weight;
}
{
var type = o.GetType();
var attr = type.GetCustomAttribute<WeightAttribute>(true);
return attr == null ? DefaultPluginWeight : attr.Weight;
}
/// <summary>
/// Gets the resolved object instances.
/// </summary>
/// <exception cref="InvalidOperationException"><c>CanResolveBeforeFrozen</c> is false, and resolution is not frozen.</exception>
protected IEnumerable<TResolved> Values
{
get
{
using (Resolution.Reader(CanResolveBeforeFrozen))
{
/// <summary>
/// Gets the resolved object instances.
/// </summary>
/// <exception cref="InvalidOperationException"><c>CanResolveBeforeFrozen</c> is false, and resolution is not frozen.</exception>
protected IEnumerable<TResolved> Values
{
get
{
using (Resolution.Reader(CanResolveBeforeFrozen))
{
// note: we apply .ToArray() to the output of CreateInstance() because that is an IEnumerable that
// comes from the PluginManager we want to be _sure_ that it's not a Linq of some sort, but the
// instances have actually been instanciated when we return.
@@ -247,7 +247,7 @@ namespace Umbraco.Core.ObjectResolution
CurrentHttpContext.Items[_httpContextKey] = instances;
}
return (TResolved[])CurrentHttpContext.Items[_httpContextKey];
case ObjectLifetimeScope.Application:
return _applicationInstances.Value;
@@ -258,132 +258,132 @@ namespace Umbraco.Core.ObjectResolution
return CreateInstances().ToArray();
}
}
}
}
}
}
/// <summary>
/// Creates the object instances for the types contained in the types collection.
/// </summary>
/// <returns>A list of objects of type <typeparamref name="TResolved"/>.</returns>
protected virtual IEnumerable<TResolved> CreateInstances()
{
return ServiceProvider.CreateInstances<TResolved>(InstanceTypes, Logger);
}
/// <summary>
/// Creates the object instances for the types contained in the types collection.
/// </summary>
/// <returns>A list of objects of type <typeparamref name="TResolved"/>.</returns>
protected virtual IEnumerable<TResolved> CreateInstances()
{
return ServiceProvider.CreateInstances<TResolved>(InstanceTypes, Logger);
}
#region Types collection manipulation
#region Types collection manipulation
/// <summary>
/// Removes a type.
/// </summary>
/// <param name="value">The type to remove.</param>
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
/// the type is not a valid type for the resolver.</exception>
public virtual void RemoveType(Type value)
{
EnsureSupportsRemove();
/// <summary>
/// Removes a type.
/// </summary>
/// <param name="value">The type to remove.</param>
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
/// the type is not a valid type for the resolver.</exception>
public virtual void RemoveType(Type value)
{
EnsureSupportsRemove();
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(value);
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(value);
l.UpgradeToWriteLock();
_instanceTypes.Remove(value);
}
}
l.UpgradeToWriteLock();
_instanceTypes.Remove(value);
}
}
/// <summary>
/// Removes a type.
/// </summary>
/// <typeparam name="T">The type to remove.</typeparam>
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
/// the type is not a valid type for the resolver.</exception>
public void RemoveType<T>()
/// <summary>
/// Removes a type.
/// </summary>
/// <typeparam name="T">The type to remove.</typeparam>
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
/// the type is not a valid type for the resolver.</exception>
public void RemoveType<T>()
where T : TResolved
{
RemoveType(typeof(T));
}
{
RemoveType(typeof(T));
}
/// <summary>
/// Adds types.
/// </summary>
/// <param name="types">The types to add.</param>
/// <remarks>The types are appended at the end of the list.</remarks>
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// a type is not a valid type for the resolver, or a type is already in the collection of types.</exception>
protected void AddTypes(IEnumerable<Type> types)
{
EnsureSupportsAdd();
/// <summary>
/// Adds types.
/// </summary>
/// <param name="types">The types to add.</param>
/// <remarks>The types are appended at the end of the list.</remarks>
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// a type is not a valid type for the resolver, or a type is already in the collection of types.</exception>
protected void AddTypes(IEnumerable<Type> types)
{
EnsureSupportsAdd();
using (Resolution.Configuration)
using (new WriteLock(_lock))
{
foreach(var t in types)
{
EnsureCorrectType(t);
using (Resolution.Configuration)
using (new WriteLock(_lock))
{
foreach (var t in types)
{
EnsureCorrectType(t);
if (_instanceTypes.Contains(t))
{
throw new InvalidOperationException(string.Format(
"Type {0} is already in the collection of types.", t.FullName));
}
_instanceTypes.Add(t);
}
}
}
{
throw new InvalidOperationException(string.Format(
"Type {0} is already in the collection of types.", t.FullName));
}
_instanceTypes.Add(t);
}
}
}
/// <summary>
/// Adds a type.
/// </summary>
/// <param name="value">The type to add.</param>
/// <remarks>The type is appended at the end of the list.</remarks>
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
public virtual void AddType(Type value)
{
EnsureSupportsAdd();
/// <summary>
/// Adds a type.
/// </summary>
/// <param name="value">The type to add.</param>
/// <remarks>The type is appended at the end of the list.</remarks>
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
public virtual void AddType(Type value)
{
EnsureSupportsAdd();
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(value);
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(value);
if (_instanceTypes.Contains(value))
{
throw new InvalidOperationException(string.Format(
"Type {0} is already in the collection of types.", value.FullName));
}
{
throw new InvalidOperationException(string.Format(
"Type {0} is already in the collection of types.", value.FullName));
}
l.UpgradeToWriteLock();
_instanceTypes.Add(value);
}
}
l.UpgradeToWriteLock();
_instanceTypes.Add(value);
}
}
/// <summary>
/// Adds a type.
/// </summary>
/// <typeparam name="T">The type to add.</typeparam>
/// <remarks>The type is appended at the end of the list.</remarks>
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
public void AddType<T>()
/// <summary>
/// Adds a type.
/// </summary>
/// <typeparam name="T">The type to add.</typeparam>
/// <remarks>The type is appended at the end of the list.</remarks>
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
public void AddType<T>()
where T : TResolved
{
AddType(typeof(T));
}
{
AddType(typeof(T));
}
/// <summary>
/// Clears the list of types
/// </summary>
/// <exception cref="InvalidOperationException">the resolver does not support clearing types.</exception>
public virtual void Clear()
{
EnsureSupportsClear();
/// <summary>
/// Clears the list of types
/// </summary>
/// <exception cref="InvalidOperationException">the resolver does not support clearing types.</exception>
public virtual void Clear()
{
EnsureSupportsClear();
using (Resolution.Configuration)
using (new WriteLock(_lock))
{
_instanceTypes.Clear();
}
}
using (Resolution.Configuration)
using (new WriteLock(_lock))
{
_instanceTypes.Clear();
}
}
/// <summary>
/// WARNING! Do not use this unless you know what you are doing, clear all types registered and instances
@@ -399,32 +399,32 @@ namespace Umbraco.Core.ObjectResolution
}
}
/// <summary>
/// Inserts a type at the specified index.
/// </summary>
/// <param name="index">The zero-based index at which the type should be inserted.</param>
/// <param name="value">The type to insert.</param>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
public virtual void InsertType(int index, Type value)
{
EnsureSupportsInsert();
/// <summary>
/// Inserts a type at the specified index.
/// </summary>
/// <param name="index">The zero-based index at which the type should be inserted.</param>
/// <param name="value">The type to insert.</param>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
public virtual void InsertType(int index, Type value)
{
EnsureSupportsInsert();
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(value);
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(value);
if (_instanceTypes.Contains(value))
{
throw new InvalidOperationException(string.Format(
"Type {0} is already in the collection of types.", value.FullName));
}
{
throw new InvalidOperationException(string.Format(
"Type {0} is already in the collection of types.", value.FullName));
}
l.UpgradeToWriteLock();
_instanceTypes.Insert(index, value);
}
}
l.UpgradeToWriteLock();
_instanceTypes.Insert(index, value);
}
}
/// <summary>
/// Inserts a type at the beginning of the list.
@@ -445,9 +445,9 @@ namespace Umbraco.Core.ObjectResolution
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
public void InsertType<T>(int index)
where T : TResolved
{
InsertType(index, typeof(T));
}
{
InsertType(index, typeof(T));
}
/// <summary>
/// Inserts a type at the beginning of the list.
@@ -458,68 +458,68 @@ namespace Umbraco.Core.ObjectResolution
{
InsertType(0, typeof(T));
}
/// <summary>
/// Inserts a type before a specified, already existing type.
/// </summary>
/// <param name="existingType">The existing type before which to insert.</param>
/// <param name="value">The type to insert.</param>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
/// or the new type is already in the collection of types.</exception>
public virtual void InsertTypeBefore(Type existingType, Type value)
{
EnsureSupportsInsert();
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(existingType);
EnsureCorrectType(value);
/// <summary>
/// Inserts a type before a specified, already existing type.
/// </summary>
/// <param name="existingType">The existing type before which to insert.</param>
/// <param name="value">The type to insert.</param>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
/// or the new type is already in the collection of types.</exception>
public virtual void InsertTypeBefore(Type existingType, Type value)
{
EnsureSupportsInsert();
using (Resolution.Configuration)
using (var l = new UpgradeableReadLock(_lock))
{
EnsureCorrectType(existingType);
EnsureCorrectType(value);
if (_instanceTypes.Contains(existingType) == false)
{
throw new InvalidOperationException(string.Format(
"Type {0} is not in the collection of types.", existingType.FullName));
}
{
throw new InvalidOperationException(string.Format(
"Type {0} is not in the collection of types.", existingType.FullName));
}
if (_instanceTypes.Contains(value))
{
throw new InvalidOperationException(string.Format(
"Type {0} is already in the collection of types.", value.FullName));
}
{
throw new InvalidOperationException(string.Format(
"Type {0} is already in the collection of types.", value.FullName));
}
int index = _instanceTypes.IndexOf(existingType);
l.UpgradeToWriteLock();
_instanceTypes.Insert(index, value);
}
}
l.UpgradeToWriteLock();
_instanceTypes.Insert(index, value);
}
}
/// <summary>
/// Inserts a type before a specified, already existing type.
/// </summary>
/// <typeparam name="TExisting">The existing type before which to insert.</typeparam>
/// <typeparam name="T">The type to insert.</typeparam>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
/// or the new type is already in the collection of types.</exception>
public void InsertTypeBefore<TExisting, T>()
/// <summary>
/// Inserts a type before a specified, already existing type.
/// </summary>
/// <typeparam name="TExisting">The existing type before which to insert.</typeparam>
/// <typeparam name="T">The type to insert.</typeparam>
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
/// or the new type is already in the collection of types.</exception>
public void InsertTypeBefore<TExisting, T>()
where TExisting : TResolved
where T : TResolved
{
InsertTypeBefore(typeof(TExisting), typeof(T));
}
{
InsertTypeBefore(typeof(TExisting), typeof(T));
}
/// <summary>
/// Returns a value indicating whether the specified type is already in the collection of types.
/// </summary>
/// <param name="value">The type to look for.</param>
/// <returns>A value indicating whether the type is already in the collection of types.</returns>
public virtual bool ContainsType(Type value)
{
using (new ReadLock(_lock))
{
return _instanceTypes.Contains(value);
}
}
/// <summary>
/// Returns a value indicating whether the specified type is already in the collection of types.
/// </summary>
/// <param name="value">The type to look for.</param>
/// <returns>A value indicating whether the type is already in the collection of types.</returns>
public virtual bool ContainsType(Type value)
{
using (new ReadLock(_lock))
{
return _instanceTypes.Contains(value);
}
}
/// <summary>
/// Gets the types in the collection of types.
@@ -536,27 +536,27 @@ namespace Umbraco.Core.ObjectResolution
return types;
}
/// <summary>
/// Returns a value indicating whether the specified type is already in the collection of types.
/// </summary>
/// <typeparam name="T">The type to look for.</typeparam>
/// <returns>A value indicating whether the type is already in the collection of types.</returns>
public bool ContainsType<T>()
/// <summary>
/// Returns a value indicating whether the specified type is already in the collection of types.
/// </summary>
/// <typeparam name="T">The type to look for.</typeparam>
/// <returns>A value indicating whether the type is already in the collection of types.</returns>
public bool ContainsType<T>()
where T : TResolved
{
return ContainsType(typeof(T));
}
{
return ContainsType(typeof(T));
}
#endregion
#endregion
/// <summary>
/// Returns a WriteLock to use when modifying collections
/// </summary>
/// <returns></returns>
protected WriteLock GetWriteLock()
{
return new WriteLock(_lock);
}
/// <summary>
/// Returns a WriteLock to use when modifying collections
/// </summary>
/// <returns></returns>
protected WriteLock GetWriteLock()
{
return new WriteLock(_lock);
}
#region Type utilities
@@ -581,70 +581,71 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <exception cref="InvalidOperationException">The resolver does not support removing types.</exception>
protected void EnsureSupportsRemove()
{
if (SupportsRemove == false)
{
if (SupportsRemove == false)
throw new InvalidOperationException("This resolver does not support removing types");
}
}
/// <summary>
/// Ensures that the resolver supports clearing types.
/// </summary>
/// <exception cref="InvalidOperationException">The resolver does not support clearing types.</exception>
protected void EnsureSupportsClear() {
if (SupportsClear == false)
protected void EnsureSupportsClear()
{
if (SupportsClear == false)
throw new InvalidOperationException("This resolver does not support clearing types");
}
}
/// <summary>
/// Ensures that the resolver supports adding types.
/// </summary>
/// <exception cref="InvalidOperationException">The resolver does not support adding types.</exception>
protected void EnsureSupportsAdd()
{
if (SupportsAdd == false)
{
if (SupportsAdd == false)
throw new InvalidOperationException("This resolver does not support adding new types");
}
}
/// <summary>
/// Ensures that the resolver supports inserting types.
/// </summary>
/// <exception cref="InvalidOperationException">The resolver does not support inserting types.</exception>
protected void EnsureSupportsInsert()
{
if (SupportsInsert == false)
{
if (SupportsInsert == false)
throw new InvalidOperationException("This resolver does not support inserting new types");
}
}
/// <summary>
/// Gets a value indicating whether the resolver supports adding types.
/// </summary>
protected virtual bool SupportsAdd
{
get { return true; }
}
{
get { return true; }
}
/// <summary>
/// Gets a value indicating whether the resolver supports inserting types.
/// </summary>
protected virtual bool SupportsInsert
{
get { return true; }
}
{
get { return true; }
}
/// <summary>
/// Gets a value indicating whether the resolver supports clearing types.
/// </summary>
protected virtual bool SupportsClear
{
get { return true; }
}
{
get { return true; }
}
/// <summary>
/// Gets a value indicating whether the resolver supports removing types.
/// </summary>
protected virtual bool SupportsRemove
{
get { return true; }
{
get { return true; }
}
#endregion
@@ -1,25 +1,25 @@
using System;
namespace Umbraco.Core.ObjectResolution
{
/// <summary>
/// Indicates the relative weight of a resolved object type.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
internal class WeightedPluginAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="WeightedPluginAttribute"/> class with a weight.
/// </summary>
/// <param name="weight">The object type weight.</param>
public WeightedPluginAttribute(int weight)
{
Weight = weight;
}
/// <summary>
/// Gets or sets the weight of the object type.
/// </summary>
public int Weight { get; private set; }
}
using System;
namespace Umbraco.Core.ObjectResolution
{
/// <summary>
/// Indicates the relative weight of a resolved object type.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class WeightAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="WeightAttribute"/> class with a weight.
/// </summary>
/// <param name="weight">The object type weight.</param>
public WeightAttribute(int weight)
{
Weight = weight;
}
/// <summary>
/// Gets or sets the weight of the object type.
/// </summary>
public int Weight { get; private set; }
}
}
@@ -29,20 +29,24 @@ namespace Umbraco.Core.Packaging
/// </remarks>
public static IEnumerable<string> ScanAssembliesForTypeReference<T>(IEnumerable<byte[]> assemblys, out string[] errorReport)
{
var appDomain = GetTempAppDomain();
var type = typeof(PackageBinaryInspector);
try
// beware! when toying with domains, use a safe call context!
using (new SafeCallContext())
{
var value = (PackageBinaryInspector)appDomain.CreateInstanceAndUnwrap(
type.Assembly.FullName,
type.FullName);
// do NOT turn PerformScan into static (even if ReSharper says so)!
var result = value.PerformScan<T>(assemblys.ToArray(), out errorReport);
return result;
}
finally
{
AppDomain.Unload(appDomain);
var appDomain = GetTempAppDomain();
var type = typeof(PackageBinaryInspector);
try
{
var value = (PackageBinaryInspector) appDomain.CreateInstanceAndUnwrap(
type.Assembly.FullName,
type.FullName);
// do NOT turn PerformScan into static (even if ReSharper says so)!
var result = value.PerformScan<T>(assemblys.ToArray(), out errorReport);
return result;
}
finally
{
AppDomain.Unload(appDomain);
}
}
}
@@ -78,7 +82,7 @@ namespace Umbraco.Core.Packaging
/// <summary>
/// Performs the assembly scanning
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="assemblies"></param>
/// <param name="errorReport"></param>
/// <returns></returns>
@@ -107,7 +111,7 @@ namespace Umbraco.Core.Packaging
/// <summary>
/// Performs the assembly scanning
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="dllPath"></param>
/// <param name="errorReport"></param>
/// <returns></returns>
@@ -154,7 +158,7 @@ namespace Umbraco.Core.Packaging
//get the list of assembly names to compare below
var loadedNames = loaded.Select(x => x.GetName().Name).ToArray();
//Then load each referenced assembly into the context
foreach (var a in loaded)
{
@@ -170,7 +174,7 @@ namespace Umbraco.Core.Packaging
}
catch (FileNotFoundException)
{
//if an exception occurs it means that a referenced assembly could not be found
//if an exception occurs it means that a referenced assembly could not be found
errors.Add(
string.Concat("This package references the assembly '",
assemblyName.Name,
@@ -179,7 +183,7 @@ namespace Umbraco.Core.Packaging
}
catch (Exception ex)
{
//if an exception occurs it means that a referenced assembly could not be found
//if an exception occurs it means that a referenced assembly could not be found
errors.Add(
string.Concat("This package could not be verified for compatibility. An error occurred while loading a referenced assembly '",
assemblyName.Name,
@@ -197,7 +201,7 @@ namespace Umbraco.Core.Packaging
{
//now we need to see if they contain any type 'T'
var reflectedAssembly = a;
try
{
var found = reflectedAssembly.GetExportedTypes()
@@ -210,8 +214,8 @@ namespace Umbraco.Core.Packaging
}
catch (Exception ex)
{
//This is a hack that nobody can seem to get around, I've read everything and it seems that
// this is quite a common thing when loading types into reflection only load context, so
//This is a hack that nobody can seem to get around, I've read everything and it seems that
// this is quite a common thing when loading types into reflection only load context, so
// we're just going to ignore this specific one for now
var typeLoadEx = ex as TypeLoadException;
if (typeLoadEx != null)
@@ -232,7 +236,7 @@ namespace Umbraco.Core.Packaging
LogHelper.Error<PackageBinaryInspector>("An error occurred scanning package assemblies", ex);
}
}
}
errorReport = errors.ToArray();
@@ -252,7 +256,7 @@ namespace Umbraco.Core.Packaging
var contractType = contractAssemblyLoadFrom.GetExportedTypes()
.FirstOrDefault(x => x.FullName == typeof(T).FullName && x.Assembly.FullName == typeof(T).Assembly.FullName);
if (contractType == null)
{
throw new InvalidOperationException("Could not find type " + typeof(T) + " in the LoadFrom assemblies");
@@ -281,12 +285,8 @@ namespace Umbraco.Core.Packaging
PrivateBinPathProbe = AppDomain.CurrentDomain.SetupInformation.PrivateBinPathProbe
};
//create new domain with full trust
return AppDomain.CreateDomain(
appName,
AppDomain.CurrentDomain.Evidence,
domainSetup,
new PermissionSet(PermissionState.Unrestricted));
// create new domain with full trust
return AppDomain.CreateDomain(appName, AppDomain.CurrentDomain.Evidence, domainSetup, new PermissionSet(PermissionState.Unrestricted));
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
// ReSharper disable once CheckNamespace
namespace Umbraco.Core
{
static partial class Constants
{
public static class Locks
{
public const int Servers = -331;
}
}
}
@@ -0,0 +1,171 @@
#if DEBUG_DATABASES
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Umbraco.Core.Persistence
{
internal static class DatabaseDebugHelper
{
private const int CommandsSize = 100;
private static readonly Queue<Tuple<string, WeakReference<IDbCommand>>> Commands = new Queue<Tuple<string, WeakReference<IDbCommand>>>();
public static void SetCommand(IDbCommand command, string context)
{
var prof = command as StackExchange.Profiling.Data.ProfiledDbCommand;
if (prof != null) command = prof.InternalCommand;
lock (Commands)
{
Commands.Enqueue(Tuple.Create(context, new WeakReference<IDbCommand>(command)));
while (Commands.Count > CommandsSize) Commands.Dequeue();
}
}
public static string GetCommandContext(IDbCommand command)
{
lock (Commands)
{
var tuple = Commands.FirstOrDefault(x =>
{
IDbCommand c;
return x.Item2.TryGetTarget(out c) && c == command;
});
return tuple == null ? "?" : tuple.Item1;
}
}
public static string GetReferencedObjects(IDbConnection con)
{
var prof = con as StackExchange.Profiling.Data.ProfiledDbConnection;
if (prof != null) con = prof.InnerConnection;
var ceCon = con as System.Data.SqlServerCe.SqlCeConnection;
if (ceCon != null) return null; // "NotSupported: SqlCE";
var dbCon = con as DbConnection;
return dbCon == null
? "NotSupported: " + con.GetType()
: GetReferencedObjects(dbCon);
}
public static string GetReferencedObjects(DbConnection con)
{
var t = con.GetType();
var field = t.GetField("_innerConnection", BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null) throw new Exception("panic: _innerConnection (" + t + ").");
var innerConnection = field.GetValue(con);
var tin = innerConnection.GetType();
var fi = con is System.Data.SqlClient.SqlConnection
? tin.BaseType.BaseType.GetField("_referenceCollection", BindingFlags.Instance | BindingFlags.NonPublic)
: tin.BaseType.GetField("_referenceCollection", BindingFlags.Instance | BindingFlags.NonPublic);
if (fi == null)
//return "";
throw new Exception("panic: referenceCollection.");
var rc = fi.GetValue(innerConnection);
if (rc == null)
//return "";
throw new Exception("panic: innerCollection.");
field = rc.GetType().BaseType.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null) throw new Exception("panic: items.");
var items = field.GetValue(rc);
var prop = items.GetType().GetProperty("Length", BindingFlags.Instance | BindingFlags.Public);
if (prop == null) throw new Exception("panic: Length.");
var count = Convert.ToInt32(prop.GetValue(items, null));
var miGetValue = items.GetType().GetMethod("GetValue", new[] { typeof(int) });
if (miGetValue == null) throw new Exception("panic: GetValue.");
if (count == 0) return null;
StringBuilder result = null;
var hasb = false;
for (var i = 0; i < count; i++)
{
var referencedObj = miGetValue.Invoke(items, new object[] { i });
var hasTargetProp = referencedObj.GetType().GetProperty("HasTarget");
if (hasTargetProp == null) throw new Exception("panic: HasTarget");
var hasTarget = Convert.ToBoolean(hasTargetProp.GetValue(referencedObj, null));
if (hasTarget == false) continue;
if (hasb == false)
{
result = new StringBuilder();
result.AppendLine("ReferencedItems");
hasb = true;
}
//var inUseProp = referencedObj.GetType().GetProperty("InUse");
//if (inUseProp == null) throw new Exception("panic: InUse.");
//var inUse = Convert.ToBoolean(inUseProp.GetValue(referencedObj, null));
var inUse = "?";
var targetProp = referencedObj.GetType().GetProperty("Target");
if (targetProp == null) throw new Exception("panic: Target.");
var objTarget = targetProp.GetValue(referencedObj, null);
result.AppendFormat("\tDiff.Item id=\"{0}\" inUse=\"{1}\" type=\"{2}\" hashCode=\"{3}\"" + Environment.NewLine,
i, inUse, objTarget.GetType(), objTarget.GetHashCode());
DbCommand cmd = null;
if (objTarget is DbDataReader)
{
//var rdr = objTarget as DbDataReader;
try
{
cmd = objTarget.GetType().GetProperty("Command", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(objTarget, null) as DbCommand;
}
catch (Exception e)
{
result.AppendFormat("\t\tObjTarget: DbDataReader, Exception: {0}" + Environment.NewLine, e);
}
}
else if (objTarget is DbCommand)
{
cmd = objTarget as DbCommand;
}
if (cmd == null)
{
result.AppendFormat("\t\tObjTarget: {0}" + Environment.NewLine, objTarget.GetType());
continue;
}
result.AppendFormat("\t\tCommand type=\"{0}\" hashCode=\"{1}\"" + Environment.NewLine,
cmd.GetType(), cmd.GetHashCode());
var context = GetCommandContext(cmd);
result.AppendFormat("\t\t\tContext: {0}" + Environment.NewLine, context);
var properties = cmd.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var pi in properties)
{
if (pi.PropertyType.IsPrimitive || pi.PropertyType == typeof(string))
result.AppendFormat("\t\t\t{0}: {1}" + Environment.NewLine, pi.Name, pi.GetValue(cmd, null));
if (pi.PropertyType != typeof (DbConnection) || pi.Name != "Connection") continue;
var con1 = pi.GetValue(cmd, null) as DbConnection;
result.AppendFormat("\t\t\tConnection type=\"{0}\" state=\"{1}\" hashCode=\"{2}\"" + Environment.NewLine,
con1.GetType(), con1.State, con1.GetHashCode());
var propertiesCon = con1.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var picon in propertiesCon)
{
if (picon.PropertyType.IsPrimitive || picon.PropertyType == typeof(string))
result.AppendFormat("\t\t\t\t{0}: {1}" + Environment.NewLine, picon.Name, picon.GetValue(con1, null));
}
}
}
return result == null ? null : result.ToString();
}
}
}
#endif
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
{
internal static class DefinitionFactory
{
public static TableDefinition GetTableDefinition(Type modelType)
public static TableDefinition GetTableDefinition(ISqlSyntaxProvider syntaxProvider, Type modelType)
{
//Looks for PetaPoco's TableNameAtribute for the name of the table
//If no attribute is set we use the name of the Type as the default convention
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
//Otherwise use the name of the property itself as the default convention
var columnAttribute = propertyInfo.FirstAttribute<ColumnAttribute>();
string columnName = columnAttribute != null ? columnAttribute.Name : propertyInfo.Name;
var columnDefinition = GetColumnDefinition(modelType, propertyInfo, columnName, tableName);
var columnDefinition = GetColumnDefinition(syntaxProvider, modelType, propertyInfo, columnName, tableName);
tableDefinition.Columns.Add(columnDefinition);
//Creates a foreignkey definition and adds it to the collection on the table definition
@@ -58,7 +58,7 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
return tableDefinition;
}
public static ColumnDefinition GetColumnDefinition(Type modelType, PropertyInfo propertyInfo, string columnName, string tableName)
public static ColumnDefinition GetColumnDefinition(ISqlSyntaxProvider syntaxProvider, Type modelType, PropertyInfo propertyInfo, string columnName, string tableName)
{
var definition = new ColumnDefinition{ Name = columnName, TableName = tableName, ModificationType = ModificationType.Create };
@@ -110,7 +110,7 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
{
//Special case for MySQL as it can't have multiple default DateTime values, which
//is what the umbracoServer table definition is trying to create
if (SqlSyntaxContext.SqlSyntaxProvider is MySqlSyntaxProvider && definition.TableName == "umbracoServer" &&
if (syntaxProvider is MySqlSyntaxProvider && definition.TableName == "umbracoServer" &&
definition.TableName.ToLowerInvariant() == "lastNotifiedDate".ToLowerInvariant())
return definition;
@@ -99,7 +99,7 @@ namespace Umbraco.Core.Persistence
public void CreateTable(bool overwrite, Type modelType)
{
var tableDefinition = DefinitionFactory.GetTableDefinition(modelType);
var tableDefinition = DefinitionFactory.GetTableDefinition(_syntaxProvider, modelType);
var tableName = tableDefinition.Name;
string createSql = _syntaxProvider.Format(tableDefinition);
@@ -107,10 +107,10 @@ namespace Umbraco.Core.Persistence
var foreignSql = _syntaxProvider.Format(tableDefinition.ForeignKeys);
var indexSql = _syntaxProvider.Format(tableDefinition.Indexes);
var tableExist = _db.TableExist(tableName);
var tableExist = TableExist(tableName);
if (overwrite && tableExist)
{
_db.DropTable(tableName);
DropTable(tableName);
tableExist = false;
}
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Persistence
{
ValidateDatabase(database);
database.Execute("UPDATE umbracoNode SET sortOrder = (CASE WHEN (sortOrder=1) THEN -1 ELSE 1 END) WHERE id=@id",
database.Execute("UPDATE umbracoLock SET value = (CASE WHEN (value=1) THEN -1 ELSE 1 END) WHERE id=@id",
new { @id = nodeId });
}
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence
{
ValidateDatabase(database);
database.ExecuteScalar<int>("SELECT sortOrder FROM umbracoNode WHERE id=@id",
database.ExecuteScalar<int>("SELECT value FROM umbracoLock WHERE id=@id",
new { @id = nodeId });
}
}
@@ -4,9 +4,11 @@ using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.SqlServerCe;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Persistence
@@ -42,13 +44,13 @@ namespace Umbraco.Core.Persistence
{
case DatabaseProviders.SqlServer:
case DatabaseProviders.SqlAzure:
factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
factory = DbProviderFactories.GetFactory(Constants.DatabaseProviders.SqlServer);
break;
case DatabaseProviders.SqlServerCE:
factory = DbProviderFactories.GetFactory("System.Data.SqlServerCe.4.0");
break;
case DatabaseProviders.MySql:
factory = DbProviderFactories.GetFactory("MySql.Data.MySqlClient");
factory = DbProviderFactories.GetFactory(Constants.DatabaseProviders.MySql);
break;
case DatabaseProviders.PostgreSQL:
case DatabaseProviders.Oracle:
@@ -69,6 +71,38 @@ namespace Umbraco.Core.Persistence
}
}
public static string GetConnStringExSecurityInfo(this IDbConnection connection)
{
try
{
if (connection is SqlConnection)
{
var builder = new SqlConnectionStringBuilder(connection.ConnectionString);
return string.Format("DataSource: {0}, InitialCatalog: {1}", builder.DataSource, builder.InitialCatalog);
}
if (connection is SqlCeConnection)
{
var builder = new SqlCeConnectionStringBuilder(connection.ConnectionString);
return string.Format("DataSource: {0}", builder.DataSource);
}
if (connection is MySqlConnection)
{
var builder = new MySqlConnectionStringBuilder(connection.ConnectionString);
return string.Format("Server: {0}, Database: {1}", builder.Server, builder.Database);
}
}
catch (Exception ex)
{
LogHelper.WarnWithException(typeof(DbConnectionExtensions),
"Could not resolve connection string parameters", ex);
return "(Could not resolve)";
}
throw new ArgumentException(string.Format("The connection type {0} is not supported", connection.GetType()));
}
public static bool IsAvailable(this IDbConnection connection)
{
try
@@ -79,7 +113,8 @@ namespace Umbraco.Core.Persistence
catch (DbException exc)
{
// Don't swallow this error, the exception is super handy for knowing "why" its not available
LogHelper.WarnWithException<IDbConnection>("Configured database is reporting as not being available!", exc);
LogHelper.WarnWithException(typeof(DbConnectionExtensions),
"Configured database is reporting as not being available! {0}", exc, connection.GetConnStringExSecurityInfo);
return false;
}
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;
using System.Web;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Persistence
@@ -19,13 +20,24 @@ namespace Umbraco.Core.Persistence
private readonly ILogger _logger;
public string ConnectionString { get; private set; }
public string ProviderName { get; private set; }
//very important to have ThreadStatic:
// see: http://issues.umbraco.org/issue/U4-2172
[ThreadStatic]
private static volatile UmbracoDatabase _nonHttpInstance;
private static readonly object Locker = new object();
// NO! see notes in v8 HybridAccessorBase
//[ThreadStatic]
//private static volatile UmbracoDatabase _nonHttpInstance;
private const string ItemKey = "Umbraco.Core.Persistence.DefaultDatabaseFactory";
private static UmbracoDatabase NonContextValue
{
get { return (UmbracoDatabase) CallContext.LogicalGetData(ItemKey); }
set
{
if (value == null) CallContext.FreeNamedDataSlot(ItemKey);
else CallContext.LogicalSetData(ItemKey, value);
}
}
private static readonly object Locker = new object();
/// <summary>
/// Constructor accepting custom connection string
@@ -34,9 +46,12 @@ namespace Umbraco.Core.Persistence
/// <param name="logger"></param>
public DefaultDatabaseFactory(string connectionStringName, ILogger logger)
{
if (logger == null) throw new ArgumentNullException("logger");
if (logger == null) throw new ArgumentNullException("logger");
Mandate.ParameterNotNullOrEmpty(connectionStringName, "connectionStringName");
_connectionStringName = connectionStringName;
//if (NonContextValue != null) throw new Exception("NonContextValue is not null.");
_connectionStringName = connectionStringName;
_logger = logger;
}
@@ -48,68 +63,264 @@ namespace Umbraco.Core.Persistence
/// <param name="logger"></param>
public DefaultDatabaseFactory(string connectionString, string providerName, ILogger logger)
{
if (logger == null) throw new ArgumentNullException("logger");
if (logger == null) throw new ArgumentNullException("logger");
Mandate.ParameterNotNullOrEmpty(connectionString, "connectionString");
Mandate.ParameterNotNullOrEmpty(providerName, "providerName");
ConnectionString = connectionString;
//if (NonContextValue != null) throw new Exception("NonContextValue is not null.");
ConnectionString = connectionString;
ProviderName = providerName;
_logger = logger;
}
public UmbracoDatabase CreateDatabase()
{
//no http context, create the singleton global object
if (HttpContext.Current == null)
{
if (_nonHttpInstance == null)
{
lock (Locker)
{
//double check
if (_nonHttpInstance == null)
{
_nonHttpInstance = string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false
? new UmbracoDatabase(ConnectionString, ProviderName, _logger)
: new UmbracoDatabase(_connectionStringName, _logger);
}
}
}
return _nonHttpInstance;
}
UmbracoDatabase database;
//we have an http context, so only create one per request
if (HttpContext.Current.Items.Contains(typeof(DefaultDatabaseFactory)) == false)
{
HttpContext.Current.Items.Add(typeof (DefaultDatabaseFactory),
string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false
? new UmbracoDatabase(ConnectionString, ProviderName, _logger)
: new UmbracoDatabase(_connectionStringName, _logger));
}
return (UmbracoDatabase)HttpContext.Current.Items[typeof(DefaultDatabaseFactory)];
// gets or creates a database, using either the call context (if no http context) or
// the current request context (http context) to store it. once done using the database,
// it should be disposed - which will remove it from whatever context it is currently
// stored in. this is automatic with http context because UmbracoDatabase implements
// IDisposeOnRequestEnd, but NOT with call context.
if (HttpContext.Current == null)
{
database = NonContextValue;
if (database == null)
{
lock (Locker)
{
database = NonContextValue;
if (database == null)
{
database = CreateDatabaseInstance(ContextOwner.CallContext);
NonContextValue = database;
}
#if DEBUG_DATABASES
else
{
Log("Get lcc", database);
}
#endif
}
}
#if DEBUG_DATABASES
else
{
Log("Get lcc", database);
}
#endif
return database;
}
if (HttpContext.Current.Items.Contains(typeof (DefaultDatabaseFactory)) == false)
{
database = CreateDatabaseInstance(ContextOwner.HttpContext);
HttpContext.Current.Items.Add(typeof (DefaultDatabaseFactory), database);
}
else
{
database = (UmbracoDatabase) HttpContext.Current.Items[typeof(DefaultDatabaseFactory)];
#if DEBUG_DATABASES
Log("Get ctx", database);
#endif
}
return database;
}
protected override void DisposeResources()
// called by UmbracoDatabase when disposed, so that the factory can de-list it from context
internal void OnDispose(UmbracoDatabase disposing)
{
var value = disposing;
switch (disposing.ContextOwner)
{
case ContextOwner.CallContext:
value = NonContextValue;
break;
case ContextOwner.HttpContext:
value = (UmbracoDatabase) HttpContext.Current.Items[typeof (DefaultDatabaseFactory)];
break;
}
if (value != null && value.InstanceId != disposing.InstanceId) throw new Exception("panic: wrong db.");
switch (disposing.ContextOwner)
{
case ContextOwner.CallContext:
NonContextValue = null;
#if DEBUG_DATABASES
Log("Clr lcc", disposing);
#endif
break;
case ContextOwner.HttpContext:
HttpContext.Current.Items.Remove(typeof(DefaultDatabaseFactory));
#if DEBUG_DATABASES
Log("Clr ctx", disposing);
#endif
break;
}
disposing.ContextOwner = ContextOwner.None;
#if DEBUG_DATABASES
_databases.Remove(value);
#endif
}
#if DEBUG_DATABASES
// helps identifying when non-httpContext databases are created by logging the stack trace
private void LogCallContextStack()
{
var trace = Environment.StackTrace;
if (trace.IndexOf("ScheduledPublishing") > 0)
LogHelper.Debug<DefaultDatabaseFactory>("CallContext: Scheduled Publishing");
else if (trace.IndexOf("TouchServerTask") > 0)
LogHelper.Debug<DefaultDatabaseFactory>("CallContext: Server Registration");
else if (trace.IndexOf("LogScrubber") > 0)
LogHelper.Debug<DefaultDatabaseFactory>("CallContext: Log Scrubber");
else
LogHelper.Debug<DefaultDatabaseFactory>("CallContext: " + Environment.StackTrace);
}
private readonly List<UmbracoDatabase> _databases = new List<UmbracoDatabase>();
// helps identifying database leaks by keeping track of all instances
public List<UmbracoDatabase> Databases { get { return _databases; } }
private static void Log(string message, UmbracoDatabase database)
{
LogHelper.Debug<DefaultDatabaseFactory>(message + " (" + (database == null ? "" : database.InstanceSid) + ").");
}
#endif
internal enum ContextOwner
{
None,
HttpContext,
CallContext
}
internal UmbracoDatabase CreateDatabaseInstance(ContextOwner contextOwner)
{
var database = string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false
? new UmbracoDatabase(ConnectionString, ProviderName, _logger)
: new UmbracoDatabase(_connectionStringName, _logger);
database.ContextOwner = contextOwner;
database.DatabaseFactory = this;
//database.EnableSqlTrace = true;
#if DEBUG_DATABASES
Log("Create " + contextOwner, database);
if (contextOwner == ContextOwner.CallContext)
LogCallContextStack();
_databases.Add(database);
#endif
return database;
}
protected override void DisposeResources()
{
if (HttpContext.Current == null)
{
_nonHttpInstance.Dispose();
}
else
{
if (HttpContext.Current.Items.Contains(typeof(DefaultDatabaseFactory)))
{
((UmbracoDatabase)HttpContext.Current.Items[typeof(DefaultDatabaseFactory)]).Dispose();
}
}
}
UmbracoDatabase database;
if (HttpContext.Current == null)
{
database = NonContextValue;
#if DEBUG_DATABASES
Log("Release lcc", database);
#endif
}
else
{
database = (UmbracoDatabase) HttpContext.Current.Items[typeof (DefaultDatabaseFactory)];
#if DEBUG_DATABASES
Log("Release ctx", database);
#endif
}
if (database != null) database.Dispose(); // removes it from call context
}
// during tests, the thread static var can leak between tests
// this method provides a way to force-reset the variable
internal void ResetForTests()
internal void ResetForTests()
{
if (_nonHttpInstance == null) return;
_nonHttpInstance.Dispose();
_nonHttpInstance = null;
var value = NonContextValue;
if (value != null) value.Dispose();
NonContextValue = null;
}
#region SafeCallContext
// see notes in SafeCallContext - need to do this since we are using
// the logical call context...
static DefaultDatabaseFactory()
{
SafeCallContext.Register(DetachAmbientDatabase, AttachAmbientDatabase);
}
// gets a value indicating whether there is an ambient database
internal static bool HasAmbientDatabase
{
get
{
return HttpContext.Current == null
? NonContextValue != null
: HttpContext.Current.Items[typeof (DefaultDatabaseFactory)] != null;
}
}
}
// detaches the current database
// ie returns the database and remove it from whatever is "context"
internal static UmbracoDatabase DetachAmbientDatabase()
{
UmbracoDatabase database;
if (HttpContext.Current == null)
{
database = NonContextValue;
NonContextValue = null;
}
else
{
database = (UmbracoDatabase) HttpContext.Current.Items[typeof (DefaultDatabaseFactory)];
HttpContext.Current.Items.Remove(typeof (DefaultDatabaseFactory));
}
if (database != null) database.ContextOwner = ContextOwner.None;
return database;
}
// attach a current database
// ie assign it to whatever is "context"
// throws if there already is a database
internal static void AttachAmbientDatabase(object o)
{
var database = o as UmbracoDatabase;
if (o != null && database == null) throw new ArgumentException("Not an UmbracoDatabase.", "o");
var ambient = DetachAmbientDatabase();
if (ambient != null) ambient.Dispose();
if (HttpContext.Current == null)
{
//if (NonContextValue != null) throw new InvalidOperationException();
if (database == null) return;
NonContextValue = database;
database.ContextOwner = ContextOwner.CallContext;
}
else
{
//if (HttpContext.Current.Items[typeof (DefaultDatabaseFactory)] != null) throw new InvalidOperationException();
if (database == null) return;
HttpContext.Current.Items[typeof (DefaultDatabaseFactory)] = database;
database.ContextOwner = ContextOwner.HttpContext;
}
}
#endregion
}
}
@@ -122,7 +122,7 @@ namespace Umbraco.Core.Persistence.Factories
else if (entity is IMemberType)
nodeObjectType = Constants.ObjectTypes.MemberTypeGuid;
else
throw new Exception("oops: invalid entity.");
throw new Exception("Invalid entity.");
var contentTypeDto = new ContentTypeDto
{
@@ -7,12 +7,9 @@ namespace Umbraco.Core.Persistence.Factories
{
internal class MacroFactory
{
#region Implementation of IEntityFactory<Language,LanguageDto>
public IMacro BuildEntity(MacroDto dto)
{
var model = new Macro(dto.Id, dto.UseInEditor, dto.RefreshRate, dto.Alias, dto.Name, dto.ScriptType, dto.ScriptAssembly, dto.Xslt, dto.CacheByPage, dto.CachePersonalized, dto.DontRender, dto.Python);
var model = new Macro(dto.Id, dto.UniqueId, dto.UseInEditor, dto.RefreshRate, dto.Alias, dto.Name, dto.ScriptType, dto.ScriptAssembly, dto.Xslt, dto.CacheByPage, dto.CachePersonalized, dto.DontRender, dto.Python);
try
{
@@ -20,7 +17,7 @@ namespace Umbraco.Core.Persistence.Factories
foreach (var p in dto.MacroPropertyDtos)
{
model.Properties.Add(new MacroProperty(p.Id, p.Alias, p.Name, p.SortOrder, p.EditorAlias));
model.Properties.Add(new MacroProperty(p.Id, p.UniqueId, p.Alias, p.Name, p.SortOrder, p.EditorAlias));
}
//on initial construction we don't want to have dirty properties tracked
@@ -36,8 +33,9 @@ namespace Umbraco.Core.Persistence.Factories
public MacroDto BuildDto(IMacro entity)
{
var dto = new MacroDto()
{
var dto = new MacroDto
{
UniqueId = entity.Key,
Alias = entity.Alias,
CacheByPage = entity.CacheByPage,
CachePersonalized = entity.CacheByMember,
@@ -58,8 +56,6 @@ namespace Umbraco.Core.Persistence.Factories
return dto;
}
#endregion
private List<MacroPropertyDto> BuildPropertyDtos(IMacro entity)
{
var list = new List<MacroPropertyDto>();
@@ -67,6 +63,7 @@ namespace Umbraco.Core.Persistence.Factories
{
var text = new MacroPropertyDto
{
UniqueId = p.Key,
Alias = p.Alias,
Name = p.Name,
Macro = entity.Id,
@@ -9,9 +9,10 @@ namespace Umbraco.Core.Persistence.Factories
{
internal class MemberTypeReadOnlyFactory
{
public IMemberType BuildEntity(MemberTypeReadOnlyDto dto)
public IMemberType BuildEntity(MemberTypeReadOnlyDto dto, out bool needsSaving)
{
var standardPropertyTypes = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
needsSaving = false;
var memberType = new MemberType(dto.ParentId);
@@ -47,6 +48,12 @@ namespace Umbraco.Core.Persistence.Factories
{
if (dto.PropertyTypes.Any(x => x.Alias.Equals(standardPropertyType.Key))) continue;
// beware!
// means that we can return a memberType "from database" that has some property types
// that do *not* come from the database and therefore are incomplete eg have no key,
// no id, no dataTypeDefinitionId - ouch! - better notify caller of the situation
needsSaving = true;
//Add the standard PropertyType to the current list
propertyTypes.Add(standardPropertyType.Value);
@@ -79,7 +86,7 @@ namespace Umbraco.Core.Persistence.Factories
{
// note: no idea why Id is nullable here, but better check
if (groupDto.Id.HasValue == false)
throw new Exception("oops: groupDto.Id has no value.");
throw new Exception("GroupDto.Id has no value.");
group.Id = groupDto.Id.Value;
}
@@ -8,7 +8,17 @@ namespace Umbraco.Core.Persistence.Mappers
{
public abstract class BaseMapper
{
private readonly ISqlSyntaxProvider _sqlSyntax;
protected BaseMapper() : this(SqlSyntaxContext.SqlSyntaxProvider)
{
}
protected BaseMapper(ISqlSyntaxProvider sqlSyntax)
{
_sqlSyntax = sqlSyntax;
}
internal abstract ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache { get; }
internal abstract void BuildMap();
@@ -58,8 +68,8 @@ namespace Umbraco.Core.Persistence.Mappers
string columnName = columnAttribute.Name;
string columnMap = string.Format("{0}.{1}",
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(columnName));
_sqlSyntax.GetQuotedTableName(tableName),
_sqlSyntax.GetQuotedColumnName(columnName));
return columnMap;
}
}
@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
using System.Linq.Expressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Mappers
{
@@ -16,6 +17,11 @@ namespace Umbraco.Core.Persistence.Mappers
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
public ContentMapper(ISqlSyntaxProvider sqlSyntax) : base(sqlSyntax)
{
}
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
// otherwise that would fail because there is no public constructor.
public ContentMapper()
@@ -43,7 +43,7 @@ namespace Umbraco.Core.Persistence.Mappers
{
return byAttribute.Result;
}
throw new Exception("Invalid Type: A Mapper could not be resolved based on the passed in Type");
throw new Exception("Invalid Type: A Mapper could not be resolved based on the passed in Type " + type);
});
}
@@ -33,7 +33,12 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
CreateUmbracNodeData();
}
if(tableName.Equals("cmsContentType"))
if (tableName.Equals("umbracoLock"))
{
CreateUmbracoLockData();
}
if (tableName.Equals("cmsContentType"))
{
CreateCmsContentTypeData();
}
@@ -141,16 +146,19 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
//_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1038, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1038", SortOrder = 2, UniqueId = new Guid("1251c96c-185c-4e9b-93f4-b48205573cbd"), Text = "Simple Editor", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
//_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1042, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1042", SortOrder = 2, UniqueId = new Guid("0a452bd5-83f9-4bc3-8403-1286e13fb77e"), Text = "Macro Container", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
}
private void CreateUmbracoLockData()
{
// all lock objects
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.ServersLock, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1," + Constants.System.ServersLock, SortOrder = 1, UniqueId = new Guid("0AF5E610-A310-4B6F-925F-E928D5416AF7"), Text = "LOCK: Servers", NodeObjectType = Constants.ObjectTypes.LockObjectGuid, CreateDate = DateTime.Now });
_database.Insert("umbracoLock", "id", false, new LockDto { Id = Constants.Locks.Servers, Name = "Servers" });
}
private void CreateCmsContentTypeData()
{
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Constants.Conventions.MediaTypes.Folder, Icon = "icon-folder", Thumbnail = "icon-folder", IsContainer = false, AllowAtRoot = true });
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Constants.Conventions.MediaTypes.Image, Icon = "icon-picture", Thumbnail = "icon-picture" });
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Constants.Conventions.MediaTypes.File, Icon = "icon-document", Thumbnail = "icon-document" });
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Constants.Conventions.MediaTypes.Image, Icon = "icon-picture", Thumbnail = "icon-picture", AllowAtRoot = true });
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Constants.Conventions.MediaTypes.File, Icon = "icon-document", Thumbnail = "icon-document", AllowAtRoot = true });
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Constants.Conventions.MemberTypes.DefaultAlias, Icon = "icon-user", Thumbnail = "icon-user" });
}
@@ -266,9 +274,9 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
//defaults for the member list
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -1, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "10" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "Name" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "username" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -3, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "asc" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -4, Alias = "includeProperties", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "[{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -4, Alias = "includeProperties", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "[{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]" });
//layouts for the list view
var cardLayout = "{\"name\": \"Grid\",\"path\": \"views/propertyeditors/listview/layouts/grid/grid.html\", \"icon\": \"icon-thumbnails-small\", \"isSystem\": 1, \"selected\": true}";
@@ -276,10 +284,10 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
//defaults for the media list
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -5, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "100" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -6, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "VersionDate" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -6, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "updateDate" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -7, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "desc" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -8, Alias = "layouts", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[" + cardLayout + "," + listLayout + "]" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -9, Alias = "includeProperties", SortOrder = 5, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[{\"alias\":\"sortOrder\",\"isSystem\":1, \"header\": \"Sort order\"},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -9, Alias = "includeProperties", SortOrder = 5, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]" });
}
private void CreateUmbracoRelationTypeData()
@@ -82,9 +82,10 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{43, typeof (CacheInstructionDto)},
{44, typeof (ExternalLoginDto)},
{45, typeof (MigrationDto)},
{46, typeof (UmbracoDeployChecksumDto)},
{47, typeof (UmbracoDeployDependencyDto)},
{48, typeof (RedirectUrlDto) }
//46, removed: UmbracoDeployChecksumDto
//47, removed: UmbracoDeployDependencyDto
{48, typeof (RedirectUrlDto) },
{49, typeof (LockDto) }
};
#endregion
@@ -159,7 +160,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
foreach (var item in OrderedTables.OrderBy(x => x.Key))
{
var tableDefinition = DefinitionFactory.GetTableDefinition(item.Value);
var tableDefinition = DefinitionFactory.GetTableDefinition(_sqlSyntaxProvider, item.Value);
result.TableDefinitions.Add(tableDefinition);
}
@@ -43,8 +43,13 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
/// <returns></returns>
public SemVersion DetermineInstalledVersionByMigrations(IMigrationEntryService migrationEntryService)
{
var allMigrations = migrationEntryService.GetAll(GlobalSettings.UmbracoMigrationName);
var mostrecent = allMigrations.OrderByDescending(x => x.Version).Select(x => x.Version).FirstOrDefault();
SemVersion mostrecent = null;
if (ValidTables.Any(x => x.InvariantEquals("umbracoMigration")))
{
var allMigrations = migrationEntryService.GetAll(GlobalSettings.UmbracoMigrationName);
mostrecent = allMigrations.OrderByDescending(x => x.Version).Select(x => x.Version).FirstOrDefault();
}
return mostrecent ?? new SemVersion(new Version(0, 0, 0));
}
@@ -116,13 +121,25 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
//if the error is for umbracoAccess it must be the previous version to 7.3 since that is when it is added
if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoAccess"))))
{
return new Version(7, 2, 5);
return new Version(7, 2, 0);
}
//if the error is for umbracoDeployChecksum it must be the previous version to 7.4 since that is when it is added
if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoDeployChecksum"))))
{
return new Version(7, 3, 4);
return new Version(7, 3, 0);
}
//if the error is for umbracoRedirectUrl it must be the previous version to 7.5 since that is when it is added
if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoRedirectUrl"))))
{
return new Version(7, 4, 0);
}
//if the error indicates a problem with the column cmsMacroProperty.uniquePropertyId then it is not version 7.6 since that is when it is added
if (Errors.Any(x => x.Item1.Equals("Column") && (x.Item2.InvariantEquals("cmsMacroProperty,uniquePropertyId"))))
{
return new Version(7, 5, 0);
}
return UmbracoVersion.Current;
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Migrations
Logger = logger;
}
internal IMigrationContext Context;
public IMigrationContext Context { get; internal set; }
public abstract void Up();
public abstract void Down();
@@ -6,6 +6,7 @@ using Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions;
using Umbraco.Core.Persistence.Migrations.Syntax.Create.ForeignKey;
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Index;
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Table;
using Umbraco.Core.Persistence.Migrations.Syntax.Execute.Expressions;
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -27,6 +28,24 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create
_databaseProviders = databaseProviders;
}
public void Table<T>()
{
var tableDefinition = DefinitionFactory.GetTableDefinition(_sqlSyntax, typeof(T));
AddSql(_sqlSyntax.Format(tableDefinition));
AddSql(_sqlSyntax.FormatPrimaryKey(tableDefinition));
foreach (var sql in _sqlSyntax.Format(tableDefinition.ForeignKeys))
AddSql(sql);
foreach (var sql in _sqlSyntax.Format(tableDefinition.Indexes))
AddSql(sql);
}
private void AddSql(string sql)
{
var expression = new ExecuteSqlStatementExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { SqlStatement = sql };
_context.Expressions.Add(expression);
}
public ICreateTableWithColumnSyntax Table(string tableName)
{
var expression = new CreateTableExpression(_context.CurrentDatabaseProvider, _databaseProviders, _sqlSyntax) { TableName = tableName };
@@ -8,6 +8,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create
{
public interface ICreateBuilder : IFluentSyntax
{
void Table<T>();
ICreateTableWithColumnSyntax Table(string tableName);
ICreateColumnOnTableSyntax Column(string columnName);

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