Compare commits

..

303 Commits

Author SHA1 Message Date
Sebastiaan Janssen a8d7a1d01d Makes the test green: don't add the passed in composition as a dependency to itself.. also added another invariant check 2014-12-15 19:52:28 +01:00
Sebastiaan Janssen e62597521e Remove the renaming to 'title' which would cause a duplicate and make the next test fail 2014-12-15 19:51:37 +01:00
Sebastiaan Janssen fa91321299 Adds test for adding properties to a composition that has been saved and now doesn't allow a new property to be added 2014-12-15 18:56:58 +01:00
Morten Christensen 2d81691407 Adding new test case for renaming PropertyType aliases on indirect references 2014-12-15 16:34:41 +01:00
Morten Christensen 21f08ca491 Refactoring validation and adding new test case for renaming PropertyTypes 2014-12-15 15:33:05 +01:00
Morten Christensen e202f21934 Adds new test, fix, refactoring for adding duplicate PropertyType aliases 2014-12-15 14:29:48 +01:00
Shannon 2936ff0bf9 Makes provider user key type for new membership provider configurable, by default it is int 2014-12-15 20:44:00 +11:00
Sebastiaan Janssen 8e4e575276 Makes sure messages are shown in the user's configured language 2014-12-15 09:30:04 +01:00
Sebastiaan Janssen 84752babc8 Moved both new sections to the bottom so it's easier for upgraders to merge them 2014-12-15 09:04:25 +01:00
Shannon 60a1116acd Fixes: U4-6009 Distributed calls not working in 7.2 2014-12-15 11:45:55 +11:00
Sebastiaan Janssen a480d7bbe6 U4-5959 Getting YSOD when wanting to create partial view in a subfolder in the backoffie
#U4-5959 Fixed Due in version 7.2.1
2014-12-14 17:22:10 +01:00
Sebastiaan Janssen 7316c5462a U4-5928 Umbraco 7.2 RC GetCurrentMemberProfileModel Null Ref
#U4-5928 Fixed Due in version 7.2.1
2014-12-14 16:50:11 +01:00
Morten Christensen 2a9960afb3 Adding UI feedback for invalid compositions 2014-12-12 17:04:53 +01:00
Morten Christensen ed899ec73d Adding additional test coverage for Compositions and updating PropertyTypes and PropertyGroups 2014-12-12 17:04:11 +01:00
Morten Christensen 8f26f9385d Refactoring the logic around saving updates to PropertyTypes and PropertyGroups 2014-12-12 17:02:03 +01:00
Morten Christensen a446cc224d Refactoring the logic in the validation method for when ContentTypes are saved 2014-12-11 17:14:01 +01:00
Morten Christensen 07f9a9700d Ensures that inherited PropertyType aliases are also checked for indirect references 2014-12-11 12:22:49 +01:00
Sebastiaan Janssen 7e7acd0049 Correcting my mistakes to the unit test, using the wrong alias 2014-12-11 11:02:51 +01:00
Morten Christensen 57985c26a2 Updating the name of PropertyGroups in DB to ensure renaming is done properly 2014-12-11 10:55:33 +01:00
Morten Christensen 504c1f7254 Updating tests related to #U4-5986
Conflicts:
	src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs
2014-12-11 10:55:21 +01:00
Shannon 52ad36a6c2 removes commented out code form PR 2014-12-11 10:49:41 +01:00
Peter Gregory 01670e0832 Fixes issue U4-5925 GetMedia returning nothing
Removed the use of FromXElement that was only used by GetMedia.  The change introduced in commit f3f6504398 caused GetMedia to return nothing due to the introduction of the FromXElement method.
2014-12-11 10:49:30 +01:00
Stephan 99c96bce86 U4-5986 - reject ppty alias used by ancestor 2014-12-10 13:01:51 +01:00
Sebastiaan Janssen da2bc6764b Version also updates in the csproj 2014-12-10 12:59:08 +01:00
Shannon d11a377f0f bump version 2014-12-10 12:28:06 +01:00
Stephan d445f7cb0d U4-5986 - reject ppty alias used by descendant 2014-12-10 12:27:55 +01:00
Sebastiaan Janssen 899d325ca1 Updates unit tests to use the newer new ContentType method and obsoletes the old one 2014-12-10 11:52:03 +01:00
Sebastiaan Janssen f1107b7a91 Fixes U4-5986 Compositions: Possible to get stuck in document type ysod's
#U4-5986 Fixed Due in version 7.2.1
2014-12-10 11:51:53 +01:00
Stephan a3f171e7b3 U4-5931 - fix DocType inheritance issue 2014-12-10 11:51:42 +01:00
Sebastiaan Janssen 788a0241d8 Remove Forms preview notice 2014-12-04 13:17:29 +01:00
Sebastiaan Janssen 25237995eb It's nice to unzip a build in the build folder, so just ignore it for git :) 2014-12-04 12:41:39 +01:00
per ploug ed75109829 Removes textstring editor controller - not needed
functionality moved to directive
2014-12-04 12:27:33 +01:00
per ploug 6738a25bfa Fxes grid datatype config to handle cols > 12 and <= 0 2014-12-04 12:27:10 +01:00
per ploug aa9c753455 Forms installer cookie check fixed 2014-12-04 12:26:32 +01:00
per ploug 0e5f9b92e8 adds autocomplete=off to installer password
To avoid autocomplete to pick up peoples secret passwords
2014-12-04 12:26:05 +01:00
per ploug 77fd4d383b Fixes grid cell resizing timing bug 2014-12-04 12:25:33 +01:00
Sebastiaan Janssen 98a03a0127 Fixes nonodes a:visited bug 2014-12-04 08:55:19 +01:00
Shannon 464130a102 Fixes: U4-5930 Lock "Save and publish" once activated 2014-12-04 13:09:28 +11:00
Shannon dfb324b003 Fixes: U4-5706 Listview search bar enter button in IE11 submits form 2014-12-04 12:44:46 +11:00
Shannon 966b8565ba publicizes Mandate 2014-12-04 11:36:15 +11:00
Shannon 2b774dbdf2 Revert "Revert "Fixes PetaPoco to support Medium trust." - This revert back to original peta poco actually causes issues with some custom multi-poco queries, turns out the med trust fix also fixes a few other things! We've been running with this fix for a very long time now so it is definitely stable and correct. 2014-12-04 11:35:42 +11:00
Sebastiaan Janssen cae600ac2f Merge pull request #574 from readingdancer/Fix_for_U4-4125
Fix for U4 4125 - Spanish Localization file updated.
2014-12-03 17:12:23 +01:00
Chris Houston 5e4702a4ab Final changes (for now) for the Spanish localization file. 2014-12-03 16:04:26 +00:00
Sebastiaan Janssen 8442b2e8e7 Updates installer backgrounnd and nonodes page 2014-12-03 16:51:16 +01:00
Morten Christensen 64efd0abbc #U4-5913 Fixed Media Type composition panel so it shows the right types 2014-12-03 16:40:46 +01:00
Chris Houston b8f3f93d83 Added more Spanish translations. 2014-12-03 14:24:13 +00:00
per ploug ce9e851087 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-12-03 14:11:08 +01:00
per ploug 53d9a34996 Makes the forms installer reload hard 2014-12-03 14:10:44 +01:00
Sebastiaan Janssen 2f79d4a71d Better replacement of examine management ascx to html 2014-12-03 11:27:02 +01:00
per ploug 98d72da622 Removes .Syntax from grid macro editor
This is never used and should not be stored
2014-12-03 10:33:52 +01:00
Sebastiaan Janssen c563629756 Bump version 2014-12-03 10:25:08 +01:00
Sebastiaan Janssen acb3ecbbf7 Updates NuGet Readme 2014-12-03 09:57:22 +01:00
Shannon Deminick 2cbe6f5543 Merge pull request #571 from umbraco/starterkit
Implements new starterkit rest call
2014-12-03 18:58:40 +11:00
Sebastiaan Janssen 9beaaa825e Use the UmbracoContext property instead of the singleton 2014-12-03 08:56:21 +01:00
per ploug bf90edb5be Fixed U4-5906 7.2.0 RC - other values than 12 in Grid Columns config mess up styling 2014-12-03 08:17:02 +01:00
Shannon 94a506f8e8 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-12-03 15:24:22 +11:00
Shannon 4f68941f98 Fixes: U4-5701 Upgrade to 7.2 beta error. Cannot alter column of type NTEXT or IMAGE. 2014-12-03 15:24:10 +11:00
Morten Christensen 25de56a98b Ensuring that imported data types raise events with PreValues saved. 2014-12-02 16:11:59 +01:00
Morten Christensen b11135a096 Fixes #U4-5921 Import of Document Type fails, if dependencies are not part of the import. 2014-12-02 13:35:58 +01:00
Sebastiaan Janssen d4db32c0f2 Don't ship with or require dotLess install 2014-12-02 11:44:15 +01:00
Sebastiaan Janssen d54f35f5f7 Merge pull request #570 from readingdancer/Fix_for_U4-5911
Fixed issue U4-5911 & part of U4-5101 - Allow descriptions on property editors to be localized
2014-12-02 11:25:21 +01:00
Shannon f163381399 Fixes: U4-4756 Error Uploading images to Media section 2014-12-02 17:47:16 +11:00
Morten Christensen 86cb3e8695 Adding a unit test for importing the Fanoe package xml 2014-12-01 15:40:52 +01:00
Morten Christensen dcc50c3b53 Adding optional ctor overload for ContentType to enable passing an Alias 2014-12-01 15:26:20 +01:00
Sebastiaan Janssen 0209b71182 Fixes problem where Umbraco "thinks" it's a brand new install when upgrading sites on UaaS 2014-12-01 13:44:50 +01:00
Sebastiaan Janssen 6b92e47631 Unfortunately, we HAVE to point to MVC 4.0.0.0 else you get YSODs on machines with 4.0.0.1 in the GAC (and we can't point to 4.0.0.1 because 4.0.0.0 might be in the GAC and then it'll YSOD for THOSE people). BOOOO 2014-12-01 10:57:24 +01:00
Sebastiaan Janssen 36ffebbb49 Adds usings for the http request, client and response 2014-12-01 08:17:37 +01:00
Chris Houston d0bafc6184 Removed "description" as Shaz pointed out this was not required.
Fixed a couple of UK English spelling mistakes.
2014-11-30 23:54:46 +00:00
Sebastiaan Janssen 801828df70 Update test URL to live URL 2014-11-30 17:02:25 +01:00
Sebastiaan Janssen 953c371580 Get starterkits in new way so we can support version compatibility (Fanoe is only compatible with 7.2+) 2014-11-30 15:50:55 +01:00
Chris Houston 83d3882b9a - Added the GRID localization strings to the US English file.
- Updated the umbControlGroup directive so that the Description files are now localized, for some reason only the label was being localized even though the text had been added to the UK English file?
2014-11-30 01:27:26 +00:00
Morten Christensen c37777b289 It should not be possible for a ContentType to add itself as a composition 2014-11-28 13:11:11 +01:00
Sebastiaan Janssen ef6a4139de Whoops, period should've been comma 2014-11-28 07:44:19 +01:00
Sebastiaan Janssen 98ceabaf7e Don't point web.config to MVC 4.0.0.1, it may not be installed (merge fail..) 2014-11-27 20:44:48 +01:00
Sebastiaan Janssen 85bcb7ad2b Update migration 2014-11-27 20:20:56 +01:00
Sebastiaan Janssen adea6dd2f6 Final addition to disallowed upload files 2014-11-27 15:28:38 +01:00
Sebastiaan Janssen cad0650223 #U4-5901 Fixed Due in version 7.2.0
Remote Code Execution
2014-11-27 14:29:49 +01:00
Sebastiaan Janssen d8909fe09c Also adds migration for U4-5837 2014-11-27 14:11:18 +01:00
Sebastiaan Janssen bf5acf6724 #U4-5837 Fixed Due in version 7.2.0
Missing Indexes
2014-11-27 13:57:39 +01:00
Sebastiaan Janssen 9bf33f0eea #U4-5893 Fixed
Related Links - rearranging a link will completely remove all link content fields
2014-11-27 13:24:23 +01:00
Sebastiaan Janssen 0155a094b1 Bump Version 2014-11-27 12:12:31 +01:00
Sebastiaan Janssen 08432e8b23 U4-5895 follow up on U4-5889 2014-11-27 12:05:38 +01:00
Stephan 717f67874a Fix nodeType.ascx merge issue 2014-11-27 11:57:38 +01:00
Shannon dc27368397 Fixes: U4-5891 2014-11-27 17:57:33 +11:00
Morten Christensen de7900cd2e Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-11-26 22:47:51 +01:00
Morten Christensen c288c2b9a3 Improves sorting of doc types before importing. Related to U4-5868 2014-11-26 22:47:36 +01:00
Sebastiaan Janssen 26032e46dd Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-11-26 14:42:41 +01:00
Sebastiaan Janssen caee5c6baf #U4-5889 Fixed Due in version 7.2.0
Cross Site Scripting through umbraco uploader
2014-11-26 14:42:24 +01:00
Morten Christensen ea9c37d500 Implements U4-5868 Packager should include compositions 2014-11-26 14:22:31 +01:00
Sebastiaan Janssen a1c223bc2b Revert to using MVC 4.0.0.0 OOB so that people who have only 4.0.0.0 in the GAC can actually install Umbraco. If 4.0.0.1 is in the GAC that version will be taken.
Leaves the additional reference to System.Web.Http in web.config so that you don't get the System.Web.Http.ApiController when 4.0.0.1 is indeed in the GAC.
2014-11-26 10:43:46 +01:00
Shannon 6afd9b37a6 Merge branch '7.1.9' into 7.2.0 2014-11-26 15:29:18 +11:00
Shannon 1930022f19 Fixes: U4-5714 Calling Index() on IPublishedContent level 1 media fails 2014-11-26 10:52:30 +11:00
Shannon bece953fa3 fixes a null check 2014-11-26 10:20:19 +11:00
Shannon a41d37b1cf Fixes assembly error msg. 2014-11-26 09:44:31 +11:00
Shannon 31603f7063 Fixes assembly error msg. 2014-11-26 09:43:44 +11:00
Sebastiaan Janssen 4520c06454 Fixes missing filename in the log 2014-11-25 19:21:10 +01:00
Sebastiaan Janssen 9f0c00827d Fixes build, still had some wrong paths preventing build.bat from working 2014-11-25 18:54:25 +01:00
Sebastiaan Janssen 2a66f95873 #U4-5453 Fixed
#U4-5871
Enabling IIS Compression gives ERR_CONTENT_DECODING_FAILED in backoffice
2014-11-25 18:22:27 +01:00
Sebastiaan Janssen 3330c617b4 Merge branch '7.1.9' into 7.2.0
Conflicts:
	src/SQLCE4Umbraco/SqlCEHelper.cs
2014-11-25 17:04:47 +01:00
Sebastiaan Janssen 0df0b78b90 #U4-5453 Fixed
Enabling IIS Compression gives ERR_CONTENT_DECODING_FAILED in backoffice
2014-11-25 16:56:44 +01:00
Sebastiaan Janssen c6b6685dc7 Fixes the build for VS15 2014-11-25 16:55:59 +01:00
Sebastiaan Janssen 2db45eaca3 Merge pull request #516 from nul800sebastiaan/vs2014
Fixes VS14 build.
2014-11-25 15:52:05 +01:00
per ploug b876e34586 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-11-25 14:41:50 +01:00
per ploug 935436203e Adds razor helper comments to all grid razor views 2014-11-25 14:41:43 +01:00
Stephan 9580c8965f Merge branch '7.1.9' into 7.2.0
Conflicts:
	src/Umbraco.Web/umbraco.presentation/umbraco/create/nodeType.ascx.cs
2014-11-25 11:34:49 +01:00
Stephan 7c3c477f18 Merge remote-tracking branch 'origin/7.1.9' into 7.1.9
Conflicts:
	src/Umbraco.Web/umbraco.presentation/umbraco/create/nodeType.ascx.cs
2014-11-25 11:28:48 +01:00
Stephan d7cc626396 U4-1083 - proper error message on content type alias duplicate 2014-11-25 11:25:04 +01:00
Shannon e2cc342adf Removes non-completed/tested/used code for templates which was during a WIP of the grid some time ago. 2014-11-25 17:36:44 +11:00
Shannon ea785a6585 Fixes: U4-5867 Installer, no starter kit link moves when starter kit list is populated 2014-11-25 13:14:18 +11:00
Shannon 46a8e586ce Fixes: U4-5872 Using list view editor as a standard property on media type causes error 2014-11-25 12:51:55 +11:00
Shannon fa0f15f5c4 fix merge 2014-11-25 10:05:10 +11:00
Shannon 6a15c2603d Merge branch '7.1.9' into 7.2.0
Conflicts:
	src/Umbraco.Web.UI/umbraco/config/lang/da.xml
	src/Umbraco.Web.UI/umbraco/config/lang/de.xml
	src/Umbraco.Web.UI/umbraco/config/lang/en.xml
	src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
	src/Umbraco.Web.UI/umbraco/config/lang/es.xml
	src/Umbraco.Web.UI/umbraco/config/lang/fr.xml
	src/Umbraco.Web.UI/umbraco/config/lang/he.xml
	src/Umbraco.Web.UI/umbraco/config/lang/it.xml
	src/Umbraco.Web.UI/umbraco/config/lang/ja.xml
	src/Umbraco.Web.UI/umbraco/config/lang/ko.xml
	src/Umbraco.Web.UI/umbraco/config/lang/nl.xml
	src/Umbraco.Web.UI/umbraco/config/lang/no.xml
	src/Umbraco.Web.UI/umbraco/config/lang/pl.xml
	src/Umbraco.Web.UI/umbraco/config/lang/pt.xml
	src/Umbraco.Web.UI/umbraco/config/lang/ru.xml
	src/Umbraco.Web.UI/umbraco/config/lang/sv.xml
	src/Umbraco.Web.UI/umbraco/config/lang/zh.xml
	src/Umbraco.Web.UI/umbraco/create/nodeType.ascx
	src/Umbraco.Web/umbraco.presentation/umbraco/create/nodeType.ascx.cs
2014-11-25 09:59:08 +11:00
Shannon 9d50a4d2a5 Re Fixes: U4-5220 XSLT Extensions in App_Code or /bin not working in 7.1.4 - this is just a work-around fix, the real problem is the dll's in the user's bin folder. 2014-11-25 09:50:16 +11:00
Shannon 60263c9040 Re Fixes: U4-5220 XSLT Extensions in App_Code or /bin not working in 7.1.4 - this is just a work-around fix, the real problem is the dll's in the user's bin folder. 2014-11-25 09:48:54 +11:00
per ploug ba6a5825fa Fixes: U4-5742 Grid "thumbnail" property for media 2014-11-24 09:16:53 +01:00
Shannon Deminick 321e2f9de0 Merge pull request #546 from readingdancer/UmbUkFest-U4-3979
Updated the language files to fix issue #U4-3979
2014-11-24 13:12:56 +11:00
Sebastiaan Janssen 4e68380c32 Update en.xml 2014-11-23 15:12:40 +01:00
Chris Houston 9834352de2 - Added all the missing Key's to the Spanish file
- Updated the help documentation URL's
- Updated the Community Contributor URL's
2014-11-23 03:30:18 +00:00
Shannon da87ba8bc7 Merge remote-tracking branch 'origin/7.1.9' into 7.2.0
Conflicts:
	src/Umbraco.Core/Services/PackagingService.cs
2014-11-21 09:59:31 +11:00
Shannon d34255b1fc Fixes display order (U4-4347) 2014-11-21 09:49:29 +11:00
Shannon Deminick 9b6ab24890 Merge pull request #562 from tompipe/umbukfest-U4-4347
If no doctypes exist then hide Master Doc Type dropdown
2014-11-21 09:47:21 +11:00
Shannon Deminick 2341622243 Merge pull request #558 from LottePitcher/7.1.9
U4-5851
2014-11-21 09:31:02 +11:00
Shannon Deminick 956a51ab67 Merge pull request #557 from AnthonyCogworks/umbUKFest-u4-5307
Issue U4-5307 - Added umb-editor css class to allow text box stretching.
2014-11-21 09:30:14 +11:00
Shannon 0fdf69be8b Merge branch 'tompipe-umbukfest-U4-4731' into 7.2.0 2014-11-21 09:26:30 +11:00
Shannon ee040eb04f Merge branch 'umbukfest-U4-4731' of https://github.com/tompipe/Umbraco-CMS into tompipe-umbukfest-U4-4731
Conflicts:
	src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs
2014-11-21 09:25:57 +11:00
Shannon Deminick e358d3b170 Merge pull request #555 from ismailmayat/umbUKFest-906
fix for u4-906
2014-11-21 09:20:08 +11:00
Shannon Deminick 752ce55cfa Merge pull request #551 from kristianschneider/UmbUkFest-5737
Fix for U4-5737 Create package: ContentType Tab index not saved
2014-11-21 08:55:30 +11:00
Shannon Deminick d1e684cb40 Merge pull request #550 from tompipe/umbukfest-U4-5848
Reset the template when converting a doctype and the new doctype does no...
2014-11-21 08:46:16 +11:00
Shannon Deminick e6d6d3dd69 Merge pull request #545 from kristianschneider/UmbUKFest-5657
Fix for U4-5657 List view typo: "There are no items show in the list."
2014-11-21 08:19:43 +11:00
Shannon Deminick 98b41256c1 Merge pull request #547 from Alain-es/umbUkFest-U4422
Bug fix U4-4422
2014-11-21 08:18:42 +11:00
Tom Pipe bc446a63fe If no doctypes exist then hide Master Doc Type dropdown
Fixes U4-4347
2014-11-20 17:04:34 +00:00
Lotte Pitcher dca14f3eb4 U4-5851 - Typo of 'seperate' when creating new MNTP data type : changed to 'separate' 2014-11-20 15:41:06 +00:00
Anthony Dang 1abdca2432 Issue U4-5307 - Added umb-editor css class to allow text box stretching. 2014-11-20 15:22:13 +00:00
Tom Pipe 8a214b5181 Correctly translate property label and description on ALL Tabs
Fixes U4-4731
2014-11-20 15:19:58 +00:00
Ismail Mayat 6db4fedcad some reason there is double quote escape which is not needed as peta poco handles any encoding 2014-11-20 15:12:34 +00:00
Kristian Schneider 3e66235932 amendment to U4-5737 Create package: ContentType Tab index not saved to ensure that the sortorder gets updated when importing doctypes 2014-11-20 14:23:47 +00:00
Tom Pipe 91f087141b Reset the template when converting a doctype and the new doctype does not have a template assigned
Fixes U4-5848
2014-11-20 14:22:19 +00:00
Kristian Schneider 1ab321c7b1 Fix for U4-5737 Create package: ContentType Tab index not saved 2014-11-20 14:04:13 +00:00
Chris Houston dffcf10032 Fixed ticket U4-4840 invalid Italian words in the Italian language file. 2014-11-20 12:44:41 +00:00
per ploug 6265354327 Fixes grid auto-resizing fields on hidden tabs 2014-11-20 13:39:28 +01:00
Chris Houston 054033c73f Updated the language files to fix issue #U4-3979 and also corrected invalid URL's across all the language files. 2014-11-20 12:24:49 +00:00
Kristian Schneider 4fcd23d8dc Fix for U4-5657 List view typo: "There are no items show in the list." 2014-11-20 12:04:54 +00:00
Alain 86f39aee03 Bug fix U4-4422 2014-11-20 12:32:46 +01:00
per ploug 9190930f49 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-11-19 15:08:52 +01:00
per ploug 11ec43c5c1 Have grid refresh editor config automatically 2014-11-19 15:08:43 +01:00
per ploug 1b83c5c180 Fluid grid views in seperate files 2014-11-19 10:37:17 +01:00
Shannon 8a98b66cfd removes un-needed lock on data type service 2014-11-19 12:47:33 +11:00
Shannon 9638bd8bd2 Fixes: U4-5758 Unable to add pre values to checkbox/dropdown list datatype after removing previous values correctly 2014-11-19 12:37:49 +11:00
Shannon Deminick 362717c05d Merge pull request #541 from jforage/issue-U4-5758
Fix to issue U4-5758. Branched off from 7.2.0
2014-11-19 12:03:36 +11:00
Shannon 16d9b9f527 fix last failing test 2014-11-19 11:58:00 +11:00
Shannon 3ae57100c8 fix merge 2014-11-19 11:52:37 +11:00
Shannon 6d33cf6c69 Merge branch '7.1.9' into 7.2.0
Conflicts:
	src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs
2014-11-19 11:50:10 +11:00
Shannon 209ccb9ae7 removes a MoveNext() call since we're no longer dealing with xdocuments and instead xelements 2014-11-19 11:49:13 +11:00
Shannon 2850c8aa05 Fixes build and fixes how published media cache gets root nodes - if people have done this in the past it would have been horrible for site performance 2014-11-19 11:35:37 +11:00
Shannon 87a9a57e6d Fixes media tests and updates how the IPublishedContent is created from the xpath iterator 2014-11-19 11:11:14 +11:00
Shannon 3e6273d073 Fixes: U4-5768 Partial View Macro path is wrong on create 2014-11-19 11:09:45 +11:00
Shannon 8d98813440 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-11-19 10:21:19 +11:00
Shannon d0b409341e Fixes media tests and updates how the IPublishedContent is created from the xpath iterator 2014-11-19 10:21:08 +11:00
per ploug 84489f612b Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-11-18 23:41:07 +01:00
per ploug ee6c9a3b05 Updates grid render cshtml
Better single/multi section layout support
Cleaned up the templates with a helper for cleaner code
2014-11-18 23:40:53 +01:00
per ploug d12162cca5 Grid Media rendering + sets save url correct 2014-11-18 23:39:56 +01:00
Sebastiaan Janssen 1117f96597 Spellchecker performed action again.. ;) 2014-11-18 18:09:15 +01:00
per ploug d3f3e161e0 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0
Conflicts:
	src/Umbraco.Web.UI.Client/src/installer/installer.service.js
2014-11-18 17:45:23 +01:00
per ploug 90d78d1b60 Install fact, minor tweak 2014-11-18 17:43:30 +01:00
Sebastiaan Janssen 5673b1907b Grid also renders the macro, so added to that description as well 2014-11-18 17:37:13 +01:00
Sebastiaan Janssen bc9ebb24f9 Makes it clear the checkbox is for both RTE and the grid 2014-11-18 17:12:03 +01:00
Sebastiaan Janssen 084e9e00ce Fix spelling mistake in new installer fact 2014-11-18 17:07:43 +01:00
per ploug 96e4f723b1 Fixes issue with grid media without size config 2014-11-18 13:58:49 +01:00
per ploug 163a03986c force add base.cshtml 2014-11-18 13:22:56 +01:00
per ploug 7007389505 New installer fact 2014-11-18 13:14:33 +01:00
Stephan 2336905dae Merge remote-tracking branch 'origin/7.2.0' into 7.2.0 2014-11-18 13:10:20 +01:00
Stephan a2164819f5 Safe compositions for 7.2 2014-11-18 13:09:57 +01:00
Morten Christensen 6b345bfc75 Ignoring *_Without_Examine tests which seem to cause eternal loop. 2014-11-18 12:41:22 +01:00
Morten Christensen a699f32178 Correcting invalid tests related to Compositions 2014-11-18 12:40:31 +01:00
Stephan e597886d0f Merge remote-tracking branch 'origin/7.2.0' into 7.2.0 2014-11-18 10:32:28 +01:00
Stephan 10e53de029 Safe compositions for 7.2 2014-11-18 10:29:46 +01:00
Shannon Deminick c9336ba32f Merge pull request #520 from Jeavon/U4-5698
Fix for U4-5698 - EntityService.GetObjectType throws for deleted Id's
2014-11-18 17:15:12 +11:00
Shannon 55190b7318 Fixes: U4-5707 Cannot upgrade 6.2.2 site to 7.2 2014-11-18 15:59:15 +11:00
Shannon 0328ba1aec Working on U4-5707 Cannot upgrade 6.2.2 site to 7.2 2014-11-18 15:06:27 +11:00
Shannon 1accc6275a Updates how the validation works in the member model mapper to use the native validation stuff instead of custom pre-values. 2014-11-18 14:32:51 +11:00
Shannon Deminick ce80c9a244 Merge pull request #540 from AndyButland/u4-5619
U4-5619 - Applied required setting for text field client-side validation to handle both native and custom properties
2014-11-18 14:22:25 +11:00
Shannon 2d9bd394ae Updates the codemirror plugin for tinymce so that it uses it's own alias: codemirror, so the code and codemirror plugins can be enabled individually. 2014-11-18 14:06:43 +11:00
Shannon b3c291206a Merge branch '7.1.9' into 7.2.0 2014-11-18 12:23:51 +11:00
Shannon f3f6504398 Working on: U4-5711 Media cache valueDictionary exception 2014-11-18 12:23:32 +11:00
Shannon 52629f829d Working on: U4-5711 Media cache valueDictionary exception 2014-11-18 12:05:03 +11:00
Shannon 3496c5aece Fix merge issue 2014-11-18 11:08:14 +11:00
Shannon 613f56107d Merge branch '7.1.9' into 7.2.0
Conflicts:
	src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
2014-11-18 10:52:50 +11:00
Shannon c47d59a257 Fixes: U4-5820 List View showing content of complete site after deleting last page of data 2014-11-18 10:50:56 +11:00
Shannon 8fe0e4223b fixes media service paged query so recycle bin works properly 2014-11-18 10:13:21 +11:00
per ploug 9abda14530 fixes U4-5541 Update copy for tag property editor to clearly state to press 'enter' after entering a tag
Instead of requiring enter to save, it will also add tags on blur so
entered data isnt lost
2014-11-18 00:08:16 +01:00
Shannon Deminick 9df2979d7d Merge pull request #539 from AndyButland/u4-5757
U4-5757 - Recycle bin list view issue
2014-11-18 10:07:55 +11:00
Shannon f4a81bfc04 Fixes: U4-5822 Can't create my own implementation of a PropertyvalueConverter for MacroContainer 2014-11-18 09:44:40 +11:00
Shannon bff7aba778 updates naming conventions in csproj 2014-11-18 09:41:02 +11:00
Shannon Deminick ade7278724 Merge pull request #542 from OrbintSoft/7.2.0
Fix to :
2014-11-18 09:15:05 +11:00
Stefano Balzarotti f5835baa27 Fix to :
http://issues.umbraco.org/issue/U4-5475
http://our.umbraco.org/forum/getting-started/installing-umbraco/56540-Could-not-install-packages
http://our.umbraco.org/forum/getting-started/installing-umbraco/57035-Installing-Package-Error-invalid-search
http://issues.umbraco.org/issue/U4-5571

Ecc...

This is only  a temporary workaround, because this is a stupid way of parsing a URI!!
1) It's not a real parsing, it uses browser DOM API with correlated compability problems (Invalid Protocol in Internet Explorer)
2) Check the validity of url clientside is useless...
2014-11-17 23:00:43 +01:00
per ploug d7f6bd0d20 Missing grid cshtml file in csproj 2014-11-17 22:35:41 +01:00
per ploug d92e5ca2e3 Fixes U4-5586 HTML in property descriptions is not supported in v7 2014-11-17 22:31:57 +01:00
per ploug 94465892ed Adds radiobuttonlist prevalue editor 2014-11-17 22:23:03 +01:00
per ploug 4b59caf18f PR from andy butland manually added
Adds Pixes unit to rte config field, close buttons to grid config
dialogs
2014-11-17 22:23:00 +01:00
Per Ploug a0994ff105 Merge pull request #538 from AndyButland/u4-5608
U4-5608 - fixed styling issue with embedded items in grid
2014-11-17 21:39:54 +01:00
per ploug 9b3a7b8abc Allows the grid to crop images 2014-11-17 21:24:54 +01:00
per ploug bb93f0a4a2 Fixes U4-5723 Only enable macros allowed in RTE in grid 2014-11-17 21:24:52 +01:00
per ploug 3c8be919da Fixes U4-5824 Grid editor lacks localized labels 2014-11-17 21:24:51 +01:00
per ploug 168893a888 Fixes issues with image directives
Didnt work properly outside property editor
2014-11-17 21:24:46 +01:00
jforage eb4076399e Fix to issue U4-5758. Branched off from 7.2.0 2014-11-17 13:24:58 +00:00
Shannon d61d6008da Adds internal event for when a package is installed which gives access to the InstalledPackage instance which contains a PackageInstance reference that contains all of the files installed in the package 2014-11-17 18:00:51 +11:00
AndyButland 47a78c1bcb Applied required setting for text field client-side validation to handle both native and custom properties 2014-11-16 23:53:36 +01:00
AndyButland dfdf85fc0b Fixed filter that was returning all nodes for list view display of recycle bin 2014-11-16 22:12:21 +01:00
AndyButland 8862b99e6a Added css style to ensure embedded items don't take up more width than the column they are within when editing 2014-11-16 21:44:08 +01:00
Sebastiaan Janssen a1a1b9ebb5 Merge branch '7.1.9' into 7.2.0 2014-11-15 14:19:51 +01:00
Sebastiaan Janssen 403f64eeed Only set comment to blank if there's command line arguments 2014-11-15 14:19:26 +01:00
Sebastiaan Janssen 5a26a52157 Merge branch '7.1.9' into 7.2.0
Conflicts:
	build/Build.bat
	build/UmbracoVersion.txt
2014-11-15 14:18:34 +01:00
Sebastiaan Janssen 5aa29cc150 Adds version comment to UmbracoVersion.txt and makes it possible to overrule by adding arguments to build.bat 2014-11-15 14:04:19 +01:00
Sebastiaan Janssen 9be3bdb8a5 Makes sure that the very first build on a fresh machine works immediately (previously you'd get an error saying that some NuGet packages were restored and you need to run the build again). 2014-11-15 13:14:40 +01:00
Sebastiaan Janssen c0baac2b38 Should fix the build for real now. Sets GenerateSerializationAssemblies to Off which then doesn't produce umbraco.XmlSerializers.dll any more.
Should be safe as this is only used for updatechecker and packageinstaller. From:  http://hashtagfail.com/post/5255977780/sgen-loaderexceptions-error - "Visual Studio attempts to generate a serialization assembly containing the types in your solution, to improve XmlSerializer serialization performance, should you choose to serialize your types."

Conflicts:
	build/NuSpecs/tools/install.core.ps1
2014-11-15 12:38:28 +01:00
Sebastiaan Janssen 31903c8ead Merge pull request #536 from yannisgu/fixDotLess
Fix dotless reference in csproj
2014-11-14 17:17:21 +01:00
Sebastiaan Janssen e59b14b7e7 Makes sure that the very first build on a fresh machine works immediately (previously you'd get an error saying that some NuGet packages were restored and you need to run the build again). 2014-11-14 17:16:33 +01:00
Sebastiaan Janssen cb869b9064 Merge branch '7.1.9' into 7.2.0
Conflicts:
	build/Build.bat
2014-11-14 16:53:34 +01:00
Sebastiaan Janssen b20fc22577 U4-5814 Apply MVC 4.0.0.1 security update 2014-11-14 16:51:51 +01:00
yannisgu df0c297f55 Fix dotless reference in csproj
In the packages.config the version 1.4.1 of dotless is referenced while in the csproj the version 1.4.0 was referenced.
2014-11-14 11:16:20 +01:00
Stephan e36dc368d9 U4-5802 - fix Ancestor<T>, AncestorOrSelf<T> + document 2014-11-14 10:27:57 +01:00
antoine 656ba98b1b U4-5793 prevent drag element off screen vertically 2014-11-13 21:29:18 +01:00
per ploug 5c17201006 Fixes custom grid view lookup 2014-11-13 15:42:36 +01:00
per ploug d86a1946a7 Filter grid cell and row settings
Settings and styles can now be specifically applied to a cell or a row,
by default on both
2014-11-13 10:58:42 +01:00
per ploug 18bf4a87b4 Grid component editors should only open on insert 2014-11-13 10:57:51 +01:00
per ploug 91475c7103 Fixes the bottom floating buttons
On datatype editor buttons floated randomly at the bottom
2014-11-13 09:22:54 +01:00
per ploug 88934a3f14 Darkens the grid layout editor 2014-11-13 09:22:49 +01:00
per ploug 80b5c99111 Sanitizes empty grid items 2014-11-13 09:22:47 +01:00
Shannon 658a045168 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-11-13 18:07:10 +11:00
Shannon ccd438ba26 Fixes: U4-5801 macro container property needs to be type TEXT 2014-11-13 18:06:58 +11:00
per ploug 71863f8ba1 Sets a horizontal overflow on grid cells
To avoid that cell editors go beyond the cell horizontally
2014-11-13 07:52:19 +01:00
Shannon 6df6e3bdad Fixes: U4-3737 macro container make sure you can define the allowed macros + the max number 2014-11-13 17:44:03 +11:00
Shannon 9019c49ee8 Merge branch '7.1.9' into 7.2.0
Conflicts:
	build/NuSpecs/UmbracoCms.Core.nuspec
	build/UmbracoVersion.txt
	src/Umbraco.Core/Configuration/UmbracoVersion.cs
	src/Umbraco.Core/Sync/ServerEnvironmentHelper.cs
	src/Umbraco.Tests/Plugins/PluginManagerTests.cs
	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
	src/Umbraco.Web/Scheduling/KeepAlive.cs
	src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
	src/Umbraco.Web/Trees/ApplicationTreeRegistrar.cs
	src/UmbracoExamine/BaseUmbracoIndexer.cs
	src/UmbracoExamine/DataServices/UmbracoContentService.cs
	src/UmbracoExamine/DataServices/UmbracoMediaService.cs
	src/UmbracoExamine/UmbracoContentIndexer.cs
	src/UmbracoExamine/UmbracoMemberIndexer.cs
2014-11-13 16:32:50 +11:00
Shannon 74ebf67aef updates the local storage sync, simplifies options and does more error checking in case sync cannot occur - which will default to normal storage. 2014-11-13 15:49:34 +11:00
Shannon 33036f80fe Fixes: U4-5789 Add native option to UmbracoExamine library to run the indexes locally 2014-11-13 14:01:13 +11:00
Shannon 0688550143 start integrating the local templ storage option for examine 2014-11-13 13:09:29 +11:00
Shannon d43b673092 Merge branch '7.1.9' of https://github.com/umbraco/Umbraco-CMS into 7.1.9 2014-11-13 13:06:53 +11:00
Shannon 4ec37b9d3a Fixes: U4-5391 Create config to explicitly set the 'base url' for a website that is not running as a load balanced site - used for scheduled tasks/publishing/keepalive 2014-11-13 13:05:27 +11:00
Shannon Deminick a5240a852e Merge pull request #527 from designagencytom/patch-4
Flip ternary to prevent defaults being overridden from false to true.
2014-11-13 10:46:58 +11:00
Shannon Deminick c74c269b9a Merge pull request #535 from zpqrtbnk/7.2.0-wherein
Add WhereIn PetaPoco Sql Extension
2014-11-13 09:35:00 +11:00
per ploug 0cbdebc9b0 Merge remote-tracking branch 'origin/7.2.0' into 7.2.0
Conflicts:

	src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.html
2014-11-12 15:44:11 +01:00
per ploug 4f655acda5 Splits the grid layout config into 3 2014-11-12 15:37:23 +01:00
Stephan 0cb396825f Add WhereIn PetaPoco Sql Extension 2014-11-12 14:42:03 +01:00
Sebastiaan Janssen 4eb0981552 Bump version 2014-11-12 14:28:13 +01:00
antoine 4257a89cc1 U4-5793 The three icons (delete, move, settings) seems to fail to appear if the cursor is coming from inside the row. I need to move the cursor out of the row entirely and then back in. Seems like a bug to me. 2014-11-12 14:14:02 +01:00
antoine 7300316780 grid add button always centered 2014-11-12 14:14:00 +01:00
antoine 94da555fea Some styles unification for the grid's prevalues 2014-11-12 14:13:57 +01:00
Sebastiaan Janssen ed8cc2ad0d Also fixes U4-5592 and U4-5746 for 7.1.9 2014-11-12 12:40:24 +01:00
Sebastiaan Janssen ae47ad882d #U4-5592 Fixed, Due in version 7.2.0
#U4-5746 Fixed, Due in version 7.2.0
Note: dotless is required for the artist formerly known as tuning
2014-11-12 10:40:31 +01:00
Shannon 10bc7d0c1e Makes the section scanning and loading from the xml lazy so this no longer happens on startup but instead when sections are required, this ensures during startup there is no IO or scanning for sections, this should assist with U4-5126 config files get cleared out with zero size and of course also help a bunch with startup time. 2014-11-12 18:32:51 +11:00
Shannon aa11d3504d Makes the tree scanning and loading from the xml lazy so this no longer happens on startup but instead when trees are required, this ensures during startup there is no IO or scanning for trees, this should assist with U4-5126 config files get cleared out with zero size and of course also help a bunch with startup time. 2014-11-12 18:06:10 +11:00
Shannon 6903ebda1f even slightly better locking 2014-11-12 16:45:36 +11:00
Shannon 6c6e398c53 Fixes locking check on tree collection, will speed things up a little 2014-11-12 16:36:08 +11:00
Shannon bccb9655d0 Fixes: U4-5715 On startup when detecting if the db is configured we need to ensure it can also be connected to 2014-11-12 16:30:01 +11:00
Shannon dd143681f1 By default, changes all log output for NH to be Warn 2014-11-12 16:02:02 +11:00
Shannon b1d4a99510 U4-5728 - Do not run KeepAlive, ScheduledPublishing, without an url
Updates the scheduler and the scheduled tasks to use a background task runner (ported from new courier codebase with tests) so that they are web aware and wind down properly.
2014-11-12 16:00:17 +11:00
Shannon 79d9412b31 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-11-12 10:05:28 +11:00
Shannon f6c39362cd reverts codemirror tinymce editor from release until we can fix the IE issue with it, people can still enable it if they want though. 2014-11-12 10:05:20 +11:00
Shannon Deminick 48fb2a2fcc Merge pull request #534 from kipusoep/Textbox-trimming-disabled
Disabled trimming (U4-5603)
2014-11-12 09:09:59 +11:00
antoine 4562237a96 U4-5778 Grid: Not all of the add-circle/button is clickable 2014-11-11 22:04:30 +01:00
antoine 3420694cca Some grid view css adjustments 2014-11-11 21:56:25 +01:00
antoine c68067eb09 highlight area for setting, not control. 2014-11-11 21:27:38 +01:00
antoine a8c73296ea Right info and warm highlight for rows' and controls' options (remove, move and setting) 2014-11-11 20:58:35 +01:00
Stefan Kip 805c1bf8d0 Disabled trimming
Set ngTrim to false.
2014-11-11 13:59:09 +01:00
Shannon 15119fc8d0 removes other refs to $scope.cfg, this is never necessary 2014-11-11 18:03:37 +11:00
Shannon Deminick e2f8a73561 Merge pull request #528 from robertjf/7.2.0
Fixes issue U4-5754 Attempt to set start node on Media Picker sends user...
2014-11-11 17:57:26 +11:00
Shannon 4d9f6ccd22 Fixes: U4-5780 RenderActionInvoker needs a perf fix with caching when it's using reflection 2014-11-11 17:52:40 +11:00
Sebastiaan Janssen 9112c05477 Merge pull request #531 from Jeavon/GridCodeStandards
A few small tweaks to the C# part of the Grid editor for coding standard...
2014-11-10 15:46:50 +01:00
Jeavon Leopold c0c624d62e A few small tweaks to the C# part of the Grid editor for coding standards 2014-11-10 14:43:43 +00:00
per ploug 306a30265e Remove ace from bower and directives folder 2014-11-10 13:36:57 +01:00
per ploug 1ee6fc8514 Update build.bat to beta2 2014-11-10 13:33:42 +01:00
Rune Hem Strand 1003ac42df Grid template preview
New template preview for content section
2014-11-10 12:17:39 +01:00
Robert Foster ca951aa56b Fix for issue U4-5755 Issue: Multiple mixins with same tab cause content node edit crash 2014-11-08 01:13:17 +11:00
Robert Foster 6ea7b32363 Fixes issue U4-5754 Attempt to set start node on Media Picker sends user to Content section 2014-11-08 00:57:37 +11:00
Per Ploug Krogslund db4495cf50 Grid mock data and modified tests
all client side changes, will not affect live sites
2014-11-07 11:13:28 +01:00
designagencytom c35fa7c975 Flip ternary to prevent defaults being overridden from false to true. 2014-11-07 09:43:46 +00:00
per ploug ed8cccdf5a Minor visual annoyances + changed output html
changes made due to feedback from Adam, Rune and Simon on how to make
the grid as flexible as possible
2014-11-06 22:58:35 +01:00
per ploug 9cd8ce5626 Grid layout changes to support breaking rows 2014-11-06 14:13:27 +01:00
per ploug 990f271c63 Merge 2014-11-05 20:10:06 +01:00
per ploug adfdbaec46 Adds support for grid row configuration and styling 2014-11-05 15:44:29 +01:00
Stephan 0f4436a465 U4-5728 - Do not run KeepAlive, ScheduledPublishing, without an url 2014-11-03 20:20:10 +01:00
Sebastiaan Janssen 8ccbf70b39 Making sure lower-case "Change password" is also removed 2014-11-03 18:05:12 +01:00
antoine ddd26f3ad4 Move/remove row button hover wasn't correct, point on control's methods instead of row's 2014-11-03 14:04:59 +01:00
Sebastiaan Janssen 316e7531a0 #U4-5738 Fixed Due in version 7.2.0
Umbraco 7.2 installation via NuGet fails
2014-11-03 13:13:23 +01:00
Shannon Deminick 0f068f5fb1 Merge pull request #524 from Odie20XX/patch-1
Update MembershipHelper.cs
2014-11-01 05:53:52 +10:00
antoine 8f6b76f9fc U4-5730 7.2.0 Grid - edit parameters of macro added into grid content 2014-10-31 16:29:22 +01:00
Odie20XX 468c281d7d Update MembershipHelper.cs
The parameter "logMemberIn" wasn't used so setting "LoginOnSuccess" on the RegisterModel didn't have any effect. By checking the parameter you can disable automatically logging in the user after registration. If registration failed, it would have returned null in an earlier stage so it's safe to say registration succeeded at this point.
2014-10-31 15:30:20 +01:00
Jeavon Leopold 419531f373 Fix for U4-5698 - using method logic from NPoco as it works :) 2014-10-31 13:29:03 +00:00
Jeavon Leopold 3457768646 Merge branch '7.2.0' into U4-5698 2014-10-31 12:31:06 +00:00
Antoine Giraud f7cb188210 Merge pull request #522 from arknu/U4-5638-grid-prevalue-editor
U4-5638: Replace style with ng-style to ensure styling is applied in IE
2014-10-31 12:55:18 +01:00
antoine 00518d0de7 Add the startNodeId option for the grid media editor 2014-10-31 09:59:13 +01:00
Sebastiaan Janssen 892a8d2a8a Update gruntFile.js 2014-10-30 10:12:43 +01:00
arknu ced6c011aa U4-5638: Also replace style with ng-style in the property editor 2014-10-29 15:25:59 +01:00
arknu efc2008783 U4-5638: Replace style with ng-style to ensure styling is applied in IE 2014-10-29 12:58:38 +01:00
Shannon acb987a451 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-10-29 18:20:10 +10:00
Shannon 4a1ea6e2d8 Fixes: U4-5710 UmbracoVirtualNodeRouteHandler does not allow for SurfaceController forms 2014-10-29 18:20:01 +10:00
Antoine Giraud cc23d57803 Merge pull request #521 from enricleon/7.2.0
Add new colorpicker directive to the canvasdesigner to improve reusability into the canvasdesigner editors
2014-10-29 09:18:32 +01:00
Enric León 81fdae3dc4 Change spectrumpicker to colorpicker in all editors 2014-10-28 16:27:04 +01:00
Enric León 2859eb560c Add new directive colorpicker that wraps spectrumpicker into a dialog 2014-10-28 16:27:03 +01:00
Sebastiaan Janssen 7c5ad67a9f Update to config transform adding a <remove /> too late and assembly bindings not transforming correctly 2014-10-28 14:41:52 +01:00
Jeavon Leopold 69c3962f21 Fix for U4-5698 - EntityService.GetObjectType throws for deleted Id's 2014-10-28 08:46:07 +00:00
Sebastiaan Janssen 6c2750b0cc Moves fix for VS14 to the SqlCEHelper class itself, InternalsVisibleTo didn't seem to work in VS (worked on command line build though) 2014-10-24 10:32:41 +02:00
Sebastiaan Janssen abc672e348 Fixes VS14 build. SqlCEHelper.cs - the compiler in Vs14 doesn't like that we're callng public IRecordsReader ExecuteReader(string commandText, params IParameter[] parameters) like this: ExecuteNonQuery("alter table [" + table + "] drop constraint [" + constraint + "]");
Added two internal method overloads that just send an empty parameter array instead.
2014-10-23 17:52:14 +02:00
307 changed files with 15954 additions and 5031 deletions
+1
View File
@@ -128,3 +128,4 @@ src/*.boltdata/
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.config.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.front.js
src/umbraco.sln.ide/*
build/UmbracoCms.*/
+29 -15
View File
@@ -2,9 +2,18 @@
IF NOT EXIST UmbracoVersion.txt (
ECHO UmbracoVersion.txt missing!
GOTO :showerror
)
SET /p release=<UmbracoVersion.txt
SET comment=beta
)
REM Get the version and comment from UmbracoVersion.txt lines 2 and 3
SET "release="
SET "comment="
FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i"
FOR /F "skip=2 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED comment SET "comment=%%i"
REM If there's arguments on the command line overrule UmbracoVersion.txt and use that as the version
IF [%1] NEQ [] (SET release=%1)
IF [%2] NEQ [] (SET comment=%2) ELSE (IF [%1] NEQ [] (SET "comment="))
SET version=%release%
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
@@ -14,8 +23,11 @@ ReplaceIISExpressPortNumber.exe ..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj %rel
ECHO Installing the Microsoft.Bcl.Build package before anything else, otherwise you'd have to run build.cmd twice
SET nuGetFolder=%CD%\..\src\packages\
..\src\.nuget\NuGet.exe sources Remove -Name MyGetUmbracoCore
..\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%
..\src\.nuget\NuGet.exe install ..\src\umbraco.businesslogic\packages.config -OutputDirectory %nuGetFolder%
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Core\packages.config -OutputDirectory %nuGetFolder%
ECHO Removing the belle build folder to make sure everything is clean as a whistle
RD ..\src\Umbraco.Web.UI.Client\build /Q /S
@@ -33,20 +45,22 @@ ECHO Performing MSBuild and producing Umbraco binaries zip files
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment%
ECHO Adding dummy files to include in the NuGet package so that empty folders actually get created
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Code\dummy.txt
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Data\dummy.txt
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Plugins\dummy.txt
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\css\dummy.txt
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\masterpages\dummy.txt
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\media\dummy.txt
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\scripts\dummy.txt
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\usercontrols\dummy.txt
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\Views\Partials\dummy.txt
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\Views\MacroPartials\dummy.txt
SET dummytext=This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete.
ECHO %dummytext% > .\_BuildOutput\WebApp\App_Code\dummy.txt
ECHO %dummytext% > .\_BuildOutput\WebApp\App_Data\dummy.txt
ECHO %dummytext% > .\_BuildOutput\WebApp\App_Plugins\dummy.txt
ECHO %dummytext% > .\_BuildOutput\WebApp\css\dummy.txt
ECHO %dummytext% > .\_BuildOutput\WebApp\masterpages\dummy.txt
ECHO %dummytext% > .\_BuildOutput\WebApp\media\dummy.txt
ECHO %dummytext% > .\_BuildOutput\WebApp\scripts\dummy.txt
ECHO %dummytext% > .\_BuildOutput\WebApp\usercontrols\dummy.txt
ECHO %dummytext% > .\_BuildOutput\WebApp\Views\Partials\dummy.txt
ECHO %dummytext% > .\_BuildOutput\WebApp\Views\MacroPartials\dummy.txt
ECHO Adding Web.config transform files to the NuGet package
ren .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
ren .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
REN .\_BuildOutput\WebApp\MacroScripts\Web.config Web.config.transform
REN .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
REN .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
ECHO Packing the NuGet release files
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version%
+2 -2
View File
@@ -156,8 +156,8 @@
<Target Name="ZipWebApp" DependsOnTargets="ZipUmbracoExaminePDF" >
<Message Text="Starting to zip to $(buildDate)-$(BuildZipFileName)" Importance="high" />
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameBin)%22 %22$(SolutionBinFolderAbsolutePath)*%22" />
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileName)%22 %22$(WebAppFolderAbsolutePath)*%22" />
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameBin)%22 %22$(SolutionBinFolderAbsolutePath)*%22 -x!dotLess.Core.dll" />
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileName)%22 %22$(WebAppFolderAbsolutePath)*%22 -x!dotLess.Core.dll" />
<Message Text="Finished zipping to build\$(BuildFolder)\$(buildDate)-$(BuildZipFileName)" Importance="high" />
</Target>
+3 -3
View File
@@ -15,7 +15,7 @@
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="Microsoft.AspNet.Mvc" version="[4.0.40804.0,5.0.0)" />
<dependency id="Microsoft.AspNet.Mvc" version="[4.0.30506.0,5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi" version="[4.0.30506,5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.WebHost" version="[4.0.30506, 5.0.0)" />
<dependency id="Microsoft.AspNet.WebApi.Core" version="[4.0.30506, 5.0.0)" />
@@ -33,8 +33,8 @@
<dependency id="AutoMapper" version="[3.0.0, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.5, 7.0.0)" />
<dependency id="Examine" version="[0.1.57, 1.0.0)" />
<dependency id="ImageProcessor" version="[1.9.5, 2.0.0)" />
<dependency id="ImageProcessor.Web" version="[3.3.1, 4.0.0)" />
<dependency id="ImageProcessor" version="[1.9.5, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[3.3.1, 5.0.0)" />
</dependencies>
</metadata>
<files>
@@ -26,11 +26,15 @@
views/dashboard/developer/developerdashboardvideos.html
</control>
</tab>
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
</section>
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)">
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
<control>
views/dashboard/developer/examinemanagement.html
</control>
</tab>
</tab>
</section>
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)">
@@ -53,6 +57,7 @@
views/dashboard/default/startupdashboardintro.html
</control>
</tab>
<tab caption="Change password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Change Password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Change Password" xdt:Transform="Insert">
<control showOnce="false" addPanel="false" panelCaption="">
+10 -12
View File
@@ -2,24 +2,22 @@ A note about running Umbraco from Visual Studio.
Don't forget to build!
BETA Notice: We've done our best to transform your config files, we are testing this in 7.2 beta and would love to
hear back if it didn't work so we can improve this feature. We'd love to see your before and after config files
(make sure to delete sensitive data like passwords and API keys) in the issue tracker at http://issues.umbraco.org/
Remember, we backed up your files in App_Data\NuGetBackup so you can find the original file before it was transformed.
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
file (and config files in the config folder).
We've overwritten all the files in the Umbraco and Umbraco_Client folder, these have been backed up in
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or a package
might have added. Only the existing files were overwritten. If you customized anything then make sure to do a compare
and merge with the NuGetBackup folder.
We've done our best to transform your configuration files but in case something is not quite right: remember we
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
This nuget package includes build targets that extends the creation of a deploy package, which is generated by
We've overwritten all the files in the Umbraco and Umbraco_Client folder, these have been backed up in
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or
a package might have added. Only the existing files were overwritten. If you customized anything then make
sure to do a compare and merge with the NuGetBackup folder.
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
Publish this won't affect you.
These things will now be automatically included when creating a deploy package or publishing to the file system:
umbraco, umbraco_client, config\splashes and global.asax.
The following items will now be automatically included when creating a deploy package or publishing to the file
system: umbraco, umbraco_client, config\splashes and global.asax.
Please read the release notes on our.umbraco.org:
http://our.umbraco.org/contribute/releases
+38 -21
View File
@@ -6,7 +6,9 @@
<section name="FileSystemProviders" xdt:Locator="Match(name)" xdt:Transform="Remove" />
<section name="ExamineLuceneIndexSets" type="Examine.LuceneEngine.Config.IndexSets, Examine" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type,requirePermission)" />
<sectionGroup name="applicationSettings" xdt:Locator="Match(name)" xdt:Transform="Remove" />
<sectionGroup name="applicationSettings" xdt:Locator="Match(name)">
<section name="umbraco.presentation.Properties.Settings" xdt:Locator="Match(name)" xdt:Transform="Remove" />
</sectionGroup>
<sectionGroup name="system.web.webPages.razor" xdt:Locator="Match(name)" xdt:Transform="Remove" />
<sectionGroup name="umbracoConfiguration" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing">
<section name="settings" type="Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
@@ -52,8 +54,6 @@
<compilation>
<assemblies xdt:Transform="InsertIfMissing" />
<assemblies>
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)"
xdt:Transform="InsertIfMissing" />
<add assembly="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
@@ -71,6 +71,13 @@
</assemblies>
</compilation>
<compilation>
<assemblies>
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
</assemblies>
</compilation>
<xhtmlConformance xdt:Transform="Remove" />
<httpModules xdt:Transform="InsertIfMissing" />
@@ -126,38 +133,48 @@
<runtime xdt:Transform="InsertIfMissing" />
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" xdt:Transform="SetAttributes()">
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="InsertIfMissing">
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
</dependentAssembly>
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="InsertIfMissing">
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="InsertIfMissing">
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.1" />
</dependentAssembly>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" xdt:Transform="InsertIfMissing" />
</runtime>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<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" />
</assemblyBinding>
</runtime>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="Replace">
<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"/>
</dependentAssembly>
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="Replace">
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="Replace">
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.1" />
</dependentAssembly>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web.webPages.razor xdt:Transform="Remove" />
<location path="umbraco" xdt:Locator="Match(path)" xdt:Transform="InsertIfMissing" />
<location path="umbraco" xdt:Locator="Match(path)">
<system.webServer xdt:Transform="InsertIfMissing">
<urlCompression doStaticCompression="false" doDynamicCompression="false" dynamicCompressionBeforeCache="false" xdt:Transform="SetAttributes(doStaticCompression,doDynamicCompression,dynamicCompressionBeforeCache)" />
</system.webServer>
</location>
<location path="App_Plugins" xdt:Locator="Match(path)" xdt:Transform="InsertIfMissing" />
<location path="App_Plugins" xdt:Locator="Match(path)">
<system.webServer xdt:Transform="InsertIfMissing">
<urlCompression doStaticCompression="false" doDynamicCompression="false" dynamicCompressionBeforeCache="false" xdt:Transform="SetAttributes(doStaticCompression,doDynamicCompression,dynamicCompressionBeforeCache)" />
</system.webServer>
</location>
</configuration>
+4 -8
View File
@@ -63,8 +63,7 @@ if ($project) {
$consoleWindow = $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow])
$props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
$props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
$prop = $props | ? { $_.Name -eq "ActiveHostInfo" } | select -first 1
if ($prop -eq $null) { return }
@@ -91,10 +90,8 @@ if ($project) {
# get reference to the window, then smart output console provider
# copy web.config if messages in buffered console contains "installing...UmbracoCms" in last operation
$instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor `
[System.Reflection.BindingFlags]::NonPublic)
$consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
$instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::NonPublic)
$consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
if ($instanceField -eq $null -or $consoleField -eq $null) { return }
$instance = $instanceField.GetValue($null)
@@ -105,8 +102,7 @@ if ($project) {
$console = $consoleProvider.CreateOutputConsole($false)
$messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
$messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
if ($messagesField -eq $null) { return }
$messages = $messagesField.GetValue($console)
+2 -1
View File
@@ -1 +1,2 @@
7.2.0
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.2.1
+12
View File
@@ -229,5 +229,17 @@ namespace SqlCE4Umbraco
return new SqlCeDataReaderHelper(SqlCeApplicationBlock.ExecuteReader(ConnectionString, CommandType.Text,
commandText, parameters));
}
internal IRecordsReader ExecuteReader(string commandText)
{
return ExecuteReader(commandText, new SqlCEParameter(string.Empty, string.Empty));
}
internal int ExecuteNonQuery(string commandText)
{
return ExecuteNonQuery(commandText, new SqlCEParameter(string.Empty, string.Empty));
}
}
}
+1 -1
View File
@@ -8,7 +8,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+2 -2
View File
@@ -74,7 +74,7 @@ namespace Umbraco.Core
/// <returns></returns>
private bool ShouldExecute(ApplicationContext applicationContext)
{
if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured)
if (applicationContext.IsConfigured && applicationContext.DatabaseContext.CanConnect)
{
return true;
}
@@ -84,7 +84,7 @@ namespace Umbraco.Core
return true;
}
if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured)
if (!applicationContext.DatabaseContext.CanConnect && ExecuteWhenDatabaseNotConfigured)
{
return true;
}
@@ -5,5 +5,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
public interface IScheduledTasksSection : IUmbracoConfigurationSection
{
IEnumerable<IScheduledTask> Tasks { get; }
string BaseUrl { get; }
}
}
@@ -16,5 +16,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return Tasks; }
}
[ConfigurationProperty("baseUrl", IsRequired = false, DefaultValue = null)]
public string BaseUrl
{
get { return (string)base["baseUrl"]; }
}
}
}
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.2.0");
private static readonly Version Version = new Version("7.2.1");
/// <summary>
/// Gets the current version of Umbraco.
@@ -23,7 +23,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 "beta"; } }
public static string CurrentComment { get { return ""; } }
// 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
+29
View File
@@ -26,6 +26,9 @@ namespace Umbraco.Core
{
private readonly IDatabaseFactory _factory;
private bool _configured;
private bool _canConnect;
private volatile bool _connectCheck = false;
private readonly object _locker = new object();
private string _connectionString;
private string _providerName;
private DatabaseSchemaResult _result;
@@ -56,6 +59,32 @@ namespace Umbraco.Core
get { return _configured; }
}
/// <summary>
/// Determines if the db can be connected to
/// </summary>
public bool CanConnect
{
get
{
if (IsDatabaseConfigured == false) return false;
//double check lock so that it is only checked once and is fast
if (_connectCheck == false)
{
lock (_locker)
{
if (_canConnect == false)
{
_canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider);
_connectCheck = true;
}
}
}
return _canConnect;
}
}
/// <summary>
/// Gets the configured umbraco db connection string.
/// </summary>
+1 -1
View File
@@ -8,7 +8,7 @@ namespace Umbraco.Core
/// <summary>
/// Helper class for mandating values, for example on method parameters.
/// </summary>
internal static class Mandate
public static class Mandate
{
/// <summary>
/// Mandates that the specified parameter is not null.
+22 -10
View File
@@ -15,11 +15,11 @@ namespace Umbraco.Core.Models
{
private int _defaultTemplate;
private IEnumerable<ITemplate> _allowedTemplates;
/// <summary>
/// Constuctor for creating a ContentType with the parent's id.
/// </summary>
/// <remarks>You usually only want to use this for creating ContentTypes at the root.</remarks>
/// <remarks>Only use this for creating ContentTypes at the root (with ParentId -1).</remarks>
/// <param name="parentId"></param>
public ContentType(int parentId) : base(parentId)
{
@@ -31,14 +31,26 @@ namespace Umbraco.Core.Models
/// </summary>
/// <remarks>Use this to ensure inheritance from parent.</remarks>
/// <param name="parent"></param>
public ContentType(IContentType parent) : base(parent)
{
_allowedTemplates = new List<ITemplate>();
}
[Obsolete("This method is obsolete, use ContentType(IContentType parent, string alias) instead.", false)]
public ContentType(IContentType parent) : this(parent, null)
{
}
/// <summary>
/// Constuctor for creating a ContentType with the parent as an inherited type.
/// </summary>
/// <remarks>Use this to ensure inheritance from parent.</remarks>
/// <param name="parent"></param>
/// <param name="alias"></param>
public ContentType(IContentType parent, string alias)
: base(parent, alias)
{
_allowedTemplates = new List<ITemplate>();
}
private static readonly PropertyInfo DefaultTemplateSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.DefaultTemplateId);
private static readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo<ContentType, IEnumerable<ITemplate>>(x => x.AllowedTemplates);
/// <summary>
/// Gets or sets the alias of the default Template.
/// </summary>
@@ -95,7 +107,7 @@ namespace Umbraco.Core.Models
}
DefaultTemplateId = template.Id;
if(_allowedTemplates.Any(x => x != null && x.Id == template.Id) == false)
if (_allowedTemplates.Any(x => x != null && x.Id == template.Id) == false)
{
var templates = AllowedTemplates.ToList();
templates.Add(template);
@@ -129,7 +141,7 @@ namespace Umbraco.Core.Models
{
base.AddingEntity();
if(Key == Guid.Empty)
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
@@ -140,7 +152,7 @@ namespace Umbraco.Core.Models
/// <returns></returns>
[Obsolete("Use DeepCloneWithResetIdentities instead")]
public IContentType Clone(string alias)
{
{
return DeepCloneWithResetIdentities(alias);
}
+14 -7
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
@@ -15,6 +16,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
public abstract class ContentTypeBase : Entity, IContentTypeBase
{
private Lazy<int> _parentId;
@@ -48,17 +50,22 @@ namespace Umbraco.Core.Models
_additionalData = new Dictionary<string, object>();
}
protected ContentTypeBase(IContentTypeBase parent)
protected ContentTypeBase(IContentTypeBase parent) : this(parent, null)
{
Mandate.ParameterNotNull(parent, "parent");
}
_parentId = new Lazy<int>(() => parent.Id);
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
protected ContentTypeBase(IContentTypeBase parent, string alias)
{
Mandate.ParameterNotNull(parent, "parent");
_alias = alias;
_parentId = new Lazy<int>(() => parent.Id);
_allowedContentTypes = new List<ContentTypeSort>();
_propertyGroups = new PropertyGroupCollection();
_propertyTypes = new PropertyTypeCollection();
_propertyTypes.CollectionChanged += PropertyTypesChanged;
_additionalData = new Dictionary<string, object>();
}
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.ParentId);
@@ -492,7 +499,6 @@ namespace Umbraco.Core.Models
/// <param name="propertyTypeAlias">Alias of the <see cref="PropertyType"/> to remove</param>
public void RemovePropertyType(string propertyTypeAlias)
{
//check if the property exist in one of our collections
if (PropertyGroups.Any(group => group.PropertyTypes.Any(pt => pt.Alias == propertyTypeAlias))
|| _propertyTypes.Any(x => x.Alias == propertyTypeAlias))
@@ -519,6 +525,7 @@ namespace Umbraco.Core.Models
public void RemovePropertyGroup(string propertyGroupName)
{
PropertyGroups.RemoveItem(propertyGroupName);
OnPropertyChanged(PropertyGroupCollectionSelector);
}
/// <summary>
@@ -22,11 +22,16 @@ namespace Umbraco.Core.Models
}
protected ContentTypeCompositionBase(IContentTypeComposition parent)
: base(parent)
: this(parent, null)
{
AddContentType(parent);
}
protected ContentTypeCompositionBase(IContentTypeComposition parent, string alias)
: base(parent, alias)
{
AddContentType(parent);
}
private static readonly PropertyInfo ContentTypeCompositionSelector =
ExpressionHelper.GetPropertyInfo<ContentTypeCompositionBase, IEnumerable<IContentTypeComposition>>(
x => x.ContentTypeComposition);
@@ -76,6 +81,9 @@ namespace Umbraco.Core.Models
if (contentType.ContentTypeComposition.Any(x => x.CompositionAliases().Any(ContentTypeCompositionExists)))
return false;
if (string.IsNullOrEmpty(Alias) == false && Alias.Equals(contentType.Alias))
return false;
if (ContentTypeCompositionExists(contentType.Alias) == false)
{
//Before we actually go ahead and add the ContentType as a Composition we ensure that we don't
+13 -2
View File
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Constuctor for creating a MediaType with the parent's id.
/// </summary>
/// <remarks>You usually only want to use this for creating MediaTypes at the root.</remarks>
/// <remarks>Only use this for creating MediaTypes at the root (with ParentId -1).</remarks>
/// <param name="parentId"></param>
public MediaType(int parentId) : base(parentId)
{
@@ -24,10 +24,21 @@ namespace Umbraco.Core.Models
/// </summary>
/// <remarks>Use this to ensure inheritance from parent.</remarks>
/// <param name="parent"></param>
public MediaType(IMediaType parent) : base(parent)
public MediaType(IMediaType parent) : this(parent, null)
{
}
/// <summary>
/// Constuctor for creating a MediaType with the parent as an inherited type.
/// </summary>
/// <remarks>Use this to ensure inheritance from parent.</remarks>
/// <param name="parent"></param>
/// <param name="alias"></param>
public MediaType(IMediaType parent, string alias)
: base(parent, alias)
{
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
+1 -34
View File
@@ -20,7 +20,6 @@ namespace Umbraco.Core.Models
private string _email;
private string _rawPasswordValue;
private object _providerUserKey;
private Type _userTypeKey;
/// <summary>
/// Constructor for creating an empty Member object
@@ -114,7 +113,6 @@ namespace Umbraco.Core.Models
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Email);
private static readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.RawPasswordValue);
private static readonly PropertyInfo ProviderUserKeySelector = ExpressionHelper.GetPropertyInfo<Member, object>(x => x.ProviderUserKey);
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<Member, Type>(x => x.ProviderUserKeyType);
/// <summary>
/// Gets or sets the Username
@@ -502,38 +500,7 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Gets or sets the type of the provider user key.
/// </summary>
/// <value>
/// The type of the provider user key.
/// </value>
[IgnoreDataMember]
internal Type ProviderUserKeyType
{
get
{
return _userTypeKey;
}
private set
{
SetPropertyValueAndDetectChanges(o =>
{
_userTypeKey = value;
return _userTypeKey;
}, _userTypeKey, UserTypeKeySelector);
}
}
/// <summary>
/// Sets the type of the provider user key.
/// </summary>
/// <param name="type">The type.</param>
internal void SetProviderUserKeyType(Type type)
{
ProviderUserKeyType = type;
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
+6 -2
View File
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
@@ -21,7 +20,12 @@ namespace Umbraco.Core.Models
MemberTypePropertyTypes = new Dictionary<string, MemberTypePropertyProfileAccess>();
}
public MemberType(IContentTypeComposition parent) : base(parent)
public MemberType(IContentTypeComposition parent) : this(parent, null)
{
}
public MemberType(IContentTypeComposition parent, string alias)
: base(parent, alias)
{
MemberTypePropertyTypes = new Dictionary<string, MemberTypePropertyProfileAccess>();
}
@@ -7,9 +7,9 @@ namespace Umbraco.Core.Models.Membership
{
internal static class MembershipUserExtensions
{
internal static UmbracoMembershipMember AsConcreteMembershipUser(this IMembershipUser member, string providerName)
internal static UmbracoMembershipMember AsConcreteMembershipUser(this IMembershipUser member, string providerName, bool providerKeyAsGuid = false)
{
var membershipMember = new UmbracoMembershipMember(member, providerName);
var membershipMember = new UmbracoMembershipMember(member, providerName, providerKeyAsGuid);
return membershipMember;
}
@@ -1,5 +1,6 @@
using System;
using System.Web.Security;
using Umbraco.Core.Configuration;
namespace Umbraco.Core.Models.Membership
{
@@ -25,7 +26,7 @@ namespace Umbraco.Core.Models.Membership
//NOTE: We are not calling the base constructor which will validate that a provider with the specified name exists which causes issues with unit tests. The ctor
// validation for that doesn't need to be there anyways (have checked the source).
public UmbracoMembershipMember(IMembershipUser member, string providerName)
public UmbracoMembershipMember(IMembershipUser member, string providerName, bool providerKeyAsGuid = false)
{
_member = member;
//NOTE: We are copying the values here so that everything is consistent with how the underlying built-in ASP.Net membership user
@@ -37,7 +38,7 @@ namespace Umbraco.Core.Models.Membership
if (member.PasswordQuestion != null)
_passwordQuestion = member.PasswordQuestion.Trim();
_providerName = providerName;
_providerUserKey = member.ProviderUserKey;
_providerUserKey = providerKeyAsGuid ? member.ProviderUserKey : member.Id;
_comment = member.Comments;
_isApproved = member.IsApproved;
_isLockedOut = member.IsLockedOut;
@@ -58,7 +58,6 @@ namespace Umbraco.Core.Models.Membership
private IUserType _userType;
private string _name;
private Type _userTypeKey;
private List<string> _addedSections;
private List<string> _removedSections;
private ObservableCollection<string> _sectionCollection;
@@ -80,7 +79,6 @@ namespace Umbraco.Core.Models.Membership
private static readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartMediaId);
private static readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.AllowedSections);
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Name);
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<User, Type>(x => x.ProviderUserKeyType);
private static readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Username);
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Email);
@@ -101,37 +99,6 @@ namespace Umbraco.Core.Models.Membership
set { throw new NotSupportedException("Cannot set the provider user key for a user"); }
}
/// <summary>
/// Gets or sets the type of the provider user key.
/// </summary>
/// <value>
/// The type of the provider user key.
/// </value>
[IgnoreDataMember]
internal Type ProviderUserKeyType
{
get
{
return _userTypeKey;
}
private set
{
SetPropertyValueAndDetectChanges(o =>
{
_userTypeKey = value;
return _userTypeKey;
}, _userTypeKey, UserTypeKeySelector);
}
}
/// <summary>
/// Sets the type of the provider user key.
/// </summary>
/// <param name="type">The type.</param>
internal void SetProviderUserKeyType(Type type)
{
ProviderUserKeyType = type;
}
[DataMember]
public string Username
@@ -71,16 +71,34 @@ namespace Umbraco.Core.Models
{
using (new WriteLock(_addLocker))
{
var key = GetKeyForItem(item);
if (key != null)
//Note this is done to ensure existig groups can be renamed
if (item.HasIdentity && item.Id > 0)
{
var exists = this.Contains(key);
var exists = this.Contains(item.Id);
if (exists)
{
SetItem(IndexOfKey(key), item);
var keyExists = this.Contains(item.Name);
if(keyExists)
throw new Exception(string.Format("Naming conflict: Changing the name of PropertyGroup '{0}' would result in duplicates", item.Name));
SetItem(IndexOfKey(item.Id), item);
return;
}
}
else
{
var key = GetKeyForItem(item);
if (key != null)
{
var exists = this.Contains(key);
if (exists)
{
SetItem(IndexOfKey(key), item);
return;
}
}
}
base.Add(item);
OnAdd.IfNotNull(x => x.Invoke());//Could this not be replaced by a Mandate/Contract for ensuring item is not null
@@ -99,6 +117,11 @@ namespace Umbraco.Core.Models
return this.Any(x => x.Name == groupName);
}
public bool Contains(int id)
{
return this.Any(x => x.Id == id);
}
public void RemoveItem(string propertyGroupName)
{
var key = IndexOfKey(propertyGroupName);
@@ -119,6 +142,18 @@ namespace Umbraco.Core.Models
return -1;
}
public int IndexOfKey(int id)
{
for (var i = 0; i < this.Count; i++)
{
if (this[i].Id == id)
{
return i;
}
}
return -1;
}
protected override string GetKeyForItem(PropertyGroup item)
{
return item.Name;
+2 -1
View File
@@ -1,9 +1,9 @@
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Strings;
@@ -14,6 +14,7 @@ namespace Umbraco.Core.Models
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
public class PropertyType : Entity, IEquatable<PropertyType>
{
private readonly bool _isExplicitDbType;
+1
View File
@@ -41,6 +41,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("uniqueID")]
[NullSetting(NullSetting = NullSettings.Null)]
[Index(IndexTypes.NonClustered, Name = "IX_umbracoNodeUniqueID")]
public Guid? UniqueId { get; set; }
[Column("text")]
@@ -75,7 +75,7 @@ namespace Umbraco.Core.Persistence
connection.Open();
connection.Close();
}
catch (SqlException)
catch (DbException)
{
return false;
}
@@ -33,7 +33,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
}
else
{
//If we are on SQLServer, we need to delete constraints by name, older versions of umbraco did not name these default constraints
//If we are on SQLServer, we need to delete default constraints by name, older versions of umbraco did not name these default constraints
// consistently so we need to look up the constraint name to delete, this only pertains to SQL Server and this issue:
// http://issues.umbraco.org/issue/U4-4133
var sqlServerSyntaxProvider = new SqlServerSyntaxProvider();
@@ -51,16 +51,15 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
Delete.Column("macroPropertyHidden").FromTable("cmsMacroProperty");
if (Context.CurrentDatabaseProvider != DatabaseProviders.SqlServer)
if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql)
{
Delete.ForeignKey().FromTable("cmsMacroProperty").ForeignColumn("macroPropertyType").ToTable("cmsMacroPropertyType").PrimaryColumn("id");
}
else
{
//If we are on SQLServer, we need to delete constraints by name, older versions of umbraco did not name these key constraints
// consistently so we need to look up the constraint name to delete, this only pertains to SQL Server and this issue:
// http://issues.umbraco.org/issue/U4-4133
//Before we try to delete this constraint, we'll see if it exists first, some older schemas never had it and some older schema's had this named
// differently than the default.
var keyConstraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct();
var constraint = keyConstraints
.SingleOrDefault(x => x.Item1 == "cmsMacroProperty" && x.Item2 == "macroPropertyType" && x.Item3.InvariantStartsWith("PK_") == false);
@@ -31,15 +31,14 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
Alter.Table("cmsTagRelationship").AddColumn("propertyTypeId").AsInt32().Nullable();
//drop the foreign key on umbracoNode. Must drop foreign key first before primary key can be removed in MySql.
if (Context.CurrentDatabaseProvider != DatabaseProviders.SqlServer)
if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql)
{
Delete.ForeignKey().FromTable("cmsTagRelationship").ForeignColumn("nodeId").ToTable("umbracoNode").PrimaryColumn("id");
}
else
{
//If we are on SQLServer, we need to delete constraints by name, older versions of umbraco did not name these key constraints
// consistently so we need to look up the constraint name to delete, this only pertains to SQL Server and this issue:
// http://issues.umbraco.org/issue/U4-4133
//Before we try to delete this constraint, we'll see if it exists first, some older schemas never had it and some older schema's had this named
// differently than the default.
var constraint = constraints
.SingleOrDefault(x => x.Item1 == "cmsTagRelationship" && x.Item2 == "nodeId" && x.Item3.InvariantStartsWith("PK_") == false);
@@ -62,7 +61,12 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
}
else
{
Delete.PrimaryKey("PK_cmsTagRelationship").FromTable("cmsTagRelationship");
//lookup the PK by name
var pkName = constraints.FirstOrDefault(x => x.Item1.InvariantEquals("cmsTagRelationship") && x.Item3.InvariantStartsWith("PK_"));
if (pkName != null)
{
Delete.PrimaryKey(pkName.Item3).FromTable("cmsTagRelationship");
}
}
}
@@ -137,22 +141,6 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
.OnDelete(Rule.None)
.OnUpdate(Rule.None);
//Some very old schemas don't have an index on the cmsContent.nodeId column, I'm not actually sure when it was added but
// it is absolutely required to exist in order to add this foreign key, so we'll need to check it's existence
// this came to light from this issue: http://issues.umbraco.org/issue/U4-4133
var dbIndexes = SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsContent")) == false)
{
Create.Index("IX_cmsContent").OnTable("cmsContent").OnColumn("nodeId").Ascending().WithOptions().Unique();
}
//now we need to add a foreign key to the nodeId column to cmsContent (intead of the original umbracoNode)
Create.ForeignKey("FK_cmsTagRelationship_cmsContent")
.FromTable("cmsTagRelationship")
@@ -0,0 +1,93 @@
using System.Data;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
{
/// <summary>
/// I'm not actually sure how this is possible but I've come across one install that was missing these PKs
/// and it wasn't a MySQL install.
/// see: http://issues.umbraco.org/issue/U4-5707
/// </summary>
[Migration("7.0.0", 0, GlobalSettings.UmbracoMigrationName)]
public class AssignMissingKeysAndIndexes : MigrationBase
{
public override void Up()
{
//Some very old schemas don't have an index on the cmsContent.nodeId column, I'm not actually sure when it was added but
// it is absolutely required to exist in order to have it as a foreign key reference, so we'll need to check it's existence
// this came to light from this issue: http://issues.umbraco.org/issue/U4-4133
var dbIndexes = SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsContent")) == false)
{
Create.Index("IX_cmsContent").OnTable("cmsContent").OnColumn("nodeId").Ascending().WithOptions().Unique();
}
if (Context.CurrentDatabaseProvider == DatabaseProviders.SqlServer
|| Context.CurrentDatabaseProvider == DatabaseProviders.SqlServerCE)
{
var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
//This should be 2 because this table has 2 keys
if (constraints.Count(x => x.Item1.InvariantEquals("cmsPreviewXml") && x.Item3.InvariantStartsWith("PK_")) == 0)
{
Create.PrimaryKey("PK_cmsContentPreviewXml")
.OnTable("cmsPreviewXml")
.Columns(new[] { "nodeId", "versionId" });
}
if (constraints.Count(x => x.Item1.InvariantEquals("cmsTags") && x.Item3.InvariantStartsWith("PK_")) == 0)
{
Create.PrimaryKey("PK_cmsTags")
.OnTable("cmsTags")
.Columns(new[] { "id" });
}
if (constraints.Count(x => x.Item1.InvariantEquals("cmsStylesheetProperty") && x.Item3.InvariantStartsWith("PK_")) == 0)
{
Create.PrimaryKey("PK_cmsStylesheetProperty")
.OnTable("cmsStylesheetProperty")
.Columns(new[] { "nodeId" });
}
if (constraints.Count(x => x.Item1.InvariantEquals("cmsStylesheet") && x.Item3.InvariantStartsWith("PK_")) == 0)
{
Create.PrimaryKey("PK_cmsStylesheet")
.OnTable("cmsStylesheet")
.Columns(new[] { "nodeId" });
Create.ForeignKey("FK_cmsStylesheet_umbracoNode_id").FromTable("cmsStylesheet").ForeignColumn("nodeId")
.ToTable("umbracoNode").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
}
if (constraints.Count(x => x.Item1.InvariantEquals("cmsMember") && x.Item3.InvariantStartsWith("PK_")) == 0)
{
Create.PrimaryKey("PK_cmsMember")
.OnTable("cmsMember")
.Columns(new[] { "nodeId" });
Create.ForeignKey("FK_cmsMember_umbracoNode_id").FromTable("cmsMember").ForeignColumn("nodeId")
.ToTable("umbracoNode").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
Create.ForeignKey("FK_cmsMember_cmsContent_nodeId").FromTable("cmsMember").ForeignColumn("nodeId")
.ToTable("cmsContent").PrimaryColumn("nodeId").OnDeleteOrUpdate(Rule.None);
}
}
}
public override void Down()
{
//don't do anything, these keys should have always existed!
}
}
}
@@ -0,0 +1,45 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
{
[Migration("7.2.0", 3, GlobalSettings.UmbracoMigrationName)]
public class AddIndexToUmbracoNodeTable : MigrationBase
{
private readonly bool _skipIndexCheck;
internal AddIndexToUmbracoNodeTable(bool skipIndexCheck)
{
_skipIndexCheck = skipIndexCheck;
}
public AddIndexToUmbracoNodeTable()
{
}
public override void Up()
{
var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[] { } : SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")) == false)
{
Create.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode").OnColumn("uniqueID").Ascending().WithOptions().NonClustered();
}
}
public override void Down()
{
Delete.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode");
}
}
}
@@ -1,3 +1,5 @@
using System.Linq;
using AutoMapper;
using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -11,9 +13,20 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
{
public override void Up()
{
//To text
var textType = SqlSyntaxContext.SqlSyntaxProvider.GetSpecialDbType(SpecialDbTypes.NTEXT);
Alter.Table("cmsDataTypePreValues").AlterColumn("value").AsCustom(textType).Nullable();
var columns = SqlSyntaxContext.SqlSyntaxProvider.GetColumnsInSchema(Context.Database).Distinct().ToArray();
//Check if it's already text
if (columns.Any(x => x.ColumnName.InvariantEquals("value") && x.TableName.InvariantEquals("cmsDataTypePreValues")
//mysql check
&& (x.DataType.InvariantEquals("longtext") == false
//sql server check
&& x.DataType.InvariantEquals("ntext") == false)))
{
//To text
var textType = SqlSyntaxContext.SqlSyntaxProvider.GetSpecialDbType(SpecialDbTypes.NTEXT);
Alter.Table("cmsDataTypePreValues").AlterColumn("value").AsCustom(textType).Nullable();
}
}
public override void Down()
+71 -42
View File
@@ -562,7 +562,14 @@ namespace Umbraco.Core.Persistence
{
object val = cmd.ExecuteScalarWithRetry();
OnExecutedCommand(cmd);
return (T)Convert.ChangeType(val, typeof(T));
if (val == null || val == DBNull.Value)
return default(T);
Type t = typeof(T);
Type u = Nullable.GetUnderlyingType(t);
return (T)Convert.ChangeType(val, u ?? t);
}
}
finally
@@ -843,7 +850,7 @@ namespace Umbraco.Core.Persistence
public IEnumerable<T1> Query<T1, T2, T3, T4>(Sql sql) { return Query<T1>(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, null, sql.SQL, sql.Arguments); }
// Automagically guess the property relationships between various POCOs and create a delegate that will set them up
object GetAutoMapper(Type[] types)
Delegate GetAutoMapper(Type[] types)
{
// Build a key
var kb = new StringBuilder();
@@ -858,7 +865,7 @@ namespace Umbraco.Core.Persistence
RWLock.EnterReadLock();
try
{
object mapper;
Delegate mapper;
if (AutoMappers.TryGetValue(key, out mapper))
return mapper;
}
@@ -872,7 +879,7 @@ namespace Umbraco.Core.Persistence
try
{
// Try again
object mapper;
Delegate mapper;
if (AutoMappers.TryGetValue(key, out mapper))
return mapper;
@@ -945,22 +952,53 @@ namespace Umbraco.Core.Persistence
throw new InvalidOperationException(string.Format("Couldn't find split point between {0} and {1}", typeThis, typeNext));
}
// Instance data used by the Multipoco factory delegate - essentially a list of the nested poco factories to call
public class MultiPocoFactory
{
public List<Delegate> m_Delegates;
public Delegate GetItem(int index) { return m_Delegates[index]; }
public MultiPocoFactory(IEnumerable<Delegate> dels)
{
Delegates = new List<Delegate>(dels);
}
private List<Delegate> Delegates { get; set; }
private Delegate GetItem(int index) { return Delegates[index]; }
/// <summary>
/// Calls the delegate at the specified index and returns its values
/// </summary>
/// <param name="index"></param>
/// <param name="reader"></param>
/// <returns></returns>
private object CallDelegate(int index, IDataReader reader)
{
var d = GetItem(index);
var output = d.DynamicInvoke(reader);
return output;
}
/// <summary>
/// Calls the callback delegate and passes in the output of all delegates as the parameters
/// </summary>
/// <typeparam name="TRet"></typeparam>
/// <param name="callback"></param>
/// <param name="dr"></param>
/// <param name="count"></param>
/// <returns></returns>
public TRet CallCallback<TRet>(Delegate callback, IDataReader dr, int count)
{
var args = new List<object>();
for(var i = 0;i<count;i++)
{
args.Add(CallDelegate(i, dr));
}
return (TRet)callback.DynamicInvoke(args.ToArray());
}
}
// Create a multi-poco factory
Func<IDataReader, object, TRet> CreateMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
{
var m = new DynamicMethod("petapoco_multipoco_factory", typeof(TRet), new Type[] { typeof(MultiPocoFactory), typeof(IDataReader), typeof(object) }, typeof(MultiPocoFactory));
var il = m.GetILGenerator();
// Load the callback
il.Emit(OpCodes.Ldarg_2);
Func<IDataReader, Delegate, TRet> CreateMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
{
// Call each delegate
var dels = new List<Delegate>();
int pos = 0;
@@ -969,33 +1007,19 @@ namespace Umbraco.Core.Persistence
// Add to list of delegates to call
var del = FindSplitPoint(types[i], i + 1 < types.Length ? types[i + 1] : null, sql, r, ref pos);
dels.Add(del);
// Get the delegate
il.Emit(OpCodes.Ldarg_0); // callback,this
il.Emit(OpCodes.Ldc_I4, i); // callback,this,Index
il.Emit(OpCodes.Callvirt, typeof(MultiPocoFactory).GetMethod("GetItem")); // callback,Delegate
il.Emit(OpCodes.Ldarg_1); // callback,delegate, datareader
// Call Invoke
var tDelInvoke = del.GetType().GetMethod("Invoke");
il.Emit(OpCodes.Callvirt, tDelInvoke); // Poco left on stack
}
// By now we should have the callback and the N pocos all on the stack. Call the callback and we're done
il.Emit(OpCodes.Callvirt, Expression.GetFuncType(types.Concat(new Type[] { typeof(TRet) }).ToArray()).GetMethod("Invoke"));
il.Emit(OpCodes.Ret);
// Finish up
return (Func<IDataReader, object, TRet>)m.CreateDelegate(typeof(Func<IDataReader, object, TRet>), new MultiPocoFactory() { m_Delegates = dels });
var mpFactory = new MultiPocoFactory(dels);
return (reader, arg3) => mpFactory.CallCallback<TRet>(arg3, reader, types.Length);
}
// Various cached stuff
static Dictionary<string, object> MultiPocoFactories = new Dictionary<string, object>();
static Dictionary<string, object> AutoMappers = new Dictionary<string, object>();
static Dictionary<string, Delegate> AutoMappers = new Dictionary<string, Delegate>();
static System.Threading.ReaderWriterLockSlim RWLock = new System.Threading.ReaderWriterLockSlim();
// Get (or create) the multi-poco factory for a query
Func<IDataReader, object, TRet> GetMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
// Get (or create) the multi-poco factory for a query
Func<IDataReader, Delegate, TRet> GetMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
{
// Build a key string (this is crap, should address this at some point)
var kb = new StringBuilder();
@@ -1017,7 +1041,10 @@ namespace Umbraco.Core.Persistence
{
object oFactory;
if (MultiPocoFactories.TryGetValue(key, out oFactory))
return (Func<IDataReader, object, TRet>)oFactory;
{
//mpFactory = oFactory;
return (Func<IDataReader, Delegate, TRet>)oFactory;
}
}
finally
{
@@ -1029,15 +1056,17 @@ namespace Umbraco.Core.Persistence
try
{
// Check again
object oFactory;
object oFactory; ;
if (MultiPocoFactories.TryGetValue(key, out oFactory))
return (Func<IDataReader, object, TRet>)oFactory;
{
return (Func<IDataReader, Delegate, TRet>)oFactory;
}
// Create the factory
var factory = CreateMultiPocoFactory<TRet>(types, sql, r);
// Create the factory
var Factory = CreateMultiPocoFactory<TRet>(types, sql, r);
MultiPocoFactories.Add(key, Factory);
return Factory;
MultiPocoFactories.Add(key, factory);
return factory;
}
finally
{
@@ -1047,7 +1076,7 @@ namespace Umbraco.Core.Persistence
}
// Actual implementation of the multi-poco query
public IEnumerable<TRet> Query<TRet>(Type[] types, object cb, string sql, params object[] args)
public IEnumerable<TRet> Query<TRet>(Type[] types, Delegate cb, string sql, params object[] args)
{
OpenSharedConnection();
try
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
@@ -24,11 +25,17 @@ namespace Umbraco.Core.Persistence
public static Sql Where<T>(this Sql sql, Expression<Func<T, bool>> predicate)
{
var expresionist = new PocoToSqlExpressionHelper<T>();
string whereExpression = expresionist.Visit(predicate);
var whereExpression = expresionist.Visit(predicate);
return sql.Where(whereExpression, expresionist.GetSqlParameters());
}
public static Sql WhereIn<T>(this Sql sql, Expression<Func<T, object>> fieldSelector, IEnumerable values)
{
var expresionist = new PocoToSqlExpressionHelper<T>();
var fieldExpression = expresionist.Visit(fieldSelector);
return sql.Where(fieldExpression + " IN (@values)", new {@values = values});
}
public static Sql OrderBy<TColumn>(this Sql sql, Expression<Func<TColumn, object>> columnMember)
{
var column = ExpressionHelper.FindProperty(columnMember) as PropertyInfo;
@@ -728,7 +728,6 @@ namespace Umbraco.Core.Persistence.Repositories
Func<Tuple<string, object[]>> filterCallback = () => new Tuple<string, object[]>(sbWhere.ToString(), args.ToArray());
return GetPagedResultsByQuery<DocumentDto, Content>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsDocument", "nodeId"),
ProcessQuery, orderBy, orderDirection,
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
@@ -297,9 +298,38 @@ AND umbracoNode.id <> @id",
//Delete Tabs/Groups by excepting entries from db with entries from collections
var dbPropertyGroups =
Database.Fetch<PropertyTypeGroupDto>("WHERE contenttypeNodeId = @Id", new {Id = entity.Id})
.Select(x => new Tuple<int, string>(x.Id, x.Text));
var entityPropertyGroups = entity.PropertyGroups.Select(x => new Tuple<int, string>(x.Id, x.Name));
var tabs = dbPropertyGroups.Except(entityPropertyGroups);
.Select(x => new Tuple<int, string>(x.Id, x.Text))
.ToList();
var entityPropertyGroups = entity.PropertyGroups.Select(x => new Tuple<int, string>(x.Id, x.Name)).ToList();
var tabsToDelete = dbPropertyGroups.Select(x => x.Item1).Except(entityPropertyGroups.Select(x => x.Item1));
var tabs = dbPropertyGroups.Where(x => tabsToDelete.Any(y => y == x.Item1));
//Update Tab name downstream to ensure renaming is done properly
foreach (var propertyGroup in entityPropertyGroups)
{
Database.Update<PropertyTypeGroupDto>("SET Text = @TabName WHERE parentGroupId = @TabId",
new { TabName = propertyGroup.Item2, TabId = propertyGroup.Item1 });
var childGroups = Database.Fetch<PropertyTypeGroupDto>("WHERE parentGroupId = @TabId", new { TabId = propertyGroup.Item1 });
foreach (var childGroup in childGroups)
{
var sibling = Database.Fetch<PropertyTypeGroupDto>("WHERE contenttypeNodeId = @Id AND text = @Name",
new { Id = childGroup.ContentTypeNodeId, Name = propertyGroup.Item2 })
.FirstOrDefault(x => x.ParentGroupId.HasValue == false || x.ParentGroupId.Value.Equals(propertyGroup.Item1) == false);
//If the child group doesn't have a sibling there is no chance of duplicates and we continue
if (sibling == null || (sibling.ParentGroupId.HasValue && sibling.ParentGroupId.Value.Equals(propertyGroup.Item1))) continue;
//Since the child group has a sibling with the same name we need to point any PropertyTypes to the sibling
//as this child group is about to leave the party.
Database.Update<PropertyTypeDto>(
"SET propertyTypeGroupId = @PropertyTypeGroupId WHERE propertyTypeGroupId = @PropertyGroupId AND ContentTypeId = @ContentTypeId",
new { PropertyTypeGroupId = sibling.Id, PropertyGroupId = childGroup.Id, ContentTypeId = childGroup.ContentTypeNodeId });
//Since the parent group has been renamed and we have duplicates we remove this group
//and leave our sibling in charge of the part.
Database.Delete(childGroup);
}
}
//Do Tab updates
foreach (var tab in tabs)
{
Database.Update<PropertyTypeDto>("SET propertyTypeGroupId = NULL WHERE propertyTypeGroupId = @PropertyGroupId",
@@ -375,16 +375,15 @@ AND umbracoNode.id <> @id",
var existing = existingByIds.FirstOrDefault(valueDto => valueDto.Id == pre.Value.Id);
if (existing != null)
{
existing.Value = pre.Value.Value;
existing.SortOrder = sortOrder;
_preValRepository.AddOrUpdate(new PreValueEntity
{
//setting an id will update it
Id = existing.Id,
Alias = existing.Alias,
SortOrder = existing.SortOrder,
Value = existing.Value,
DataType = dataType,
//These are the new values to update
Alias = pre.Key,
SortOrder = sortOrder,
Value = pre.Value.Value
});
}
else
@@ -308,7 +308,11 @@ namespace Umbraco.Core.Persistence.Repositories
IEnumerable<TEntity> result;
var pagedResult = Database.Page<TDto>(pageIndex + 1, pageSize, sqlNodeIdsWithSort);
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
if (totalRecords > 0)
//NOTE: We need to check the actual items returned, not the 'totalRecords', that is because if you request a page number
// that doesn't actually have any data on it, the totalRecords will still indicate there are records but there are none in
// the pageResult, then the GetAll will actually return ALL records in the db.
if (pagedResult.Items.Any())
{
//Crete the inner paged query that was used above to get the paged result, we'll use that as the inner sub query
var args = sqlNodeIdsWithSort.Arguments;
@@ -8,6 +8,7 @@ using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Cache;
using File = System.IO.File;
namespace Umbraco.Core.Services
@@ -15,15 +16,18 @@ namespace Umbraco.Core.Services
internal class ApplicationTreeService : IApplicationTreeService
{
private readonly CacheHelper _cache;
private IEnumerable<ApplicationTree> _allAvailableTrees;
private volatile bool _isInitialized = false;
internal const string TreeConfigFileName = "trees.config";
private static string _treeConfig;
private static readonly object Locker = new object();
public ApplicationTreeService(CacheHelper cache)
{
_cache = cache;
}
internal const string TreeConfigFileName = "trees.config";
private static string _treeConfig;
private static readonly object Locker = new object();
/// <summary>
/// gets/sets the trees.config file path
@@ -45,74 +49,101 @@ namespace Umbraco.Core.Services
}
/// <summary>
/// The cache storage for all application trees
/// The main entry point to get application trees
/// </summary>
/// <remarks>
/// This lazily on first access will scan for plugin trees and ensure the trees.config is up-to-date with the plugins. If plugins
/// haven't changed on disk then the file will not be saved. The trees are all then loaded from this config file into cache and returned.
/// </remarks>
private List<ApplicationTree> GetAppTrees()
{
return _cache.GetCacheItem(
return _cache.RuntimeCache.GetCacheItem<List<ApplicationTree>>(
CacheKeys.ApplicationTreeCacheKey,
() =>
{
var list = ReadFromXmlAndSort();
//On first access we need to do some initialization
if (_isInitialized == false)
{
var list = new List<ApplicationTree>();
LoadXml(doc =>
lock (Locker)
{
if (_isInitialized == false)
{
foreach (var addElement in doc.Root.Elements("add").OrderBy(x =>
{
var sortOrderAttr = x.Attribute("sortOrder");
return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0;
}))
//now we can check the non-volatile flag
if (_allAvailableTrees != null)
{
var applicationAlias = (string) addElement.Attribute("application");
var type = (string) addElement.Attribute("type");
var assembly = (string) addElement.Attribute("assembly");
var hasChanges = false;
var clrType = Type.GetType(type);
if (clrType == null)
LoadXml(doc =>
{
LogHelper.Warn<ApplicationTreeService>("The tree definition: " + addElement.ToString() + " could not be resolved to a .Net object type");
continue;
}
//Now, load in the xml structure and update it with anything that is not declared there and save the file.
//check if the tree definition (applicationAlias + type + assembly) is already in the list
//NOTE: On the first iteration here, it will lazily scan all trees, etc... this is because this ienumerable is lazy
// based on the ApplicationTreeRegistrar - and as noted there this is not an ideal way to do things but were stuck like this
// currently because of the legacy assemblies and types not in the Core.
if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false)
//Get all the trees not registered in the config
var unregistered = _allAvailableTrees
.Where(x => list.Any(l => l.Alias == x.Alias) == false)
.ToArray();
hasChanges = unregistered.Any();
if (hasChanges == false) return false;
//add the unregistered ones to the list and re-save the file if any changes were found
var count = 0;
foreach (var tree in unregistered)
{
doc.Root.Add(new XElement("add",
new XAttribute("initialize", tree.Initialize),
new XAttribute("sortOrder", tree.SortOrder),
new XAttribute("alias", tree.Alias),
new XAttribute("application", tree.ApplicationAlias),
new XAttribute("title", tree.Title),
new XAttribute("iconClosed", tree.IconClosed),
new XAttribute("iconOpen", tree.IconOpened),
new XAttribute("type", tree.Type)));
count++;
}
//don't save if there's no changes
return count > 0;
}, true);
if (hasChanges)
{
list.Add(new ApplicationTree(
addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value),
addElement.Attribute("sortOrder") != null ? Convert.ToByte(addElement.Attribute("sortOrder").Value) : (byte) 0,
addElement.Attribute("application").Value,
addElement.Attribute("alias").Value,
addElement.Attribute("title").Value,
addElement.Attribute("iconClosed").Value,
addElement.Attribute("iconOpen").Value,
addElement.Attribute("type").Value));
//If there were changes, we need to re-read the structures from the XML
list = ReadFromXmlAndSort();
}
}
}, false);
return list;
});
_isInitialized = true;
}
}
}
return list;
});
}
public void Intitialize(IEnumerable<ApplicationTree> existingTrees)
/// <summary>
/// Initializes the service with any trees found in plugins
/// </summary>
/// <param name="allAvailableTrees">
/// A collection of all available tree found in assemblies in the application
/// </param>
/// <remarks>
/// This will update the trees.config with the found tree plugins that are not currently listed in the file when the first
/// access is made to resolve the tree collection
/// </remarks>
public void Intitialize(IEnumerable<ApplicationTree> allAvailableTrees)
{
LoadXml(doc =>
{
foreach (var tree in existingTrees)
{
doc.Root.Add(new XElement("add",
new XAttribute("initialize", tree.Initialize),
new XAttribute("sortOrder", tree.SortOrder),
new XAttribute("alias", tree.Alias),
new XAttribute("application", tree.ApplicationAlias),
new XAttribute("title", tree.Title),
new XAttribute("iconClosed", tree.IconClosed),
new XAttribute("iconOpen", tree.IconOpened),
new XAttribute("type", tree.Type)));
}
}, true);
_allAvailableTrees = allAvailableTrees;
}
/// <summary>
@@ -134,16 +165,19 @@ namespace Umbraco.Core.Services
if (el == null)
{
doc.Root.Add(new XElement("add",
new XAttribute("initialize", initialize),
new XAttribute("sortOrder", sortOrder),
new XAttribute("alias", alias),
new XAttribute("application", applicationAlias),
new XAttribute("title", title),
new XAttribute("iconClosed", iconClosed),
new XAttribute("iconOpen", iconOpened),
new XAttribute("type", type)));
doc.Root.Add(new XElement("add",
new XAttribute("initialize", initialize),
new XAttribute("sortOrder", sortOrder),
new XAttribute("alias", alias),
new XAttribute("application", applicationAlias),
new XAttribute("title", title),
new XAttribute("iconClosed", iconClosed),
new XAttribute("iconOpen", iconOpened),
new XAttribute("type", type)));
}
return true;
}, true);
OnNew(new ApplicationTree(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, type), new EventArgs());
@@ -161,7 +195,7 @@ namespace Umbraco.Core.Services
if (el != null)
{
el.RemoveAttributes();
el.Add(new XAttribute("initialize", tree.Initialize));
el.Add(new XAttribute("sortOrder", tree.SortOrder));
el.Add(new XAttribute("alias", tree.Alias));
@@ -172,6 +206,8 @@ namespace Umbraco.Core.Services
el.Add(new XAttribute("type", tree.Type));
}
return true;
}, true);
OnUpdated(tree, new EventArgs());
@@ -181,11 +217,16 @@ namespace Umbraco.Core.Services
/// Deletes this instance.
/// </summary>
public void DeleteTree(ApplicationTree tree)
{
{
LoadXml(doc =>
{
doc.Root.Elements("add").Where(x => x.Attribute("application") != null && x.Attribute("application").Value == tree.ApplicationAlias &&
x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove();
doc.Root.Elements("add")
.Where(x => x.Attribute("application") != null
&& x.Attribute("application").Value == tree.ApplicationAlias
&& x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove();
return true;
}, true);
OnDeleted(tree, new EventArgs());
@@ -231,31 +272,44 @@ namespace Umbraco.Core.Services
{
var list = GetAppTrees().FindAll(
t =>
{
if (onlyInitialized)
return (t.ApplicationAlias == applicationAlias && t.Initialize);
return (t.ApplicationAlias == applicationAlias);
}
{
if (onlyInitialized)
return (t.ApplicationAlias == applicationAlias && t.Initialize);
return (t.ApplicationAlias == applicationAlias);
}
);
return list.OrderBy(x => x.SortOrder).ToArray();
}
internal void LoadXml(Action<XDocument> callback, bool saveAfterCallback)
/// <summary>
/// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the
/// callback with the xml document and saves the structure back to disk if saveAfterCallback is true.
/// </summary>
/// <param name="callback"></param>
/// <param name="saveAfterCallbackIfChanges"></param>
internal void LoadXml(Func<XDocument, bool> callback, bool saveAfterCallbackIfChanges)
{
lock (Locker)
{
var doc = File.Exists(TreeConfigFilePath)
? XDocument.Load(TreeConfigFilePath)
: XDocument.Parse("<?xml version=\"1.0\"?><trees />");
if (doc.Root != null)
{
callback.Invoke(doc);
var hasChanges = callback.Invoke(doc);
if (saveAfterCallback)
if (saveAfterCallbackIfChanges && hasChanges
//Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process
// in some insane way the file saved will be empty. I'm pretty sure it's not actually anything to do with the xml doc and
// more about the IO trying to save the XML doc, but it doesn't hurt to check.
&& doc.Root != null && doc.Root.Elements().Any())
{
//ensures the folder exists
Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath));
//saves it
doc.Save(TreeConfigFilePath);
//remove the cache now that it has changed SD: I'm leaving this here even though it
@@ -266,6 +320,54 @@ namespace Umbraco.Core.Services
}
}
private List<ApplicationTree> ReadFromXmlAndSort()
{
var list = new List<ApplicationTree>();
//read in the xml file containing trees and convert them all to ApplicationTree instances
LoadXml(doc =>
{
foreach (var addElement in doc.Root.Elements("add").OrderBy(x =>
{
var sortOrderAttr = x.Attribute("sortOrder");
return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0;
}))
{
var applicationAlias = (string)addElement.Attribute("application");
var type = (string)addElement.Attribute("type");
var assembly = (string)addElement.Attribute("assembly");
var clrType = Type.GetType(type);
if (clrType == null)
{
LogHelper.Warn<ApplicationTreeService>("The tree definition: " + addElement.ToString() + " could not be resolved to a .Net object type");
continue;
}
//check if the tree definition (applicationAlias + type + assembly) is already in the list
if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false)
{
list.Add(new ApplicationTree(
addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value),
addElement.Attribute("sortOrder") != null ? Convert.ToByte(addElement.Attribute("sortOrder").Value) : (byte)0,
addElement.Attribute("application").Value,
addElement.Attribute("alias").Value,
addElement.Attribute("title").Value,
addElement.Attribute("iconClosed").Value,
addElement.Attribute("iconOpen").Value,
addElement.Attribute("type").Value));
}
}
return false;
}, false);
return list;
}
internal static event TypedEventHandler<ApplicationTree, EventArgs> Deleted;
private static void OnDeleted(ApplicationTree app, EventArgs args)
{
+2 -2
View File
@@ -507,7 +507,7 @@ namespace Umbraco.Core.Services
var query = Query<IContent>.Builder;
//if the id is -1, then just get all
if (id > 0)
if (id != -1)
{
query.Where(x => x.ParentId == id);
}
@@ -537,7 +537,7 @@ namespace Umbraco.Core.Services
var query = Query<IContent>.Builder;
//if the id is -1, then just get all
if (id > 0)
if (id != -1)
{
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
}
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Xml.Linq;
@@ -8,11 +9,13 @@ using System.Threading;
using Umbraco.Core.Auditing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
@@ -273,6 +276,74 @@ namespace Umbraco.Core.Services
}
public void Validate(IContentTypeComposition compo)
{
using (new WriteLock(Locker))
{
ValidateLocked(compo);
}
}
private void ValidateLocked(IContentTypeComposition compositionContentType)
{
// performs business-level validation of the composition
// should ensure that it is absolutely safe to save the composition
// eg maybe a property has been added, with an alias that's OK (no conflict with ancestors)
// but that cannot be used (conflict with descendants)
var contentType = compositionContentType as IContentType;
var mediaType = compositionContentType as IMediaType;
IContentTypeComposition[] allContentTypes;
if (contentType != null)
allContentTypes = GetAllContentTypes().Cast<IContentTypeComposition>().ToArray();
else if (mediaType != null)
allContentTypes = GetAllMediaTypes().Cast<IContentTypeComposition>().ToArray();
else
throw new Exception("Composition is neither IContentType nor IMediaType?");
var compositionAliases = compositionContentType.CompositionAliases();
var compositions = allContentTypes.Where(x => compositionAliases.Any(y => x.Alias.Equals(y)));
var propertyTypeAliases = compositionContentType.PropertyTypes.Select(x => x.Alias.ToLowerInvariant()).ToArray();
var indirectReferences = allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == compositionContentType.Id));
var comparer = new DelegateEqualityComparer<IContentTypeComposition>((x, y) => x.Id == y.Id, x => x.Id);
var dependencies = new HashSet<IContentTypeComposition>(compositions, comparer);
var stack = new Stack<IContentTypeComposition>();
indirectReferences.ForEach(stack.Push);//Push indirect references to a stack, so we can add recursively
while (stack.Count > 0)
{
var indirectReference = stack.Pop();
dependencies.Add(indirectReference);
//Get all compositions for the current indirect reference
var directReferences = indirectReference.ContentTypeComposition;
foreach (var directReference in directReferences)
{
if (directReference.Id == compositionContentType.Id || directReference.Alias.Equals(compositionContentType.Alias)) continue;
dependencies.Add(directReference);
//A direct reference has compositions of its own - these also need to be taken into account
var directReferenceGraph = directReference.CompositionAliases();
allContentTypes.Where(x => directReferenceGraph.Any(y => x.Alias.Equals(y, StringComparison.InvariantCultureIgnoreCase))).ForEach(c => dependencies.Add(c));
}
//Recursive lookup of indirect references
allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == indirectReference.Id)).ForEach(stack.Push);
}
foreach (var dependency in dependencies)
{
if (dependency.Id == compositionContentType.Id) continue;
var contentTypeDependency = allContentTypes.FirstOrDefault(x => x.Alias.Equals(dependency.Alias, StringComparison.InvariantCultureIgnoreCase));
if (contentTypeDependency == null) continue;
var intersect = contentTypeDependency.PropertyTypes.Select(x => x.Alias.ToLowerInvariant()).Intersect(propertyTypeAliases).ToArray();
if (intersect.Length == 0) continue;
var message = string.Format("The following PropertyType aliases from the current ContentType conflict with existing PropertyType aliases: {0}.",
string.Join(", ", intersect));
throw new Exception(message);
}
}
/// <summary>
/// Saves a single <see cref="IContentType"/> object
/// </summary>
@@ -288,6 +359,7 @@ namespace Umbraco.Core.Services
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
{
ValidateLocked(contentType); // throws if invalid
contentType.CreatorId = userId;
repository.AddOrUpdate(contentType);
@@ -317,6 +389,11 @@ namespace Umbraco.Core.Services
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
{
// all-or-nothing, validate them all first
foreach (var contentType in asArray)
{
ValidateLocked(contentType); // throws if invalid
}
foreach (var contentType in asArray)
{
contentType.CreatorId = userId;
@@ -487,6 +564,7 @@ namespace Umbraco.Core.Services
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
ValidateLocked(mediaType); // throws if invalid
mediaType.CreatorId = userId;
repository.AddOrUpdate(mediaType);
uow.Commit();
@@ -517,7 +595,11 @@ namespace Umbraco.Core.Services
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
{
// all-or-nothing, validate them all first
foreach (var mediaType in asArray)
{
ValidateLocked(mediaType); // throws if invalid
}
foreach (var mediaType in asArray)
{
mediaType.CreatorId = userId;
+35 -23
View File
@@ -200,8 +200,22 @@ namespace Umbraco.Core.Services
/// <param name="userId">Id of the user issueing the save</param>
public void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId = 0)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions), this))
return;
Save(dataTypeDefinitions, userId, true);
}
/// <summary>
/// Saves a collection of <see cref="IDataTypeDefinition"/>
/// </summary>
/// <param name="dataTypeDefinitions"><see cref="IDataTypeDefinition"/> to save</param>
/// <param name="userId">Id of the user issueing the save</param>
/// <param name="raiseEvents">Boolean indicating whether or not to raise events</param>
public void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId, bool raiseEvents)
{
if (raiseEvents)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions), this))
return;
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
@@ -213,7 +227,8 @@ namespace Umbraco.Core.Services
}
uow.Commit();
Saved.RaiseEvent(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions, false), this);
if (raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions, false), this);
}
Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, -1);
@@ -229,30 +244,27 @@ namespace Umbraco.Core.Services
{
//TODO: Should we raise an event here since we are really saving values for the data type?
using (new WriteLock(Locker))
using (var uow = _uowProvider.GetUnitOfWork())
{
using (var uow = _uowProvider.GetUnitOfWork())
using (var transaction = uow.Database.GetTransaction())
{
using (var transaction = uow.Database.GetTransaction())
var sortOrderObj =
uow.Database.ExecuteScalar<object>(
"SELECT max(sortorder) FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = dataTypeId });
int sortOrder;
if (sortOrderObj == null || int.TryParse(sortOrderObj.ToString(), out sortOrder) == false)
{
var sortOrderObj =
uow.Database.ExecuteScalar<object>(
"SELECT max(sortorder) FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = dataTypeId });
int sortOrder;
if (sortOrderObj == null || int.TryParse(sortOrderObj.ToString(), out sortOrder) == false)
{
sortOrder = 1;
}
foreach (var value in values)
{
var dto = new DataTypePreValueDto { DataTypeNodeId = dataTypeId, Value = value, SortOrder = sortOrder };
uow.Database.Insert(dto);
sortOrder++;
}
transaction.Complete();
sortOrder = 1;
}
foreach (var value in values)
{
var dto = new DataTypePreValueDto { DataTypeNodeId = dataTypeId, Value = value, SortOrder = sortOrder };
uow.Database.Insert(dto);
sortOrder++;
}
transaction.Complete();
}
}
}
@@ -250,7 +250,9 @@ namespace Umbraco.Core.Services
{
var tab = new XElement("Tab",
new XElement("Id", propertyGroup.Id.ToString(CultureInfo.InvariantCulture)),
new XElement("Caption", propertyGroup.Name));
new XElement("Caption", propertyGroup.Name),
new XElement("SortOrder", propertyGroup.SortOrder));
tabs.Add(tab);
}
@@ -309,9 +311,17 @@ namespace Umbraco.Core.Services
new XElement("AllowAtRoot", contentType.AllowedAsRoot.ToString()),
new XElement("IsListView", contentType.IsContainer.ToString()));
var masterContentType = contentType.CompositionAliases().FirstOrDefault();
if (masterContentType != null)
info.Add(new XElement("Master", masterContentType));
var masterContentType = contentType.ContentTypeComposition.FirstOrDefault(x => x.Id == contentType.ParentId);
if(masterContentType != null)
info.Add(new XElement("Master", masterContentType.Alias));
var compositionsElement = new XElement("Compositions");
var compositions = contentType.ContentTypeComposition;
foreach (var composition in compositions)
{
compositionsElement.Add(new XElement("Composition", composition.Alias));
}
info.Add(compositionsElement);
var allowedTemplates = new XElement("AllowedTemplates");
foreach (var template in contentType.AllowedTemplates)
@@ -319,6 +329,7 @@ namespace Umbraco.Core.Services
allowedTemplates.Add(new XElement("Template", template.Alias));
}
info.Add(allowedTemplates);
if (contentType.DefaultTemplate != null && contentType.DefaultTemplate.Id != 0)
info.Add(new XElement("DefaultTemplate", contentType.DefaultTemplate.Alias));
else
@@ -356,7 +367,8 @@ namespace Umbraco.Core.Services
{
var tab = new XElement("Tab",
new XElement("Id", propertyGroup.Id.ToString(CultureInfo.InvariantCulture)),
new XElement("Caption", propertyGroup.Name));
new XElement("Caption", propertyGroup.Name),
new XElement("SortOrder", propertyGroup.SortOrder));
tabs.Add(tab);
}
+12 -2
View File
@@ -391,10 +391,17 @@ namespace Umbraco.Core.Services
internal IEnumerable<string> GetPartialViewSnippetNames(params string[] filterNames)
{
var snippetPath = IOHelper.MapPath(string.Format("{0}/PartialViewMacros/Templates/", SystemDirectories.Umbraco));
return Directory.GetFiles(snippetPath, "*.cshtml")
var files = Directory.GetFiles(snippetPath, "*.cshtml")
.Select(Path.GetFileNameWithoutExtension)
.Except(filterNames, StringComparer.InvariantCultureIgnoreCase)
.ToArray();
//Ensure the ones that are called 'Empty' are at the top
var empty = files.Where(x => Path.GetFileName(x).InvariantStartsWith("Empty"))
.OrderBy(x => x.Length)
.ToArray();
return empty.Union(files.Except(empty));
}
internal void DeletePartialViewFolder(string folderPath)
@@ -515,7 +522,10 @@ namespace Umbraco.Core.Services
.ToFirstUpperInvariant()
.ToSafeAlias(false);
repository.AddOrUpdate(new Macro(name, name) { ScriptPath = partialView.Path });
//The partial view path to be saved with the macro must be a fully qualified virtual path
var virtualPath = string.Format("{0}/{1}/{2}", SystemDirectories.MvcViews, "MacroPartials", partialView.Path);
repository.AddOrUpdate(new Macro(name, name) { ScriptPath = virtualPath });
}
//commit both - ensure that the macro is created if one was added
@@ -5,7 +5,17 @@ namespace Umbraco.Core.Services
{
public interface IApplicationTreeService
{
void Intitialize(IEnumerable<ApplicationTree> existingTrees);
/// <summary>
/// Initializes the service with any trees found in plugins
/// </summary>
/// <param name="allAvailableTrees">
/// A collection of all available tree found in assemblies in the application
/// </param>
/// <remarks>
/// This will update the trees.config with the found tree plugins that are not currently listed in the file when the first
/// access is made to resolve the tree collection
/// </remarks>
void Intitialize(IEnumerable<ApplicationTree> allAvailableTrees);
/// <summary>
/// Creates a new application tree.
@@ -52,6 +52,14 @@ namespace Umbraco.Core.Services
/// <param name="userId">Id of the user issueing the save</param>
void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId = 0);
/// <summary>
/// Saves a collection of <see cref="IDataTypeDefinition"/>
/// </summary>
/// <param name="dataTypeDefinitions"><see cref="IDataTypeDefinition"/> to save</param>
/// <param name="userId">Id of the user issueing the save</param>
/// <param name="raiseEvents">Boolean indicating whether or not to raise events</param>
void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId, bool raiseEvents);
/// <summary>
/// Deletes an <see cref="IDataTypeDefinition"/>
/// </summary>
+8 -3
View File
@@ -6,10 +6,15 @@ namespace Umbraco.Core.Services
public interface ISectionService
{
/// <summary>
/// Ensures all available sections exist in the storage medium
/// Initializes the service with all available application plugins
/// </summary>
/// <param name="existingSections"></param>
void Initialize(IEnumerable<Section> existingSections);
/// <param name="allAvailableSections">
/// All application plugins found in assemblies
/// </param>
/// <remarks>
/// This is used to populate the app.config file with any applications declared in plugins that don't exist in the file
/// </remarks>
void Initialize(IEnumerable<Section> allAvailableSections);
/// <summary>
/// The cache storage for all applications
+2 -2
View File
@@ -413,7 +413,7 @@ namespace Umbraco.Core.Services
{
var query = Query<IMedia>.Builder;
//if the id is -1, then just get all
if (id > 0)
if (id != -1)
{
query.Where(x => x.ParentId == id);
}
@@ -443,7 +443,7 @@ namespace Umbraco.Core.Services
var query = Query<IMedia>.Builder;
//if the id is -1, then just get all
if (id > 0)
if (id != -1)
{
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
}
+130 -43
View File
@@ -76,7 +76,7 @@ namespace Umbraco.Core.Services
public XElement Export(IContent content, bool deep = false, bool raiseEvents = true)
{
var nodeName = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema ? "node" : content.ContentType.Alias.ToSafeAliasWithForcingCheck();
if (raiseEvents)
{
if (ExportingContent.IsRaisedEventCancelled(new ExportEventArgs<IContent>(content, nodeName), this))
@@ -86,13 +86,13 @@ namespace Umbraco.Core.Services
var exporter = new EntityXmlSerializer();
var xml = exporter.Serialize(_contentService, _dataTypeService, _userService, content, deep);
if(raiseEvents)
if (raiseEvents)
ExportedContent.RaiseEvent(new ExportEventArgs<IContent>(content, xml, false), this);
return xml;
}
/// <summary>
/// Imports and saves package xml as <see cref="IContent"/>
@@ -109,7 +109,7 @@ namespace Umbraco.Core.Services
if (ImportingContent.IsRaisedEventCancelled(new ImportEventArgs<IContent>(element), this))
return Enumerable.Empty<IContent>();
}
var name = element.Name.LocalName;
if (name.Equals("DocumentSet"))
{
@@ -122,7 +122,7 @@ namespace Umbraco.Core.Services
if (contents.Any())
_contentService.Save(contents, userId);
if(raiseEvents)
if (raiseEvents)
ImportedContent.RaiseEvent(new ImportEventArgs<IContent>(contents, element, false), this);
return contents;
}
@@ -136,7 +136,7 @@ namespace Umbraco.Core.Services
if (contents.Any())
_contentService.Save(contents, userId);
if(raiseEvents)
if (raiseEvents)
ImportedContent.RaiseEvent(new ImportEventArgs<IContent>(contents, element, false), this);
return contents;
}
@@ -250,7 +250,7 @@ namespace Umbraco.Core.Services
//TODO: We need to refactor this so the packager isn't making direct db calls for an 'edge' case
var database = ApplicationContext.Current.DatabaseContext.Database;
var dtos = database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new {Id = propertyType.DataTypeDefinitionId});
var dtos = database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = propertyType.DataTypeDefinitionId });
var propertyValueList = new List<string>();
foreach (var preValue in propertyValue.Split(','))
@@ -332,11 +332,62 @@ namespace Umbraco.Core.Services
}
_importedContentTypes = new Dictionary<string, IContentType>();
var documentTypes = name.Equals("DocumentTypes")
var unsortedDocumentTypes = name.Equals("DocumentTypes")
? (from doc in element.Elements("DocumentType") select doc).ToList()
: new List<XElement> { element };
//NOTE it might be an idea to sort the doctype XElements based on dependencies
//before creating the doc types - should also allow for a better structure/inheritance support.
//When you are importing a single doc type we have to assume that the depedencies are already there.
//Otherwise something like uSync won't work.
var fields = new List<TopologicalSorter.DependencyField<XElement>>();
var isSingleDocTypeImport = unsortedDocumentTypes.Count == 1;
if (isSingleDocTypeImport == false)
{
//NOTE Here we sort the doctype XElements based on dependencies
//before creating the doc types - this should also allow for a better structure/inheritance support.
foreach (var documentType in unsortedDocumentTypes)
{
var elementCopy = documentType;
var infoElement = elementCopy.Element("Info");
var dependencies = new List<string>();
//Add the Master as a dependency
if (elementCopy.Element("Master") != null &&
string.IsNullOrEmpty(elementCopy.Element("Master").Value) == false)
{
dependencies.Add(elementCopy.Element("Master").Value);
}
//Add compositions as dependencies
var compositionsElement = infoElement.Element("Compositions");
if (compositionsElement != null && compositionsElement.HasElements)
{
var compositions = compositionsElement.Elements("Composition");
if (compositions.Any())
{
foreach (var composition in compositions)
{
dependencies.Add(composition.Value);
}
}
}
var field = new TopologicalSorter.DependencyField<XElement>
{
Alias = infoElement.Element("Alias").Value,
Item = new Lazy<XElement>(() => elementCopy),
DependsOn = dependencies.ToArray()
};
fields.Add(field);
}
}
//Sorting the Document Types based on dependencies - if its not a single doc type import ref. #U4-5921
var documentTypes = isSingleDocTypeImport
? unsortedDocumentTypes.ToList()
: TopologicalSorter.GetSortedItems(fields).ToList();
//Iterate the sorted document types and create them as IContentType objects
foreach (var documentType in documentTypes)
{
var alias = documentType.Element("Info").Element("Alias").Value;
@@ -349,9 +400,12 @@ namespace Umbraco.Core.Services
}
}
//Save the newly created/updated IContentType objects
var list = _importedContentTypes.Select(x => x.Value).ToList();
_contentTypeService.Save(list, userId);
//Now we can finish the import by updating the 'structure',
//which requires the doc types to be saved/available in the db
if (importStructure)
{
var updatedContentTypes = new List<IContentType>();
@@ -392,15 +446,10 @@ namespace Umbraco.Core.Services
: _contentTypeService.GetContentType(masterAlias);
}
var alias = infoElement.Element("Alias").Value;
var contentType = parent == null
? new ContentType(-1)
{
Alias = infoElement.Element("Alias").Value
}
: new ContentType(parent)
{
Alias = infoElement.Element("Alias").Value
};
? new ContentType(-1) { Alias = alias }
: new ContentType(parent, alias);
if (parent != null)
contentType.AddContentType(parent);
@@ -417,15 +466,47 @@ namespace Umbraco.Core.Services
contentType.Icon = infoElement.Element("Icon").Value;
contentType.Thumbnail = infoElement.Element("Thumbnail").Value;
contentType.Description = infoElement.Element("Description").Value;
//NOTE AllowAtRoot is a new property in the package xml so we need to verify it exists before using it.
var allowAtRoot = infoElement.Element("AllowAtRoot");
if (allowAtRoot != null)
contentType.AllowedAsRoot = allowAtRoot.Value.InvariantEquals("true");
//NOTE IsListView is a new property in the package xml so we need to verify it exists before using it.
var isListView = infoElement.Element("IsListView");
if (isListView != null)
contentType.IsContainer = isListView.Value.InvariantEquals("true");
//Name of the master corresponds to the parent and we need to ensure that the Parent Id is set
var masterElement = infoElement.Element("Master");
if (masterElement != null)
{
var masterAlias = masterElement.Value;
IContentType parent = _importedContentTypes.ContainsKey(masterAlias)
? _importedContentTypes[masterAlias]
: _contentTypeService.GetContentType(masterAlias);
contentType.SetLazyParentId(new Lazy<int>(() => parent.Id));
}
//Update Compositions on the ContentType to ensure that they are as is defined in the package xml
var compositionsElement = infoElement.Element("Compositions");
if (compositionsElement != null && compositionsElement.HasElements)
{
var compositions = compositionsElement.Elements("Composition");
if (compositions.Any())
{
foreach (var composition in compositions)
{
var compositionAlias = composition.Value;
var compositionContentType = _importedContentTypes.ContainsKey(compositionAlias)
? _importedContentTypes[compositionAlias]
: _contentTypeService.GetContentType(compositionAlias);
var added = contentType.AddContentType(compositionContentType);
}
}
}
UpdateContentTypesAllowedTemplates(contentType, infoElement.Element("AllowedTemplates"), defaultTemplateElement);
UpdateContentTypesTabs(contentType, documentType.Element("Tabs"));
UpdateContentTypesProperties(contentType, documentType.Element("GenericProperties"));
@@ -492,13 +573,13 @@ namespace Umbraco.Core.Services
{
contentType.AddPropertyGroup(caption);
int sortOrder;
if(tab.Element("SortOrder") != null &&
int.TryParse(tab.Element("SortOrder").Value, out sortOrder))
{
// Override the sort order with the imported value
contentType.PropertyGroups[caption].SortOrder = sortOrder;
}
}
int sortOrder;
if (tab.Element("SortOrder") != null && int.TryParse(tab.Element("SortOrder").Value, out sortOrder))
{
// Override the sort order with the imported value
contentType.PropertyGroups[caption].SortOrder = sortOrder;
}
}
}
@@ -550,7 +631,7 @@ namespace Umbraco.Core.Services
dataTypeDefinition = dataTypeDefinitions.First();
}
}
// For backwards compatibility, if no datatype with that ID can be found, we're letting this fail silently.
// This means that the property will not be created.
if (dataTypeDefinition == null)
@@ -765,9 +846,15 @@ namespace Umbraco.Core.Services
var list = dataTypes.Select(x => x.Value).ToList();
if (list.Any())
{
_dataTypeService.Save(list, userId);
//NOTE: As long as we have to deal with the two types of PreValue lists (with/without Keys)
//this is a bit of a pain to handle while ensuring that the imported DataTypes has PreValues
//place when triggering the save event.
SavePrevaluesFromXml(list, dataTypeElements);
_dataTypeService.Save(list, userId, false);//Save without raising events
SavePrevaluesFromXml(list, dataTypeElements);//Save the PreValues for the current list of DataTypes
_dataTypeService.Save(list, userId, true);//Re-save and raise events
}
if (raiseEvents)
@@ -787,15 +874,15 @@ namespace Umbraco.Core.Services
var dataTypeDefinition = dataTypes.First(x => x.Name == dataTypeDefinitionName);
var valuesWithoutKeys = prevaluesElement.Elements("PreValue")
.Where(x => ((string) x.Attribute("Alias")).IsNullOrWhiteSpace())
.Where(x => ((string)x.Attribute("Alias")).IsNullOrWhiteSpace())
.Select(x => x.Attribute("Value").Value);
var valuesWithKeys = prevaluesElement.Elements("PreValue")
.Where(x => ((string) x.Attribute("Alias")).IsNullOrWhiteSpace() == false)
.Where(x => ((string)x.Attribute("Alias")).IsNullOrWhiteSpace() == false)
.ToDictionary(
key => (string) key.Attribute("Alias"),
val => new PreValue((string) val.Attribute("Value")));
key => (string)key.Attribute("Alias"),
val => new PreValue((string)val.Attribute("Value")));
//save the values with keys
_dataTypeService.SavePreValues(dataTypeDefinition, valuesWithKeys);
@@ -842,7 +929,7 @@ namespace Umbraco.Core.Services
var exporter = new EntityXmlSerializer();
var xml = exporter.Serialize(dictionaryItem);
if (includeChildren)
{
var children = _localizationService.GetDictionaryItemChildren(dictionaryItem.Key);
@@ -1116,7 +1203,7 @@ namespace Umbraco.Core.Services
dontRender = bool.Parse(dontRenderElement.Value);
}
var existingMacro = _macroService.GetByAlias(macroAlias) as Macro;
var existingMacro = _macroService.GetByAlias(macroAlias) as Macro;
var macro = existingMacro ?? new Macro(macroAlias, macroName, controlType, controlAssembly, xsltPath, scriptPath,
cacheByPage, cacheByMember, dontRender, useInEditor, cacheDuration);
@@ -1211,7 +1298,7 @@ namespace Umbraco.Core.Services
public XElement Export(IMedia media, bool deep = false, bool raiseEvents = true)
{
var nodeName = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema ? "node" : media.ContentType.Alias.ToSafeAliasWithForcingCheck();
if (raiseEvents)
{
if (ExportingMedia.IsRaisedEventCancelled(new ExportEventArgs<IMedia>(media, nodeName), this))
@@ -1221,7 +1308,7 @@ namespace Umbraco.Core.Services
var exporter = new EntityXmlSerializer();
var xml = exporter.Serialize(_mediaService, _dataTypeService, _userService, media, deep);
if(raiseEvents)
if (raiseEvents)
ExportedMedia.RaiseEvent(new ExportEventArgs<IMedia>(media, xml, false), this);
return xml;
@@ -1335,7 +1422,7 @@ namespace Umbraco.Core.Services
if (templates.Any())
_fileService.SaveTemplate(templates, userId);
if(raiseEvents)
if (raiseEvents)
ImportedTemplate.RaiseEvent(new ImportEventArgs<ITemplate>(templates, element, false), this);
return templates;
@@ -1353,10 +1440,10 @@ namespace Umbraco.Core.Services
IEnumerable<IFile> styleSheets = Enumerable.Empty<IFile>();
if(element.Elements().Any())
if (element.Elements().Any())
throw new NotImplementedException("This needs to be implimentet");
if (raiseEvents)
ImportingStylesheets.RaiseEvent(new ImportEventArgs<IFile>(styleSheets, element, false), this);
@@ -1481,7 +1568,7 @@ namespace Umbraco.Core.Services
/// </summary>
public static event TypedEventHandler<IPackagingService, ImportEventArgs<IContent>> ImportedContent;
public static event TypedEventHandler<IPackagingService, ExportEventArgs<IContent>> ExportingContent;
/// <summary>
@@ -1608,7 +1695,7 @@ namespace Umbraco.Core.Services
/// Occurs before Importing Stylesheets
/// </summary>
public static event TypedEventHandler<IPackagingService, ImportEventArgs<IFile>> ImportingStylesheets;
/// <summary>
/// Occurs after Template is Imported and Saved
/// </summary>
@@ -1623,7 +1710,7 @@ namespace Umbraco.Core.Services
/// Occurs after Template is Exported to Xml
/// </summary>
public static event TypedEventHandler<IPackagingService, ExportEventArgs<ITemplate>> ExportedTemplate;
/// <summary>
/// Occurs before Importing umbraco package
/// </summary>
+105 -38
View File
@@ -17,12 +17,19 @@ namespace Umbraco.Core.Services
internal class SectionService : ISectionService
{
private readonly IUserService _userService;
private IEnumerable<Section> _allAvailableSections;
private readonly IApplicationTreeService _applicationTreeService;
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly CacheHelper _cache;
internal const string AppConfigFileName = "applications.config";
private static string _appConfig;
private volatile bool _isInitialized = false;
private static readonly object Locker = new object();
public SectionService(
IUserService userService,
IApplicationTreeService applicationTreeService,
IApplicationTreeService applicationTreeService,
IDatabaseUnitOfWorkProvider uowProvider,
CacheHelper cache)
{
if (applicationTreeService == null) throw new ArgumentNullException("applicationTreeService");
@@ -30,12 +37,11 @@ namespace Umbraco.Core.Services
_userService = userService;
_applicationTreeService = applicationTreeService;
_uowProvider = uowProvider;
_cache = cache;
}
internal const string AppConfigFileName = "applications.config";
private static string _appConfig;
private static readonly object Locker = new object();
/// <summary>
/// gets/sets the application.config file path
@@ -57,22 +63,17 @@ namespace Umbraco.Core.Services
}
/// <summary>
/// Ensures all available sections exist in the storage medium
/// Initializes the service with all available application plugins
/// </summary>
/// <param name="existingSections"></param>
public void Initialize(IEnumerable<Section> existingSections)
/// <param name="allAvailableSections">
/// All application plugins found in assemblies
/// </param>
/// <remarks>
/// This is used to populate the app.config file with any applications declared in plugins that don't exist in the file
/// </remarks>
public void Initialize(IEnumerable<Section> allAvailableSections)
{
LoadXml(doc =>
{
foreach (var attr in existingSections)
{
doc.Root.Add(new XElement("add",
new XAttribute("alias", attr.Alias),
new XAttribute("name", attr.Name),
new XAttribute("icon", attr.Icon),
new XAttribute("sortOrder", attr.SortOrder)));
}
}, true);
_allAvailableSections = allAvailableSections;
}
/// <summary>
@@ -80,7 +81,7 @@ namespace Umbraco.Core.Services
/// </summary>
public IEnumerable<Section> GetSections()
{
return _cache.GetCacheItem(
return _cache.RuntimeCache.GetCacheItem<IEnumerable<Section>>(
CacheKeys.ApplicationsCacheKey,
() =>
{
@@ -88,28 +89,66 @@ namespace Umbraco.Core.Services
//if (_testApps != null)
// return _testApps;
var tmp = new List<Section>();
var list = ReadFromXmlAndSort();
LoadXml(doc =>
//On first access we need to do some initialization
if (_isInitialized == false)
{
lock (Locker)
{
foreach (var addElement in doc.Root.Elements("add").OrderBy(x =>
{
var sortOrderAttr = x.Attribute("sortOrder");
return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0;
}))
if (_isInitialized == false)
{
var sortOrderAttr = addElement.Attribute("sortOrder");
tmp.Add(new Section(addElement.Attribute("name").Value,
addElement.Attribute("alias").Value,
addElement.Attribute("icon").Value,
sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0));
//now we can check the non-volatile flag
if (_allAvailableSections != null)
{
var hasChanges = false;
LoadXml(doc =>
{
//Now, load in the xml structure and update it with anything that is not declared there and save the file.
//NOTE: On the first iteration here, it will lazily scan all apps, etc... this is because this ienumerable is lazy
// based on the ApplicationRegistrar - and as noted there this is not an ideal way to do things but were stuck like this
// currently because of the legacy assemblies and types not in the Core.
//Get all the trees not registered in the config
var unregistered = _allAvailableSections
.Where(x => list.Any(l => l.Alias == x.Alias) == false)
.ToArray();
hasChanges = unregistered.Any();
var count = 0;
foreach (var attr in unregistered)
{
doc.Root.Add(new XElement("add",
new XAttribute("alias", attr.Alias),
new XAttribute("name", attr.Name),
new XAttribute("icon", attr.Icon),
new XAttribute("sortOrder", attr.SortOrder)));
count++;
}
//don't save if there's no changes
return count > 0;
}, true);
if (hasChanges)
{
//If there were changes, we need to re-read the structures from the XML
list = ReadFromXmlAndSort();
}
}
}
}, false);
return tmp;
}
}
return list;
});
}
internal void LoadXml(Action<XDocument> callback, bool saveAfterCallback)
internal void LoadXml(Func<XDocument, bool> callback, bool saveAfterCallbackIfChanged)
{
lock (Locker)
{
@@ -119,9 +158,9 @@ namespace Umbraco.Core.Services
if (doc.Root != null)
{
callback.Invoke(doc);
var changed = callback.Invoke(doc);
if (saveAfterCallback)
if (saveAfterCallbackIfChanged && changed)
{
//ensure the folder is created!
Directory.CreateDirectory(Path.GetDirectoryName(AppConfigFilePath));
@@ -194,6 +233,7 @@ namespace Umbraco.Core.Services
new XAttribute("name", name),
new XAttribute("icon", icon),
new XAttribute("sortOrder", sortOrder)));
return true;
}, true);
//raise event
@@ -209,7 +249,7 @@ namespace Umbraco.Core.Services
lock (Locker)
{
//delete the assigned applications
ApplicationContext.Current.DatabaseContext.Database.Execute(
_uowProvider.GetUnitOfWork().Database.Execute(
"delete from umbracoUser2App where app = @appAlias",
new { appAlias = section.Alias });
@@ -222,7 +262,10 @@ namespace Umbraco.Core.Services
LoadXml(doc =>
{
doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias).Remove();
doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias)
.Remove();
return true;
}, true);
//raise event
@@ -230,6 +273,30 @@ namespace Umbraco.Core.Services
}
}
private List<Section> ReadFromXmlAndSort()
{
var tmp = new List<Section>();
LoadXml(doc =>
{
foreach (var addElement in doc.Root.Elements("add").OrderBy(x =>
{
var sortOrderAttr = x.Attribute("sortOrder");
return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0;
}))
{
var sortOrderAttr = addElement.Attribute("sortOrder");
tmp.Add(new Section(addElement.Attribute("name").Value,
addElement.Attribute("alias").Value,
addElement.Attribute("icon").Value,
sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0));
}
return false;
}, false);
return tmp;
}
internal static event TypedEventHandler<Section, EventArgs> Deleted;
private static void OnDeleted(Section app, EventArgs args)
{
+1 -1
View File
@@ -164,7 +164,7 @@ namespace Umbraco.Core.Services
_treeService = new Lazy<IApplicationTreeService>(() => new ApplicationTreeService(cache));
if (_sectionService == null)
_sectionService = new Lazy<ISectionService>(() => new SectionService(_userService.Value, _treeService.Value, cache));
_sectionService = new Lazy<ISectionService>(() => new SectionService(_userService.Value, _treeService.Value, provider, cache));
if (_macroService == null)
_macroService = new Lazy<IMacroService>(() => new MacroService(provider, repositoryFactory.Value));
@@ -3,6 +3,7 @@ using System.Linq;
using System.Web;
using System.Xml;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
namespace Umbraco.Core.Sync
@@ -17,37 +18,26 @@ namespace Umbraco.Core.Sync
/// status. This will attempt to determine the internal umbraco base url that can be used by the current
/// server to send a request to itself if it is in a load balanced environment.
/// </summary>
/// <returns>The full base url including schema (i.e. http://myserver:80/umbraco )</returns>
public static string GetCurrentServerUmbracoBaseUrl()
/// <returns>The full base url including schema (i.e. http://myserver:80/umbraco ) - or <c>null</c> if the url
/// cannot be determined at the moment (usually because the first request has not properly completed yet).</returns>
public static string GetCurrentServerUmbracoBaseUrl(ApplicationContext appContext, IUmbracoSettingsSection settings)
{
var status = GetStatus();
var status = GetStatus(settings);
if (status == CurrentServerEnvironmentStatus.Single)
{
//if it's a single install, then the base url has to be the first url registered. Use HTTP or HTTPS as appropriate.
if (GlobalSettings.UseSSL)
{
return string.Format("https://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
else
{
return string.Format("http://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
// single install, return null if no config/original url, else use config/original url as base
// use http or https as appropriate
return GetBaseUrl(appContext, settings);
}
var servers = UmbracoConfig.For.UmbracoSettings().DistributedCall.Servers.ToArray();
var servers = settings.DistributedCall.Servers.ToArray();
if (servers.Any() == false)
{
//cannot be determined, then the base url has to be the first url registered. Use HTTP or HTTPS as appropriate.
if (GlobalSettings.UseSSL)
{
return string.Format("https://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
else
{
return string.Format("http://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
// cannot be determined, return null if no config/original url, else use config/original url as base
// use http or https as appropriate
return GetBaseUrl(appContext, settings);
}
foreach (var server in servers)
@@ -72,29 +62,23 @@ namespace Umbraco.Core.Sync
}
}
//cannot be determined, then the base url has to be the first url registered. Use HTTP or HTTPS as appropriate.
if (GlobalSettings.UseSSL)
{
return string.Format("https://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
else
{
return string.Format("http://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
// cannot be determined, return null if no config/original url, else use config/original url as base
// use http or https as appropriate
return GetBaseUrl(appContext, settings);
}
/// <summary>
/// Returns the current environment status for the current server
/// </summary>
/// <returns></returns>
public static CurrentServerEnvironmentStatus GetStatus()
public static CurrentServerEnvironmentStatus GetStatus(IUmbracoSettingsSection settings)
{
if (UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled == false)
if (settings.DistributedCall.Enabled == false)
{
return CurrentServerEnvironmentStatus.Single;
}
var servers = UmbracoConfig.For.UmbracoSettings().DistributedCall.Servers.ToArray();
var servers = settings.DistributedCall.Servers.ToArray();
if (servers.Any() == false)
{
@@ -129,5 +113,21 @@ namespace Umbraco.Core.Sync
return CurrentServerEnvironmentStatus.Slave;
}
private static string GetBaseUrl(ApplicationContext appContext, IUmbracoSettingsSection settings)
{
return (
// is config empty?
settings.ScheduledTasks.BaseUrl.IsNullOrWhiteSpace()
// is the orig req empty?
? appContext.OriginalRequestUrl.IsNullOrWhiteSpace()
// we've got nothing
? null
//the orig req url is not null, use that
: string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", appContext.OriginalRequestUrl)
// the config has been specified, use that
: string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", settings.ScheduledTasks.BaseUrl))
.EnsureEndsWith('/');
}
}
}
+37 -18
View File
@@ -15,6 +15,7 @@ using System.Web.Compilation;
using System.Web.Hosting;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core
{
@@ -450,14 +451,23 @@ namespace Umbraco.Core
var allTypes = GetTypesWithFormattedException(a)
.ToArray();
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes but have
//the specified attribute
var attributedTypes = allTypes
.Where(t => (TypeHelper.IsNonStaticClass(t)
&& (onlyConcreteClasses == false || t.IsAbstract == false))
//the type must have this attribute
&& t.GetCustomAttributes(attributeType, false).Any())
.ToArray();
var attributedTypes = new Type[] {};
try
{
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes but have
//the specified attribute
attributedTypes = allTypes
.Where(t => (TypeHelper.IsNonStaticClass(t)
&& (onlyConcreteClasses == false || t.IsAbstract == false))
//the type must have this attribute
&& t.GetCustomAttributes(attributeType, false).Any())
.ToArray();
}
catch (TypeLoadException ex)
{
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", a), ex);
continue;
}
//add the types to our list to return
foreach (var t in attributedTypes)
@@ -583,16 +593,25 @@ namespace Umbraco.Core
.Where(assignTypeFrom.IsAssignableFrom)
.ToArray();
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes
var filteredTypes = allSubTypes
.Where(t => (TypeHelper.IsNonStaticClass(t)
//Do not include nested private classes - since we are in full trust now this will find those too!
&& t.IsNestedPrivate == false
&& (onlyConcreteClasses == false || t.IsAbstract == false)
//Do not include classes that are flagged to hide from the type finder
&& t.GetCustomAttribute<HideFromTypeFinderAttribute>() == null
&& additionalFilter(t)))
.ToArray();
var filteredTypes = new Type[] { };
try
{
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes
filteredTypes = allSubTypes
.Where(t => (TypeHelper.IsNonStaticClass(t)
//Do not include nested private classes - since we are in full trust now this will find those too!
&& t.IsNestedPrivate == false
&& (onlyConcreteClasses == false || t.IsAbstract == false)
//Do not include classes that are flagged to hide from the type finder
&& t.GetCustomAttribute<HideFromTypeFinderAttribute>() == null
&& additionalFilter(t)))
.ToArray();
}
catch (TypeLoadException ex)
{
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", a), ex);
continue;
}
//add the types to our list to return
foreach (var t in filteredTypes)
+4 -2
View File
@@ -99,9 +99,9 @@
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.Helpers.dll</HintPath>
</Reference>
<Reference Include="System.Web.Mvc, Version=4.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.40804.0\lib\net40\System.Web.Mvc.dll</HintPath>
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
@@ -393,7 +393,9 @@
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwoZero\AddMissingForeignKeyForContentType.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwoZero\AlterDataTypePreValueTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenOneZero\AssignMissingPrimaryForMySqlKeys.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwoZero\AddIndexToUmbracoNodeTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwoZero\RemoveCmsDocumentAliasColumn.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSeven\AssignMissingKeysAndIndexes.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSixTwoZero\AssignMissingPrimaryForMySqlKeys.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSixTwoZero\AssignMissingPrimaryForMySqlKeys2.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSixTwoZero\ChangePasswordColumn.cs" />
+1 -1
View File
@@ -8,7 +8,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+1 -1
View File
@@ -3,7 +3,7 @@
<package id="AutoMapper" version="3.0.0" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net45" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Mvc" version="4.0.40804.0" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net40" />
<package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="2.0.30506.0" targetFramework="net40" />
+1 -1
View File
@@ -100,7 +100,7 @@
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
@@ -1,120 +1,119 @@
using System.Configuration;
using System.Web.Routing;
using NUnit.Framework;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Tests.TestHelpers;
using System.Web.Mvc;
namespace Umbraco.Tests
{
[TestFixture]
public class GlobalSettingsTests : BaseWebTest
{
public override void Initialize()
{
base.Initialize();
SettingsForTests.UmbracoPath = "~/umbraco";
}
public override void TearDown()
{
//ensure this is reset
SystemDirectories.Root = null;
SettingsForTests.UmbracoPath = "~/umbraco";
//reset the app config
base.TearDown();
}
[Test]
public void Is_Debug_Mode()
{
Assert.That(Umbraco.Core.Configuration.GlobalSettings.DebugMode, Is.EqualTo(true));
}
[Ignore]
[Test]
public void Is_Version_From_Assembly_Correct()
{
Assert.That(UmbracoVersion.Current.ToString(3), Is.EqualTo("6.0.0"));
}
[TestCase("~/umbraco", "/", "umbraco")]
[TestCase("~/umbraco", "/MyVirtualDir", "umbraco")]
[TestCase("~/customPath", "/MyVirtualDir/", "custompath")]
[TestCase("~/some-wacky/nestedPath", "/MyVirtualDir", "some-wacky-nestedpath")]
[TestCase("~/some-wacky/nestedPath", "/MyVirtualDir/NestedVDir/", "some-wacky-nestedpath")]
public void Umbraco_Mvc_Area(string path, string rootPath, string outcome)
{
SettingsForTests.UmbracoPath = path;
SystemDirectories.Root = rootPath;
Assert.AreEqual(outcome, Umbraco.Core.Configuration.GlobalSettings.UmbracoMvcArea);
}
[TestCase("/umbraco/umbraco.aspx")]
[TestCase("/umbraco/editContent.aspx")]
[TestCase("/install/default.aspx")]
[TestCase("/install/")]
[TestCase("/install")]
[TestCase("/install/?installStep=asdf")]
[TestCase("/install/test.aspx")]
[TestCase("/config/splashes/booting.aspx")]
public void Is_Reserved_Path_Or_Url(string url)
{
Assert.IsTrue(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url));
}
[TestCase("/umbraco_client/Tree/treeIcons.css")]
[TestCase("/umbraco_client/Tree/Themes/umbraco/style.css")]
[TestCase("/umbraco_client/scrollingmenu/style.css")]
[TestCase("/base/somebasehandler")]
[TestCase("/")]
[TestCase("/home.aspx")]
[TestCase("/umbraco-test")]
[TestCase("/install-test")]
[TestCase("/install.aspx")]
public void Is_Not_Reserved_Path_Or_Url(string url)
{
Assert.IsFalse(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url));
}
[TestCase("/Do/Not/match", false)]
[TestCase("/Umbraco/RenderMvcs", false)]
[TestCase("/Umbraco/RenderMvc", true)]
[TestCase("/Umbraco/RenderMvc/Index", true)]
[TestCase("/Umbraco/RenderMvc/Index/1234", true)]
[TestCase("/Umbraco/RenderMvc/Index/1234/9876", false)]
[TestCase("/api", true)]
[TestCase("/api/WebApiTest", true)]
[TestCase("/api/WebApiTest/1234", true)]
[TestCase("/api/WebApiTest/Index/1234", false)]
public void Is_Reserved_By_Route(string url, bool shouldMatch)
{
//reset the app config, we only want to test routes not the hard coded paths
Umbraco.Core.Configuration.GlobalSettings.ReservedPaths = "";
Umbraco.Core.Configuration.GlobalSettings.ReservedUrls = "";
var routes = new RouteCollection();
routes.MapRoute(
"Umbraco_default",
"Umbraco/RenderMvc/{action}/{id}",
new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional });
routes.MapRoute(
"WebAPI",
"api/{controller}/{id}",
new { controller = "WebApiTestController", action = "Index", id = UrlParameter.Optional });
var context = new FakeHttpContextFactory(url);
Assert.AreEqual(
shouldMatch,
Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url, context.HttpContext, routes));
}
}
using System.Web.Mvc;
using System.Web.Routing;
using NUnit.Framework;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Configurations
{
[TestFixture]
public class GlobalSettingsTests : BaseWebTest
{
public override void Initialize()
{
base.Initialize();
SettingsForTests.UmbracoPath = "~/umbraco";
}
public override void TearDown()
{
//ensure this is reset
SystemDirectories.Root = null;
SettingsForTests.UmbracoPath = "~/umbraco";
//reset the app config
base.TearDown();
}
[Test]
public void Is_Debug_Mode()
{
Assert.That(Umbraco.Core.Configuration.GlobalSettings.DebugMode, Is.EqualTo(true));
}
[Ignore]
[Test]
public void Is_Version_From_Assembly_Correct()
{
Assert.That(UmbracoVersion.Current.ToString(3), Is.EqualTo("6.0.0"));
}
[TestCase("~/umbraco", "/", "umbraco")]
[TestCase("~/umbraco", "/MyVirtualDir", "umbraco")]
[TestCase("~/customPath", "/MyVirtualDir/", "custompath")]
[TestCase("~/some-wacky/nestedPath", "/MyVirtualDir", "some-wacky-nestedpath")]
[TestCase("~/some-wacky/nestedPath", "/MyVirtualDir/NestedVDir/", "some-wacky-nestedpath")]
public void Umbraco_Mvc_Area(string path, string rootPath, string outcome)
{
SettingsForTests.UmbracoPath = path;
SystemDirectories.Root = rootPath;
Assert.AreEqual(outcome, Umbraco.Core.Configuration.GlobalSettings.UmbracoMvcArea);
}
[TestCase("/umbraco/umbraco.aspx")]
[TestCase("/umbraco/editContent.aspx")]
[TestCase("/install/default.aspx")]
[TestCase("/install/")]
[TestCase("/install")]
[TestCase("/install/?installStep=asdf")]
[TestCase("/install/test.aspx")]
[TestCase("/config/splashes/booting.aspx")]
public void Is_Reserved_Path_Or_Url(string url)
{
Assert.IsTrue(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url));
}
[TestCase("/umbraco_client/Tree/treeIcons.css")]
[TestCase("/umbraco_client/Tree/Themes/umbraco/style.css")]
[TestCase("/umbraco_client/scrollingmenu/style.css")]
[TestCase("/base/somebasehandler")]
[TestCase("/")]
[TestCase("/home.aspx")]
[TestCase("/umbraco-test")]
[TestCase("/install-test")]
[TestCase("/install.aspx")]
public void Is_Not_Reserved_Path_Or_Url(string url)
{
Assert.IsFalse(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url));
}
[TestCase("/Do/Not/match", false)]
[TestCase("/Umbraco/RenderMvcs", false)]
[TestCase("/Umbraco/RenderMvc", true)]
[TestCase("/Umbraco/RenderMvc/Index", true)]
[TestCase("/Umbraco/RenderMvc/Index/1234", true)]
[TestCase("/Umbraco/RenderMvc/Index/1234/9876", false)]
[TestCase("/api", true)]
[TestCase("/api/WebApiTest", true)]
[TestCase("/api/WebApiTest/1234", true)]
[TestCase("/api/WebApiTest/Index/1234", false)]
public void Is_Reserved_By_Route(string url, bool shouldMatch)
{
//reset the app config, we only want to test routes not the hard coded paths
Umbraco.Core.Configuration.GlobalSettings.ReservedPaths = "";
Umbraco.Core.Configuration.GlobalSettings.ReservedUrls = "";
var routes = new RouteCollection();
routes.MapRoute(
"Umbraco_default",
"Umbraco/RenderMvc/{action}/{id}",
new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional });
routes.MapRoute(
"WebAPI",
"api/{controller}/{id}",
new { controller = "WebApiTestController", action = "Index", id = UrlParameter.Optional });
var context = new FakeHttpContextFactory(url);
Assert.AreEqual(
shouldMatch,
Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url, context.HttpContext, routes));
}
}
}
@@ -1,90 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Surface
{
[TestFixture]
public class PluginControllerAreaTests : BaseWebTest
{
[Test]
public void Ensure_Same_Area1()
{
Assert.Throws<InvalidOperationException>(() =>
new PluginControllerArea(new PluginControllerMetadata[]
{
PluginController.GetMetadata(typeof(Plugin1Controller)),
PluginController.GetMetadata(typeof(Plugin2Controller)),
PluginController.GetMetadata(typeof(Plugin3Controller)) //not same area
}));
}
[Test]
public void Ensure_Same_Area3()
{
Assert.Throws<InvalidOperationException>(() =>
new PluginControllerArea(new PluginControllerMetadata[]
{
PluginController.GetMetadata(typeof(Plugin1Controller)),
PluginController.GetMetadata(typeof(Plugin2Controller)),
PluginController.GetMetadata(typeof(Plugin4Controller)) //no area assigned
}));
}
[Test]
public void Ensure_Same_Area2()
{
var area = new PluginControllerArea(new PluginControllerMetadata[]
{
PluginController.GetMetadata(typeof(Plugin1Controller)),
PluginController.GetMetadata(typeof(Plugin2Controller))
});
Assert.Pass();
}
#region Test classes
[PluginController("Area1")]
public class Plugin1Controller : PluginController
{
public Plugin1Controller(UmbracoContext umbracoContext) : base(umbracoContext)
{
}
}
[PluginController("Area1")]
public class Plugin2Controller : PluginController
{
public Plugin2Controller(UmbracoContext umbracoContext)
: base(umbracoContext)
{
}
}
[PluginController("Area2")]
public class Plugin3Controller : PluginController
{
public Plugin3Controller(UmbracoContext umbracoContext)
: base(umbracoContext)
{
}
}
public class Plugin4Controller : PluginController
{
public Plugin4Controller(UmbracoContext umbracoContext)
: base(umbracoContext)
{
}
}
#endregion
}
}
using System;
using NUnit.Framework;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Controllers
{
[TestFixture]
public class PluginControllerAreaTests : BaseWebTest
{
[Test]
public void Ensure_Same_Area1()
{
Assert.Throws<InvalidOperationException>(() =>
new PluginControllerArea(new PluginControllerMetadata[]
{
PluginController.GetMetadata(typeof(Plugin1Controller)),
PluginController.GetMetadata(typeof(Plugin2Controller)),
PluginController.GetMetadata(typeof(Plugin3Controller)) //not same area
}));
}
[Test]
public void Ensure_Same_Area3()
{
Assert.Throws<InvalidOperationException>(() =>
new PluginControllerArea(new PluginControllerMetadata[]
{
PluginController.GetMetadata(typeof(Plugin1Controller)),
PluginController.GetMetadata(typeof(Plugin2Controller)),
PluginController.GetMetadata(typeof(Plugin4Controller)) //no area assigned
}));
}
[Test]
public void Ensure_Same_Area2()
{
var area = new PluginControllerArea(new PluginControllerMetadata[]
{
PluginController.GetMetadata(typeof(Plugin1Controller)),
PluginController.GetMetadata(typeof(Plugin2Controller))
});
Assert.Pass();
}
#region Test classes
[PluginController("Area1")]
public class Plugin1Controller : PluginController
{
public Plugin1Controller(UmbracoContext umbracoContext) : base(umbracoContext)
{
}
}
[PluginController("Area1")]
public class Plugin2Controller : PluginController
{
public Plugin2Controller(UmbracoContext umbracoContext)
: base(umbracoContext)
{
}
}
[PluginController("Area2")]
public class Plugin3Controller : PluginController
{
public Plugin3Controller(UmbracoContext umbracoContext)
: base(umbracoContext)
{
}
}
public class Plugin4Controller : PluginController
{
public Plugin4Controller(UmbracoContext umbracoContext)
: base(umbracoContext)
{
}
}
#endregion
}
}
@@ -1,211 +1,210 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Sync;
using Umbraco.Web.Cache;
using umbraco.interfaces;
namespace Umbraco.Tests.Sync
{
/// <summary>
/// Ensures that calls to DistributedCache methods carry through to the IServerMessenger correctly
/// </summary>
[TestFixture]
public class DistributedCacheTests
{
[SetUp]
public void Setup()
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
new TestServerRegistrar());
ServerMessengerResolver.Current = new ServerMessengerResolver(
new TestServerMessenger());
CacheRefreshersResolver.Current = new CacheRefreshersResolver(() => new[] { typeof(TestCacheRefresher) });
Resolution.Freeze();
}
[TearDown]
public void Teardown()
{
ServerRegistrarResolver.Reset();
ServerMessengerResolver.Reset();
CacheRefreshersResolver.Reset();
}
[Test]
public void RefreshIntId()
{
for (var i = 1; i < 11; i++)
{
DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
}
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
}
[Test]
public void RefreshIntIdFromObject()
{
for (var i = 0; i < 10; i++)
{
DistributedCache.Instance.Refresh(
Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"),
x => x.Id,
new TestObjectWithId{Id = i});
}
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
}
[Test]
public void RefreshGuidId()
{
for (var i = 0; i < 11; i++)
{
DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid());
}
Assert.AreEqual(11, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).GuidIdsRefreshed.Count);
}
[Test]
public void RemoveIds()
{
for (var i = 1; i < 13; i++)
{
DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
}
Assert.AreEqual(12, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRemoved.Count);
}
[Test]
public void FullRefreshes()
{
for (var i = 0; i < 13; i++)
{
DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"));
}
Assert.AreEqual(13, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).CountOfFullRefreshes);
}
#region internal test classes
internal class TestObjectWithId
{
public int Id { get; set; }
}
internal class TestCacheRefresher : ICacheRefresher
{
public Guid UniqueIdentifier
{
get { return Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"); }
}
public string Name
{
get { return "Test"; }
}
public void RefreshAll()
{
}
public void Refresh(int id)
{
}
public void Remove(int id)
{
}
public void Refresh(Guid id)
{
}
}
internal class TestServerMessenger : IServerMessenger
{
//used for tests
public List<int> IntIdsRefreshed = new List<int>();
public List<Guid> GuidIdsRefreshed = new List<Guid>();
public List<int> IntIdsRemoved = new List<int>();
public List<string> PayloadsRemoved = new List<string>();
public List<string> PayloadsRefreshed = new List<string>();
public int CountOfFullRefreshes = 0;
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, string jsonPayload)
{
PayloadsRefreshed.Add(jsonPayload);
}
public void PerformRefresh<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, int> getNumericId, params T[] instances)
{
IntIdsRefreshed.AddRange(instances.Select(getNumericId));
}
public void PerformRefresh<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, Guid> getGuidId, params T[] instances)
{
GuidIdsRefreshed.AddRange(instances.Select(getGuidId));
}
public void PerformRemove(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, string jsonPayload)
{
PayloadsRemoved.Add(jsonPayload);
}
public void PerformRemove<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, int> getNumericId, params T[] instances)
{
IntIdsRemoved.AddRange(instances.Select(getNumericId));
}
public void PerformRemove(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params int[] numericIds)
{
IntIdsRemoved.AddRange(numericIds);
}
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params int[] numericIds)
{
IntIdsRefreshed.AddRange(numericIds);
}
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params Guid[] guidIds)
{
GuidIdsRefreshed.AddRange(guidIds);
}
public void PerformRefreshAll(IEnumerable<IServerAddress> servers, ICacheRefresher refresher)
{
CountOfFullRefreshes++;
}
}
internal class TestServerRegistrar : IServerRegistrar
{
public IEnumerable<IServerAddress> Registrations
{
get
{
return new List<IServerAddress>()
{
new TestServerAddress("localhost")
};
}
}
}
public class TestServerAddress : IServerAddress
{
public TestServerAddress(string address)
{
ServerAddress = address;
}
public string ServerAddress { get; private set; }
}
#endregion
}
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Sync;
using umbraco.interfaces;
namespace Umbraco.Tests.DistributedCache
{
/// <summary>
/// Ensures that calls to DistributedCache methods carry through to the IServerMessenger correctly
/// </summary>
[TestFixture]
public class DistributedCacheTests
{
[SetUp]
public void Setup()
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
new TestServerRegistrar());
ServerMessengerResolver.Current = new ServerMessengerResolver(
new TestServerMessenger());
CacheRefreshersResolver.Current = new CacheRefreshersResolver(() => new[] { typeof(TestCacheRefresher) });
Resolution.Freeze();
}
[TearDown]
public void Teardown()
{
ServerRegistrarResolver.Reset();
ServerMessengerResolver.Reset();
CacheRefreshersResolver.Reset();
}
[Test]
public void RefreshIntId()
{
for (var i = 1; i < 11; i++)
{
Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
}
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
}
[Test]
public void RefreshIntIdFromObject()
{
for (var i = 0; i < 10; i++)
{
Web.Cache.DistributedCache.Instance.Refresh(
Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"),
x => x.Id,
new TestObjectWithId{Id = i});
}
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
}
[Test]
public void RefreshGuidId()
{
for (var i = 0; i < 11; i++)
{
Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid());
}
Assert.AreEqual(11, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).GuidIdsRefreshed.Count);
}
[Test]
public void RemoveIds()
{
for (var i = 1; i < 13; i++)
{
Web.Cache.DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
}
Assert.AreEqual(12, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRemoved.Count);
}
[Test]
public void FullRefreshes()
{
for (var i = 0; i < 13; i++)
{
Web.Cache.DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"));
}
Assert.AreEqual(13, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).CountOfFullRefreshes);
}
#region internal test classes
internal class TestObjectWithId
{
public int Id { get; set; }
}
internal class TestCacheRefresher : ICacheRefresher
{
public Guid UniqueIdentifier
{
get { return Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"); }
}
public string Name
{
get { return "Test"; }
}
public void RefreshAll()
{
}
public void Refresh(int id)
{
}
public void Remove(int id)
{
}
public void Refresh(Guid id)
{
}
}
internal class TestServerMessenger : IServerMessenger
{
//used for tests
public List<int> IntIdsRefreshed = new List<int>();
public List<Guid> GuidIdsRefreshed = new List<Guid>();
public List<int> IntIdsRemoved = new List<int>();
public List<string> PayloadsRemoved = new List<string>();
public List<string> PayloadsRefreshed = new List<string>();
public int CountOfFullRefreshes = 0;
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, string jsonPayload)
{
PayloadsRefreshed.Add(jsonPayload);
}
public void PerformRefresh<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, int> getNumericId, params T[] instances)
{
IntIdsRefreshed.AddRange(instances.Select(getNumericId));
}
public void PerformRefresh<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, Guid> getGuidId, params T[] instances)
{
GuidIdsRefreshed.AddRange(instances.Select(getGuidId));
}
public void PerformRemove(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, string jsonPayload)
{
PayloadsRemoved.Add(jsonPayload);
}
public void PerformRemove<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, int> getNumericId, params T[] instances)
{
IntIdsRemoved.AddRange(instances.Select(getNumericId));
}
public void PerformRemove(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params int[] numericIds)
{
IntIdsRemoved.AddRange(numericIds);
}
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params int[] numericIds)
{
IntIdsRefreshed.AddRange(numericIds);
}
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params Guid[] guidIds)
{
GuidIdsRefreshed.AddRange(guidIds);
}
public void PerformRefreshAll(IEnumerable<IServerAddress> servers, ICacheRefresher refresher)
{
CountOfFullRefreshes++;
}
}
internal class TestServerRegistrar : IServerRegistrar
{
public IEnumerable<IServerAddress> Registrations
{
get
{
return new List<IServerAddress>()
{
new TestServerAddress("localhost")
};
}
}
}
public class TestServerAddress : IServerAddress
{
public TestServerAddress(string address)
{
ServerAddress = address;
}
public string ServerAddress { get; private set; }
}
#endregion
}
}
@@ -1,162 +1,158 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using Umbraco.Core.Dynamics;
using Umbraco.Web.Dynamics;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Dynamics
{
//NOTE: there's libraries in both Umbraco.Core.Dynamics and Umbraco.Web.Dynamics - the reason for this is that the Web.Dynamics
// started with the razor macro implementation and is modified with hard coded references to dynamic node and dynamic null, though it seems
// to still work for other regular classes I don't want to move it to the core without removing these references but that would require a lot of work.
[TestFixture]
public class QueryableExtensionTests
{
[Test]
public void Order_By_Test_Int()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().OrderBy("Age").ToArray();
Assert.AreEqual(10, result.ElementAt(0).Age);
Assert.AreEqual(11, result.ElementAt(1).Age);
Assert.AreEqual(12, result.ElementAt(2).Age);
Assert.AreEqual(20, result.ElementAt(3).Age);
Assert.AreEqual(31, result.ElementAt(4).Age);
Assert.AreEqual(55, result.ElementAt(5).Age);
}
[Test]
public void Order_By_Test_String()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().OrderBy("Name").ToArray();
Assert.AreEqual("anothertest", result.ElementAt(0).Name);
Assert.AreEqual("blah", result.ElementAt(1).Name);
Assert.AreEqual("someguy", result.ElementAt(2).Name);
Assert.AreEqual("test1", result.ElementAt(3).Name);
Assert.AreEqual("test2", result.ElementAt(4).Name);
Assert.AreEqual("test3", result.ElementAt(5).Name);
}
[Test]
public void Where_Test_String()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().Where("Name = \"test1\"").ToArray();
Assert.AreEqual(1, result.Count());
Assert.AreEqual("test1", result.ElementAt(0).Name);
}
[Test]
public void Where_Test_String_With_Params()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
//NOTE: Currently the object query structure is not supported
//var result = items.AsQueryable().Where("Name = @name", new {name = "test1"}).ToArray();
var result = items.AsQueryable().Where("Name = @Name", new Dictionary<string, object> { { "Name", "test1" } }).ToArray();
Assert.AreEqual(1, result.Count());
Assert.AreEqual("test1", result.ElementAt(0).Name);
}
[Test]
public void Where_Test_Int_With_Params()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().Where("Age = @Age", new Dictionary<string, object> { { "Age", 10 } }).ToArray();
Assert.AreEqual(1, result.Count());
Assert.AreEqual("test1", result.ElementAt(0).Name);
}
[Test]
public void Where_Test_Bool_With_Params()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().Where("Female = @Female", new Dictionary<string, object> { { "Female", true } }).ToArray();
Assert.AreEqual(2, result.Count());
}
private class TestModel
{
public string Name { get; set; }
public int Age { get; set; }
public bool Female { get; set; }
}
}
}
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core.Dynamics;
using Umbraco.Web.Dynamics;
namespace Umbraco.Tests.DynamicsAndReflection
{
//NOTE: there's libraries in both Umbraco.Core.Dynamics and Umbraco.Web.Dynamics - the reason for this is that the Web.Dynamics
// started with the razor macro implementation and is modified with hard coded references to dynamic node and dynamic null, though it seems
// to still work for other regular classes I don't want to move it to the core without removing these references but that would require a lot of work.
[TestFixture]
public class QueryableExtensionTests
{
[Test]
public void Order_By_Test_Int()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().OrderBy("Age").ToArray();
Assert.AreEqual(10, result.ElementAt(0).Age);
Assert.AreEqual(11, result.ElementAt(1).Age);
Assert.AreEqual(12, result.ElementAt(2).Age);
Assert.AreEqual(20, result.ElementAt(3).Age);
Assert.AreEqual(31, result.ElementAt(4).Age);
Assert.AreEqual(55, result.ElementAt(5).Age);
}
[Test]
public void Order_By_Test_String()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().OrderBy("Name").ToArray();
Assert.AreEqual("anothertest", result.ElementAt(0).Name);
Assert.AreEqual("blah", result.ElementAt(1).Name);
Assert.AreEqual("someguy", result.ElementAt(2).Name);
Assert.AreEqual("test1", result.ElementAt(3).Name);
Assert.AreEqual("test2", result.ElementAt(4).Name);
Assert.AreEqual("test3", result.ElementAt(5).Name);
}
[Test]
public void Where_Test_String()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().Where("Name = \"test1\"").ToArray();
Assert.AreEqual(1, result.Count());
Assert.AreEqual("test1", result.ElementAt(0).Name);
}
[Test]
public void Where_Test_String_With_Params()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
//NOTE: Currently the object query structure is not supported
//var result = items.AsQueryable().Where("Name = @name", new {name = "test1"}).ToArray();
var result = items.AsQueryable().Where("Name = @Name", new Dictionary<string, object> { { "Name", "test1" } }).ToArray();
Assert.AreEqual(1, result.Count());
Assert.AreEqual("test1", result.ElementAt(0).Name);
}
[Test]
public void Where_Test_Int_With_Params()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().Where("Age = @Age", new Dictionary<string, object> { { "Age", 10 } }).ToArray();
Assert.AreEqual(1, result.Count());
Assert.AreEqual("test1", result.ElementAt(0).Name);
}
[Test]
public void Where_Test_Bool_With_Params()
{
var items = new List<TestModel>
{
new TestModel {Age = 10, Name = "test1", Female = false},
new TestModel {Age = 31, Name = "someguy", Female = true},
new TestModel {Age = 11, Name = "test2", Female = true},
new TestModel {Age = 20, Name = "anothertest", Female = false},
new TestModel {Age = 55, Name = "blah", Female = false},
new TestModel {Age = 12, Name = "test3", Female = false}
};
var result = items.AsQueryable().Where("Female = @Female", new Dictionary<string, object> { { "Female", true } }).ToArray();
Assert.AreEqual(2, result.Count());
}
private class TestModel
{
public string Name { get; set; }
public int Age { get; set; }
public bool Female { get; set; }
}
}
}
@@ -1,139 +1,139 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Tests.TestHelpers;
using umbraco.cms.businesslogic.macro;
using umbraco.interfaces;
namespace Umbraco.Tests
{
[TestFixture]
public class MacroEngineFactoryTests
{
[SetUp]
public void Initialize()
{
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
{
this.GetType().Assembly
};
}
[TearDown]
public void TearDown()
{
PluginManager.Current = null;
}
[Test]
public void Get_All()
{
var engines = MacroEngineFactory.GetAll();
Assert.AreEqual(2, engines.Count());
}
[Test]
public void Get_Engine()
{
var engine1 = MacroEngineFactory.GetEngine("MacroEngine1");
Assert.IsNotNull(engine1);
}
[Test]
public void Get_By_Filename()
{
var engine1 = MacroEngineFactory.GetByFilename("test.me1");
var engine2 = MacroEngineFactory.GetByFilename("test.me2");
Assert.IsNotNull(engine1);
Assert.IsNotNull(engine2);
Assert.Throws<MacroEngineException>(() => MacroEngineFactory.GetByFilename("test.blah"));
}
[Test]
public void Get_By_Extension()
{
var engine1 = MacroEngineFactory.GetByExtension("me1");
var engine2 = MacroEngineFactory.GetByExtension("me2");
Assert.IsNotNull(engine1);
Assert.IsNotNull(engine2);
Assert.Throws<MacroEngineException>(() => MacroEngineFactory.GetByExtension("blah"));
}
#region Classes for tests
public class MacroEngine1 : IMacroEngine
{
public string Name
{
get { return "MacroEngine1"; }
}
public IEnumerable<string> SupportedExtensions
{
get { return new[] {"me1"}; }
}
public IEnumerable<string> SupportedUIExtensions
{
get { throw new NotImplementedException(); }
}
public Dictionary<string, IMacroGuiRendering> SupportedProperties
{
get { throw new NotImplementedException(); }
}
public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage)
{
throw new NotImplementedException();
}
public string Execute(MacroModel macro, INode currentPage)
{
throw new NotImplementedException();
}
}
public class MacroEngine2 : IMacroEngine
{
public string Name
{
get { return "MacroEngine2"; }
}
public IEnumerable<string> SupportedExtensions
{
get { return new[] { "me2" }; }
}
public IEnumerable<string> SupportedUIExtensions
{
get { throw new NotImplementedException(); }
}
public Dictionary<string, IMacroGuiRendering> SupportedProperties
{
get { throw new NotImplementedException(); }
}
public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage)
{
throw new NotImplementedException();
}
public string Execute(MacroModel macro, INode currentPage)
{
throw new NotImplementedException();
}
}
#endregion
}
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using umbraco.cms.businesslogic.macro;
using Umbraco.Core;
using umbraco.interfaces;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Macros
{
[TestFixture]
public class MacroEngineFactoryTests
{
[SetUp]
public void Initialize()
{
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
{
this.GetType().Assembly
};
}
[TearDown]
public void TearDown()
{
PluginManager.Current = null;
}
[Test]
public void Get_All()
{
var engines = MacroEngineFactory.GetAll();
Assert.AreEqual(2, engines.Count());
}
[Test]
public void Get_Engine()
{
var engine1 = MacroEngineFactory.GetEngine("MacroEngine1");
Assert.IsNotNull(engine1);
}
[Test]
public void Get_By_Filename()
{
var engine1 = MacroEngineFactory.GetByFilename("test.me1");
var engine2 = MacroEngineFactory.GetByFilename("test.me2");
Assert.IsNotNull(engine1);
Assert.IsNotNull(engine2);
Assert.Throws<MacroEngineException>(() => MacroEngineFactory.GetByFilename("test.blah"));
}
[Test]
public void Get_By_Extension()
{
var engine1 = MacroEngineFactory.GetByExtension("me1");
var engine2 = MacroEngineFactory.GetByExtension("me2");
Assert.IsNotNull(engine1);
Assert.IsNotNull(engine2);
Assert.Throws<MacroEngineException>(() => MacroEngineFactory.GetByExtension("blah"));
}
#region Classes for tests
public class MacroEngine1 : IMacroEngine
{
public string Name
{
get { return "MacroEngine1"; }
}
public IEnumerable<string> SupportedExtensions
{
get { return new[] {"me1"}; }
}
public IEnumerable<string> SupportedUIExtensions
{
get { throw new NotImplementedException(); }
}
public Dictionary<string, IMacroGuiRendering> SupportedProperties
{
get { throw new NotImplementedException(); }
}
public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage)
{
throw new NotImplementedException();
}
public string Execute(MacroModel macro, INode currentPage)
{
throw new NotImplementedException();
}
}
public class MacroEngine2 : IMacroEngine
{
public string Name
{
get { return "MacroEngine2"; }
}
public IEnumerable<string> SupportedExtensions
{
get { return new[] { "me2" }; }
}
public IEnumerable<string> SupportedUIExtensions
{
get { throw new NotImplementedException(); }
}
public Dictionary<string, IMacroGuiRendering> SupportedProperties
{
get { throw new NotImplementedException(); }
}
public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage)
{
throw new NotImplementedException();
}
public string Execute(MacroModel macro, INode currentPage)
{
throw new NotImplementedException();
}
}
#endregion
}
}
+8 -5
View File
@@ -6,6 +6,7 @@ using System.Web;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Caching;
@@ -418,7 +419,7 @@ namespace Umbraco.Tests.Models
Assert.That(content.Properties["title"], Is.Not.Null);
Assert.That(content.Properties["title"].Alias, Is.EqualTo("title"));
Assert.That(content.Properties["title"].Value, Is.EqualTo("This is the new title"));
Assert.That(content.Properties["metaDescription"].Value, Is.EqualTo("This is the meta description for a textpage"));
Assert.That(content.Properties["description"].Value, Is.EqualTo("This is the meta description for a textpage"));
}
[Test]
@@ -612,9 +613,9 @@ namespace Umbraco.Tests.Models
// Assert
Assert.That(content.Properties.Contains("author"), Is.True);
Assert.That(content.Properties.Contains("keywords"), Is.True);
Assert.That(content.Properties.Contains("metaDescription"), Is.True);
Assert.That(content.Properties.Contains("description"), Is.True);
Assert.That(content.Properties["keywords"].Value, Is.EqualTo("text,page,meta"));
Assert.That(content.Properties["metaDescription"].Value, Is.EqualTo("This is the meta description for a textpage"));
Assert.That(content.Properties["description"].Value, Is.EqualTo("This is the meta description for a textpage"));
}
[Test]
@@ -631,7 +632,7 @@ namespace Umbraco.Tests.Models
// Assert
Assert.That(content.Properties.Contains("author"), Is.True);
Assert.That(content.Properties.Contains("keywords"), Is.False);
Assert.That(content.Properties.Contains("metaDescription"), Is.False);
Assert.That(content.Properties.Contains("description"), Is.False);
}
[Test]
@@ -828,7 +829,7 @@ namespace Umbraco.Tests.Models
public void Can_Avoid_Circular_Dependencies_In_Composition()
{
var textPage = MockedContentTypes.CreateTextpageContentType();
var parent = MockedContentTypes.CreateSimpleContentType("parent", "Parent");
var parent = MockedContentTypes.CreateSimpleContentType("parent", "Parent", null, true);
var meta = MockedContentTypes.CreateMetaContentType();
var mixin1 = MockedContentTypes.CreateSimpleContentType("mixin1", "Mixin1", new PropertyTypeCollection(
new List<PropertyType>
@@ -863,7 +864,9 @@ namespace Umbraco.Tests.Models
var addedMetaMixin2 = mixin2.AddContentType(meta);
var addedMixin2 = mixin1.AddContentType(mixin2);
var addedMeta = parent.AddContentType(meta);
var addedMixin1 = parent.AddContentType(mixin1);
var addedMixin1Textpage = textPage.AddContentType(mixin1);
var addedTextpageParent = parent.AddContentType(textPage);
+1 -1
View File
@@ -69,7 +69,7 @@ namespace Umbraco.Tests.Models
Assert.AreEqual(content.Properties["title"].Value.ToString(), element.Elements("title").Single().Value);
Assert.AreEqual(content.Properties["bodyText"].Value.ToString(), element.Elements("bodyText").Single().Value);
Assert.AreEqual(content.Properties["keywords"].Value.ToString(), element.Elements("keywords").Single().Value);
Assert.AreEqual(content.Properties["metaDescription"].Value.ToString(), element.Elements("metaDescription").Single().Value);
Assert.AreEqual(content.Properties["description"].Value.ToString(), element.Elements("description").Single().Value);
}
}
}
@@ -1,33 +1,33 @@
using System.Web.Mvc;
using NUnit.Framework;
using Umbraco.Web;
namespace Umbraco.Tests
{
[TestFixture]
public class HtmlHelperExtensionMethodsTests
{
[SetUp]
public virtual void Initialize()
{
//create an empty htmlHelper
_htmlHelper = new HtmlHelper(new ViewContext(), new ViewPage());
}
private HtmlHelper _htmlHelper;
[Test]
public void Wrap_Simple()
{
var output = _htmlHelper.Wrap("div", "hello world");
Assert.AreEqual("<div>hello world</div>", output.ToHtmlString());
}
[Test]
public void Wrap_Object_Attributes()
{
var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"});
Assert.AreEqual("<div style=\"color:red;\" onclick=\"void();\">hello world</div>", output.ToHtmlString());
}
}
using System.Web.Mvc;
using NUnit.Framework;
using Umbraco.Web;
namespace Umbraco.Tests.Mvc
{
[TestFixture]
public class HtmlHelperExtensionMethodsTests
{
[SetUp]
public virtual void Initialize()
{
//create an empty htmlHelper
_htmlHelper = new HtmlHelper(new ViewContext(), new ViewPage());
}
private HtmlHelper _htmlHelper;
[Test]
public void Wrap_Simple()
{
var output = _htmlHelper.Wrap("div", "hello world");
Assert.AreEqual("<div>hello world</div>", output.ToHtmlString());
}
[Test]
public void Wrap_Object_Attributes()
{
var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"});
Assert.AreEqual("<div style=\"color:red;\" onclick=\"void();\">hello world</div>", output.ToHtmlString());
}
}
}
@@ -408,7 +408,7 @@ namespace Umbraco.Tests.Mvc
var ctx = new UmbracoContext(
GetHttpContextFactory(url, routeData).HttpContext,
appCtx,
new PublishedCaches(cache, new PublishedMediaCache()),
new PublishedCaches(cache, new PublishedMediaCache(appCtx)),
new WebSecurity(http, appCtx));
//if (setSingleton)
@@ -193,8 +193,8 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var repository = CreateRepository(unitOfWork))
{
var ctMain = MockedContentTypes.CreateSimpleContentType();
var ctChild1 = MockedContentTypes.CreateSimpleContentType("child1", "Child 1", ctMain);
var ctChild2 = MockedContentTypes.CreateSimpleContentType("child2", "Child 2", ctChild1);
var ctChild1 = MockedContentTypes.CreateSimpleContentType("child1", "Child 1", ctMain, true);
var ctChild2 = MockedContentTypes.CreateSimpleContentType("child2", "Child 2", ctChild1, true);
repository.AddOrUpdate(ctMain);
repository.AddOrUpdate(ctChild1);
@@ -282,14 +282,14 @@ namespace Umbraco.Tests.Persistence.Repositories
var contentType = repository.Get(NodeDto.NodeIdSeed + 1);
// Act
contentType.PropertyGroups["Meta"].PropertyTypes.Remove("metaDescription");
contentType.PropertyGroups["Meta"].PropertyTypes.Remove("description");
repository.AddOrUpdate(contentType);
unitOfWork.Commit();
var result = repository.Get(NodeDto.NodeIdSeed + 1);
// Assert
Assert.That(result.PropertyTypes.Any(x => x.Alias == "metaDescription"), Is.False);
Assert.That(result.PropertyTypes.Any(x => x.Alias == "description"), Is.False);
Assert.That(contentType.PropertyGroups.Count, Is.EqualTo(result.PropertyGroups.Count));
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(result.PropertyTypes.Count()));
}
@@ -434,7 +434,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Assert
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(3));
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "keywords"), Is.False);
Assert.That(subpage.Properties.First(x => x.Alias == "metaDescription").Value, Is.EqualTo("This is the meta description for a textpage"));
Assert.That(subpage.Properties.First(x => x.Alias == "description").Value, Is.EqualTo("This is the meta description for a textpage"));
}
}
@@ -534,7 +534,7 @@ namespace Umbraco.Tests.Persistence.Repositories
//Assert
var updated = contentRepository.Get(subpage.Id);
Assert.That(updated.GetValue("metaAuthor").ToString(), Is.EqualTo("John Doe"));
Assert.That(updated.Properties.First(x => x.Alias == "metaDescription").Value, Is.EqualTo("This is the meta description for a textpage"));
Assert.That(updated.Properties.First(x => x.Alias == "description").Value, Is.EqualTo("This is the meta description for a textpage"));
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(4));
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "metaAuthor"), Is.True);
@@ -1,17 +1,17 @@
using System;
using System.Collections.Generic;
using Umbraco.Core;
namespace Umbraco.Tests
{
/// <summary>
/// Used for PluginTypeResolverTests
/// </summary>
internal static class PluginManagerExtensions
{
public static IEnumerable<Type> ResolveFindMeTypes(this PluginManager resolver)
{
return resolver.ResolveTypes<PluginManagerTests.IFindMe>();
}
}
using System;
using System.Collections.Generic;
using Umbraco.Core;
namespace Umbraco.Tests.Plugins
{
/// <summary>
/// Used for PluginTypeResolverTests
/// </summary>
internal static class PluginManagerExtensions
{
public static IEnumerable<Type> ResolveFindMeTypes(this PluginManager resolver)
{
return resolver.ResolveTypes<PluginManagerTests.IFindMe>();
}
}
}
@@ -1,30 +1,26 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web.Compilation;
using NUnit.Framework;
using SqlCE4Umbraco;
using umbraco;
using umbraco.businesslogic;
using umbraco.cms.businesslogic;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.PropertyEditors;
using umbraco.DataLayer;
using umbraco.editorControls;
using umbraco.MacroEngines;
using Umbraco.Tests.TestHelpers;
using umbraco.uicontrols;
using Umbraco.Web;
using Umbraco.Web.PropertyEditors;
using umbraco;
using umbraco.DataLayer;
using umbraco.MacroEngines;
using umbraco.businesslogic;
using umbraco.cms.businesslogic;
using umbraco.editorControls;
using umbraco.interfaces;
using umbraco.uicontrols;
using umbraco.cms;
namespace Umbraco.Tests
namespace Umbraco.Tests.Plugins
{
[TestFixture]
@@ -285,7 +281,7 @@ namespace Umbraco.Tests
public void Resolves_Attributed_Trees()
{
var trees = PluginManager.Current.ResolveAttributedTrees();
Assert.AreEqual(18, trees.Count());
Assert.AreEqual(19, trees.Count());
}
[Test]
File diff suppressed because it is too large Load Diff
@@ -1,79 +1,72 @@
using System;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Odbc;
using System.Data.OleDb;
using System.Data.SqlClient;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web;
using Umbraco.Web.Cache;
using Umbraco.Web.Scheduling;
using UmbracoExamine;
using UmbracoExamine.DataServices;
using umbraco;
using umbraco.presentation;
using umbraco.presentation.nodeFactory;
using umbraco.presentation.umbraco.Search;
namespace Umbraco.Tests
{
/// <summary>
/// Tests for TypeHelper
/// </summary>
[TestFixture]
public class TypeHelperTests
{
[Test]
public void Is_Static_Class()
{
Assert.IsTrue(TypeHelper.IsStaticClass(typeof(TypeHelper)));
Assert.IsFalse(TypeHelper.IsStaticClass(typeof(TypeHelperTests)));
}
[Test]
public void Find_Common_Base_Class()
{
var t1 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
typeof (OdbcCommand),
typeof (SqlCommand));
Assert.IsFalse(t1.Success);
var t2 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
typeof (OdbcCommand),
typeof (SqlCommand),
typeof (Component));
Assert.IsTrue(t2.Success);
Assert.AreEqual(typeof(Component), t2.Result);
var t3 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
typeof (OdbcCommand),
typeof (SqlCommand),
typeof (Component),
typeof (Component).BaseType);
Assert.IsTrue(t3.Success);
Assert.AreEqual(typeof(MarshalByRefObject), t3.Result);
var t4 = TypeHelper.GetLowestBaseType(typeof(OleDbCommand),
typeof(OdbcCommand),
typeof(SqlCommand),
typeof(Component),
typeof(Component).BaseType,
typeof(int));
Assert.IsFalse(t4.Success);
var t5 = TypeHelper.GetLowestBaseType(typeof(PropertyAliasDto));
Assert.IsTrue(t5.Success);
Assert.AreEqual(typeof(PropertyAliasDto), t5.Result);
var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler),
typeof (Scheduler),
typeof(CacheRefresherEventHandler));
Assert.IsTrue(t6.Success);
Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result);
}
}
using System;
using System.ComponentModel;
using System.Data.Odbc;
using System.Data.OleDb;
using System.Data.SqlClient;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web.Cache;
using Umbraco.Web.Scheduling;
using UmbracoExamine.DataServices;
namespace Umbraco.Tests.Plugins
{
/// <summary>
/// Tests for TypeHelper
/// </summary>
[TestFixture]
public class TypeHelperTests
{
[Test]
public void Is_Static_Class()
{
Assert.IsTrue(TypeHelper.IsStaticClass(typeof(TypeHelper)));
Assert.IsFalse(TypeHelper.IsStaticClass(typeof(TypeHelperTests)));
}
[Test]
public void Find_Common_Base_Class()
{
var t1 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
typeof (OdbcCommand),
typeof (SqlCommand));
Assert.IsFalse(t1.Success);
var t2 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
typeof (OdbcCommand),
typeof (SqlCommand),
typeof (Component));
Assert.IsTrue(t2.Success);
Assert.AreEqual(typeof(Component), t2.Result);
var t3 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
typeof (OdbcCommand),
typeof (SqlCommand),
typeof (Component),
typeof (Component).BaseType);
Assert.IsTrue(t3.Success);
Assert.AreEqual(typeof(MarshalByRefObject), t3.Result);
var t4 = TypeHelper.GetLowestBaseType(typeof(OleDbCommand),
typeof(OdbcCommand),
typeof(SqlCommand),
typeof(Component),
typeof(Component).BaseType,
typeof(int));
Assert.IsFalse(t4.Success);
var t5 = TypeHelper.GetLowestBaseType(typeof(PropertyAliasDto));
Assert.IsTrue(t5.Success);
Assert.AreEqual(typeof(PropertyAliasDto), t5.Result);
var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler),
typeof (Scheduler),
typeof(CacheRefresherEventHandler));
Assert.IsTrue(t6.Success);
Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result);
}
}
}
@@ -92,9 +92,9 @@ namespace Umbraco.Tests.PublishedCache
_umbracoContext = new UmbracoContext(
_httpContextFactory.HttpContext,
ApplicationContext.Current,
new PublishedCaches(cache, new PublishedMediaCache()),
new WebSecurity(_httpContextFactory.HttpContext, ApplicationContext.Current));
ApplicationContext,
new PublishedCaches(cache, new PublishedMediaCache(ApplicationContext)),
new WebSecurity(_httpContextFactory.HttpContext, ApplicationContext));
_cache = _umbracoContext.ContentCache;
}
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.PublishedCache
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot2.Id);
var ctx = GetUmbracoContext("/test", 1234);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(), ctx);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application), ctx);
var roots = cache.GetAtRoot();
Assert.AreEqual(2, roots.Count());
Assert.IsTrue(roots.Select(x => x.Id).ContainsAll(new[] {mRoot1.Id, mRoot2.Id}));
@@ -126,6 +126,8 @@ namespace Umbraco.Tests.PublishedCache
[Test]
public void Convert_From_Search_Result()
{
var ctx = GetUmbracoContext("/test", 1234);
var result = new SearchResult()
{
Id = 1234,
@@ -144,7 +146,7 @@ namespace Umbraco.Tests.PublishedCache
result.Fields.Add("updateDate", "2012-07-16T10:34:09");
result.Fields.Add("writerName", "Shannon");
var store = new PublishedMediaCache();
var store = new PublishedMediaCache(ctx.Application);
var doc = store.ConvertFromSearchResult(result);
DoAssert(doc, 1234, 0, 0, "", "Image", 0, "Shannon", "", 0, 0, "-1,1234", default(DateTime), DateTime.Parse("2012-07-16T10:34:09"), 2);
@@ -154,9 +156,11 @@ namespace Umbraco.Tests.PublishedCache
[Test]
public void Convert_From_XPath_Navigator()
{
var ctx = GetUmbracoContext("/test", 1234);
var xmlDoc = GetMediaXml();
var navigator = xmlDoc.SelectSingleNode("/root/Image").CreateNavigator();
var cache = new PublishedMediaCache();
var cache = new PublishedMediaCache(ctx.Application);
var doc = cache.ConvertFromXPathNavigator(navigator);
DoAssert(doc, 2000, 0, 2, "image1", "Image", 2044, "Shannon", "Shannon2", 22, 33, "-1,2000", DateTime.Parse("2012-06-12T14:13:17"), DateTime.Parse("2012-07-20T18:50:43"), 1);
@@ -74,7 +74,8 @@ namespace Umbraco.Tests.PublishedContent
{
var contentTypeService = ctx.Application.Services.ContentTypeService;
var baseType = new ContentType(-1) {Alias = "base", Name = "Base"};
var inheritedType = new ContentType(baseType) {Alias = "inherited", Name = "Inherited"};
const string contentTypeAlias = "inherited";
var inheritedType = new ContentType(baseType, contentTypeAlias) {Alias = contentTypeAlias, Name = "Inherited"};
contentTypeService.Save(baseType);
contentTypeService.Save(inheritedType);
createContentTypes = false;
@@ -49,7 +49,7 @@ namespace Umbraco.Tests.PublishedContent
});
PublishedCachesResolver.Current = new PublishedCachesResolver(new PublishedCaches(
new PublishedContentCache(), new PublishedMediaCache()));
new PublishedContentCache(), new PublishedMediaCache(ApplicationContext)));
if (PublishedContentModelFactoryResolver.HasCurrent == false)
PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver();
@@ -11,6 +11,7 @@ using Examine.LuceneEngine;
using Examine.LuceneEngine.Providers;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Store;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration;
@@ -60,7 +61,7 @@ namespace Umbraco.Tests.PublishedContent
internal static IPublishedContent GetNode(int id, UmbracoContext umbracoContext)
{
var ctx = umbracoContext;
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(), ctx);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application), ctx);
var doc = cache.GetById(id);
Assert.IsNotNull(doc);
return doc;
@@ -112,7 +113,7 @@ namespace Umbraco.Tests.PublishedContent
indexer.RebuildIndex();
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
var ctx = GetUmbracoContext("/test", 1234);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(1111);
@@ -141,7 +142,7 @@ namespace Umbraco.Tests.PublishedContent
indexer.RebuildIndex();
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
var ctx = GetUmbracoContext("/test", 1234);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
//ensure it is found
var publishedMedia = cache.GetById(3113);
@@ -181,7 +182,7 @@ namespace Umbraco.Tests.PublishedContent
indexer.RebuildIndex();
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
var ctx = GetUmbracoContext("/test", 1234);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(1111);
@@ -203,7 +204,7 @@ namespace Umbraco.Tests.PublishedContent
indexer.RebuildIndex();
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
var ctx = GetUmbracoContext("/test", 1234);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(1111);
@@ -225,7 +226,7 @@ namespace Umbraco.Tests.PublishedContent
indexer.RebuildIndex();
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
var ctx = GetUmbracoContext("/test", 1234);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(1111);
@@ -247,7 +248,7 @@ namespace Umbraco.Tests.PublishedContent
indexer.RebuildIndex();
var ctx = GetUmbracoContext("/test", 1234);
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(3113);
@@ -266,7 +267,7 @@ namespace Umbraco.Tests.PublishedContent
indexer.RebuildIndex();
var ctx = GetUmbracoContext("/test", 1234);
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(3113);
@@ -412,6 +413,100 @@ namespace Umbraco.Tests.PublishedContent
Assert.IsTrue(publishedSubChild1.AncestorsOrSelf().Select(x => x.Id).ContainsAll(
new[] { mSubChild1.Id, mChild1.Id, mRoot.Id }));
}
[Test]
public void Convert_From_Legacy_Xml()
{
var config = SettingsForTests.GenerateMockSettings();
var contentMock = Mock.Get(config.Content);
contentMock.Setup(x => x.UseLegacyXmlSchema).Returns(true);
SettingsForTests.ConfigureSettings(config);
var nodeId = 2112;
var xml = XElement.Parse(@"<node id=""2112"" version=""5b3e46ab-3e37-4cfa-ab70-014234b5bd39"" parentID=""2222"" level=""3"" writerID=""0"" nodeType=""1032"" template=""0"" sortOrder=""1"" createDate=""2010-05-19T17:32:46"" updateDate=""2010-05-19T17:32:46"" nodeName=""Sam's Umbraco Image"" urlName=""acnestressscrub"" writerName=""Administrator"" nodeTypeAlias=""Image"" path=""-1,1111,2222,2112"">
<data alias=""umbracoFile""><![CDATA[/media/1234/blah.pdf]]></data>
<data alias=""umbracoWidth"">115</data>
<data alias=""umbracoHeight"">268</data>
<data alias=""umbracoBytes"">10726</data>
<data alias=""umbracoExtension"">jpg</data>
<node id=""3113"" version=""5b3e46ab-3e37-4cfa-ab70-014234b5bd33"" parentID=""2112"" level=""4"" writerID=""0"" nodeType=""1032"" template=""0"" sortOrder=""2"" createDate=""2010-05-19T17:32:46"" updateDate=""2010-05-19T17:32:46"" nodeName=""Another Umbraco Image"" urlName=""acnestressscrub"" writerName=""Administrator"" nodeTypeAlias=""Image"" path=""-1,1111,2222,2112,3113"">
<data alias=""umbracoFile""><![CDATA[/media/1234/blah.pdf]]></data>
<data alias=""umbracoWidth"">115</data>
<data alias=""umbracoHeight"">268</data>
<data alias=""umbracoBytes"">10726</data>
<data alias=""umbracoExtension"">jpg</data>
</node>
</node>");
var node = xml.DescendantsAndSelf("node").Single(x => (int) x.Attribute("id") == nodeId);
var publishedMedia = new PublishedMediaCache(ApplicationContext);
var nav = node.CreateNavigator();
var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/node"), nodeId);
Assert.AreEqual(nodeId, converted.Id);
Assert.AreEqual(3, converted.Level);
Assert.AreEqual(1, converted.SortOrder);
Assert.AreEqual("Sam's Umbraco Image", converted.Name);
Assert.AreEqual("-1,1111,2222,2112", converted.Path);
}
[Test]
public void Convert_From_Standard_Xml()
{
var config = SettingsForTests.GenerateMockSettings();
var contentMock = Mock.Get(config.Content);
contentMock.Setup(x => x.UseLegacyXmlSchema).Returns(true);
SettingsForTests.ConfigureSettings(config);
var nodeId = 2112;
var xml = XElement.Parse(@"<Image id=""2112"" version=""5b3e46ab-3e37-4cfa-ab70-014234b5bd39"" parentID=""2222"" level=""3"" writerID=""0"" nodeType=""1032"" template=""0"" sortOrder=""1"" createDate=""2010-05-19T17:32:46"" updateDate=""2010-05-19T17:32:46"" nodeName=""Sam's Umbraco Image"" urlName=""acnestressscrub"" writerName=""Administrator"" nodeTypeAlias=""Image"" path=""-1,1111,2222,2112"" isDoc="""">
<umbracoFile><![CDATA[/media/1234/blah.pdf]]></umbracoFile>
<umbracoWidth>115</umbracoWidth>
<umbracoHeight>268</umbracoHeight>
<umbracoBytes>10726</umbracoBytes>
<umbracoExtension>jpg</umbracoExtension>
<Image id=""3113"" version=""5b3e46ab-3e37-4cfa-ab70-014234b5bd33"" parentID=""2112"" level=""4"" writerID=""0"" nodeType=""1032"" template=""0"" sortOrder=""2"" createDate=""2010-05-19T17:32:46"" updateDate=""2010-05-19T17:32:46"" nodeName=""Another Umbraco Image"" urlName=""acnestressscrub"" writerName=""Administrator"" nodeTypeAlias=""Image"" path=""-1,1111,2222,2112,3113"" isDoc="""">
<umbracoFile><![CDATA[/media/1234/blah.pdf]]></umbracoFile>
<umbracoWidth>115</umbracoWidth>
<umbracoHeight>268</umbracoHeight>
<umbracoBytes>10726</umbracoBytes>
<umbracoExtension>jpg</umbracoExtension>
</Image>
</Image>");
var node = xml.DescendantsAndSelf("Image").Single(x => (int)x.Attribute("id") == nodeId);
var publishedMedia = new PublishedMediaCache(ApplicationContext);
var nav = node.CreateNavigator();
var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/Image"), nodeId);
Assert.AreEqual(nodeId, converted.Id);
Assert.AreEqual(3, converted.Level);
Assert.AreEqual(1, converted.SortOrder);
Assert.AreEqual("Sam's Umbraco Image", converted.Name);
Assert.AreEqual("-1,1111,2222,2112", converted.Path);
}
[Test]
public void Detects_Error_In_Xml()
{
var errorXml = new XElement("error", string.Format("No media is maching '{0}'", 1234));
var nav = errorXml.CreateNavigator();
var publishedMedia = new PublishedMediaCache(ApplicationContext);
var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/"), 1234);
Assert.IsNull(converted);
}
}
@@ -0,0 +1,280 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web.Scheduling;
namespace Umbraco.Tests.Scheduling
{
[TestFixture]
public class BackgroundTaskRunnerTests
{
[Test]
public void Startup_And_Shutdown()
{
BackgroundTaskRunner<IBackgroundTask> tManager;
using (tManager = new BackgroundTaskRunner<IBackgroundTask>(true, true))
{
tManager.StartUp();
}
NUnit.Framework.Assert.IsFalse(tManager.IsRunning);
}
[Test]
public void Startup_Starts_Automatically()
{
BackgroundTaskRunner<BaseTask> tManager;
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
{
tManager.Add(new MyTask());
NUnit.Framework.Assert.IsTrue(tManager.IsRunning);
}
}
[Test]
public void Task_Runs()
{
var myTask = new MyTask();
var waitHandle = new ManualResetEvent(false);
BackgroundTaskRunner<BaseTask> tManager;
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
{
tManager.TaskCompleted += (sender, task) => waitHandle.Set();
tManager.Add(myTask);
//wait for ITasks to complete
waitHandle.WaitOne();
NUnit.Framework.Assert.IsTrue(myTask.Ended != default(DateTime));
}
}
[Test]
public void Many_Tasks_Run()
{
var tasks = new Dictionary<BaseTask, ManualResetEvent>();
for (var i = 0; i < 10; i++)
{
tasks.Add(new MyTask(), new ManualResetEvent(false));
}
BackgroundTaskRunner<BaseTask> tManager;
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
{
tManager.TaskCompleted += (sender, task) => tasks[task.Task].Set();
tasks.ForEach(t => tManager.Add(t.Key));
//wait for all ITasks to complete
WaitHandle.WaitAll(tasks.Values.Select(x => (WaitHandle)x).ToArray());
foreach (var task in tasks)
{
NUnit.Framework.Assert.IsTrue(task.Key.Ended != default(DateTime));
}
}
}
[Test]
public void Tasks_Can_Keep_Being_Added_And_Will_Execute()
{
Func<Dictionary<BaseTask, ManualResetEvent>> getTasks = () =>
{
var newTasks = new Dictionary<BaseTask, ManualResetEvent>();
for (var i = 0; i < 10; i++)
{
newTasks.Add(new MyTask(), new ManualResetEvent(false));
}
return newTasks;
};
IDictionary<BaseTask, ManualResetEvent> tasks = getTasks();
BackgroundTaskRunner<BaseTask> tManager;
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
{
tManager.TaskCompleted += (sender, task) => tasks[task.Task].Set();
//execute first batch
tasks.ForEach(t => tManager.Add(t.Key));
//wait for all ITasks to complete
WaitHandle.WaitAll(tasks.Values.Select(x => (WaitHandle)x).ToArray());
foreach (var task in tasks)
{
NUnit.Framework.Assert.IsTrue(task.Key.Ended != default(DateTime));
}
//execute another batch after a bit
Thread.Sleep(2000);
tasks = getTasks();
tasks.ForEach(t => tManager.Add(t.Key));
//wait for all ITasks to complete
WaitHandle.WaitAll(tasks.Values.Select(x => (WaitHandle)x).ToArray());
foreach (var task in tasks)
{
NUnit.Framework.Assert.IsTrue(task.Key.Ended != default(DateTime));
}
}
}
[Test]
public void Task_Queue_Will_Be_Completed_Before_Shutdown()
{
var tasks = new Dictionary<BaseTask, ManualResetEvent>();
for (var i = 0; i < 10; i++)
{
tasks.Add(new MyTask(), new ManualResetEvent(false));
}
BackgroundTaskRunner<BaseTask> tManager;
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
{
tManager.TaskCompleted += (sender, task) => tasks[task.Task].Set();
tasks.ForEach(t => tManager.Add(t.Key));
////wait for all ITasks to complete
//WaitHandle.WaitAll(tasks.Values.Select(x => (WaitHandle)x).ToArray());
tManager.Stop(false);
//immediate stop will block until complete - but since we are running on
// a single thread this doesn't really matter as the above will just process
// until complete.
tManager.Stop(true);
NUnit.Framework.Assert.AreEqual(0, tManager.TaskCount);
}
}
//NOTE: These tests work in .Net 4.5 but in this current version we don't have the correct
// async/await signatures with GetAwaiter, so am just commenting these out in this version
[Test]
public async void Non_Persistent_Runner_Will_End_After_Queue_Empty()
{
var tasks = new List<BaseTask>();
for (var i = 0; i < 10; i++)
{
tasks.Add(new MyTask());
}
BackgroundTaskRunner<BaseTask> tManager;
using (tManager = new BackgroundTaskRunner<BaseTask>(persistentThread: false, dedicatedThread:true))
{
tasks.ForEach(t => tManager.Add(t));
//wait till the thread is done
await tManager;
foreach (var task in tasks)
{
Assert.IsTrue(task.Ended != default(DateTime));
}
Assert.AreEqual(TaskStatus.RanToCompletion, tManager.TaskStatus);
Assert.IsFalse(tManager.IsRunning);
Assert.IsFalse(tManager.IsDisposed);
}
}
[Test]
public async void Non_Persistent_Runner_Will_Start_New_Threads_When_Required()
{
Func<List<BaseTask>> getTasks = () =>
{
var newTasks = new List<BaseTask>();
for (var i = 0; i < 10; i++)
{
newTasks.Add(new MyTask());
}
return newTasks;
};
List<BaseTask> tasks = getTasks();
BackgroundTaskRunner<BaseTask> tManager;
using (tManager = new BackgroundTaskRunner<BaseTask>(persistentThread: false, dedicatedThread: true))
{
tasks.ForEach(t => tManager.Add(t));
//wait till the thread is done
await tManager;
Assert.AreEqual(TaskStatus.RanToCompletion, tManager.TaskStatus);
Assert.IsFalse(tManager.IsRunning);
Assert.IsFalse(tManager.IsDisposed);
foreach (var task in tasks)
{
Assert.IsTrue(task.Ended != default(DateTime));
}
//create more tasks
tasks = getTasks();
//add more tasks
tasks.ForEach(t => tManager.Add(t));
//wait till the thread is done
await tManager;
foreach (var task in tasks)
{
Assert.IsTrue(task.Ended != default(DateTime));
}
Assert.AreEqual(TaskStatus.RanToCompletion, tManager.TaskStatus);
Assert.IsFalse(tManager.IsRunning);
Assert.IsFalse(tManager.IsDisposed);
}
}
private class MyTask : BaseTask
{
public MyTask()
{
}
public override void Run()
{
Thread.Sleep(500);
}
public override void Cancel()
{
}
}
public abstract class BaseTask : IBackgroundTask
{
public Guid UniqueId { get; protected set; }
public abstract void Run();
public abstract void Cancel();
public DateTime Queued { get; set; }
public DateTime Started { get; set; }
public DateTime Ended { get; set; }
public virtual void Dispose()
{
Ended = DateTime.Now;
}
}
}
}
@@ -0,0 +1,92 @@
using System.Configuration;
using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Sync;
namespace Umbraco.Tests
{
[TestFixture]
public class ServerEnvironmentHelperTests
{
[Test]
public void Get_Base_Url_Single_Server_Orig_Request_Url_No_SSL()
{
var appContext = new ApplicationContext(null)
{
OriginalRequestUrl = "test.com"
};
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "false");
var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl(
appContext,
Mock.Of<IUmbracoSettingsSection>(
section =>
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>()));
Assert.AreEqual("http://test.com/", result);
}
[Test]
public void Get_Base_Url_Single_Server_Orig_Request_Url_With_SSL()
{
var appContext = new ApplicationContext(null)
{
OriginalRequestUrl = "test.com"
};
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true");
var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl(
appContext,
Mock.Of<IUmbracoSettingsSection>(
section =>
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>()));
Assert.AreEqual("https://test.com/", result);
}
[Test]
public void Get_Base_Url_Single_Server_Via_Config_Url_No_SSL()
{
var appContext = new ApplicationContext(null);
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "false");
var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl(
appContext,
Mock.Of<IUmbracoSettingsSection>(
section =>
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/hello/world")));
Assert.AreEqual("http://mycoolhost.com/hello/world/", result);
}
[Test]
public void Get_Base_Url_Single_Server_Via_Config_Url_With_SSL()
{
var appContext = new ApplicationContext(null);
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true");
var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl(
appContext,
Mock.Of<IUmbracoSettingsSection>(
section =>
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/hello/world")));
Assert.AreEqual("https://mycoolhost.com/hello/world/", result);
}
}
}
@@ -1335,7 +1335,7 @@ namespace Umbraco.Tests.Services
//MCH: I'm guessing this is an issue because of the format the date is actually stored as, right? Cause we don't do any formatting when saving or loading
Assert.That(sut.GetValue<DateTime>("dateTime").ToString("G"), Is.EqualTo(content.GetValue<DateTime>("dateTime").ToString("G")));
Assert.That(sut.GetValue<string>("colorPicker"), Is.EqualTo("black"));
Assert.That(sut.GetValue<string>("folderBrowser"), Is.Empty);
Assert.That(sut.GetValue<string>("folderBrowser"), Is.Null);
Assert.That(sut.GetValue<string>("ddlMultiple"), Is.EqualTo("1234,1235"));
Assert.That(sut.GetValue<string>("rbList"), Is.EqualTo("random"));
Assert.That(sut.GetValue<DateTime>("date").ToString("G"), Is.EqualTo(content.GetValue<DateTime>("date").ToString("G")));
@@ -1,3 +1,4 @@
using System.Runtime.Remoting;
using NUnit.Framework;
using System;
using System.Collections.Generic;
@@ -5,6 +6,8 @@ using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Tests.CodeFirst.TestModels.Composition;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
@@ -178,10 +181,11 @@ namespace Umbraco.Tests.Services
/*,"Navigation"*/);
cts.Save(ctBase);
var ctHomePage = new ContentType(ctBase)
const string contentTypeAlias = "HomePage";
var ctHomePage = new ContentType(ctBase, contentTypeAlias)
{
Name = "Home Page",
Alias = "HomePage",
Alias = contentTypeAlias,
Icon = "settingDomain.gif",
Thumbnail = "folder.png",
AllowedAsRoot = true
@@ -191,7 +195,7 @@ namespace Umbraco.Tests.Services
cts.Save(ctHomePage);
// Act
var homeDoc = cs.CreateContent("Home Page", -1, "HomePage");
var homeDoc = cs.CreateContent("Home Page", -1, contentTypeAlias);
cs.SaveAndPublishWithStatus(homeDoc);
// Assert
@@ -243,13 +247,13 @@ namespace Umbraco.Tests.Services
var global = MockedContentTypes.CreateSimpleContentType("global", "Global");
service.Save(global);
var components = MockedContentTypes.CreateSimpleContentType("components", "Components", global);
var components = MockedContentTypes.CreateSimpleContentType("components", "Components", global, true);
service.Save(components);
var component = MockedContentTypes.CreateSimpleContentType("component", "Component", components);
var component = MockedContentTypes.CreateSimpleContentType("component", "Component", components, true);
service.Save(component);
var category = MockedContentTypes.CreateSimpleContentType("category", "Category", global);
var category = MockedContentTypes.CreateSimpleContentType("category", "Category", global, true);
service.Save(category);
var success = category.AddContentType(component);
@@ -339,10 +343,10 @@ namespace Umbraco.Tests.Services
var parentContentType1 = MockedContentTypes.CreateSimpleContentType("parent1", "Parent1");
service.Save(parentContentType1);
var parentContentType2 = MockedContentTypes.CreateSimpleContentType("parent2", "Parent2");
var parentContentType2 = MockedContentTypes.CreateSimpleContentType("parent2", "Parent2", null, true);
service.Save(parentContentType2);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", parentContentType1);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", parentContentType1, true);
service.Save(simpleContentType);
// Act
@@ -371,8 +375,8 @@ namespace Umbraco.Tests.Services
Assert.AreNotEqual(clonedContentType.Key, originalContentType.Key);
Assert.AreNotEqual(clonedContentType.Path, originalContentType.Path);
Assert.AreNotEqual(clonedContentType.PropertyTypes.First(x => x.Alias.Equals("title")).Id, originalContentType.PropertyTypes.First(x => x.Alias.Equals("title")).Id);
Assert.AreNotEqual(clonedContentType.PropertyGroups.First(x => x.Name.Equals("Content")).Id, originalContentType.PropertyGroups.First(x => x.Name.Equals("Content")).Id);
Assert.AreNotEqual(clonedContentType.PropertyTypes.First(x => x.Alias.StartsWith("title")).Id, originalContentType.PropertyTypes.First(x => x.Alias.StartsWith("title")).Id);
Assert.AreNotEqual(clonedContentType.PropertyGroups.First(x => x.Name.StartsWith("Content")).Id, originalContentType.PropertyGroups.First(x => x.Name.StartsWith("Content")).Id);
}
[Test]
@@ -432,10 +436,10 @@ namespace Umbraco.Tests.Services
var parentContentType1 = MockedContentTypes.CreateSimpleContentType("parent1", "Parent1");
service.Save(parentContentType1);
var parentContentType2 = MockedContentTypes.CreateSimpleContentType("parent2", "Parent2");
var parentContentType2 = MockedContentTypes.CreateSimpleContentType("parent2", "Parent2", null, true);
service.Save(parentContentType2);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", parentContentType1);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", parentContentType1, true);
service.Save(simpleContentType);
// Act
@@ -460,8 +464,768 @@ namespace Umbraco.Tests.Services
Assert.AreNotEqual(clonedContentType.Key, originalContentType.Key);
Assert.AreNotEqual(clonedContentType.Path, originalContentType.Path);
Assert.AreNotEqual(clonedContentType.PropertyTypes.First(x => x.Alias.Equals("title")).Id, originalContentType.PropertyTypes.First(x => x.Alias.Equals("title")).Id);
Assert.AreNotEqual(clonedContentType.PropertyGroups.First(x => x.Name.Equals("Content")).Id, originalContentType.PropertyGroups.First(x => x.Name.Equals("Content")).Id);
Assert.AreNotEqual(clonedContentType.PropertyTypes.First(x => x.Alias.StartsWith("title")).Id, originalContentType.PropertyTypes.First(x => x.Alias.StartsWith("title")).Id);
Assert.AreNotEqual(clonedContentType.PropertyGroups.First(x => x.Name.StartsWith("Content")).Id, originalContentType.PropertyGroups.First(x => x.Name.StartsWith("Content")).Id);
}
[Test]
public void Cannot_Add_Duplicate_PropertyType_Alias_To_Referenced_Composition()
{
//Related the second issue in screencast from this post http://issues.umbraco.org/issue/U4-5986
// Arrange
var service = ServiceContext.ContentTypeService;
var parent = MockedContentTypes.CreateSimpleContentType();
service.Save(parent);
var child = MockedContentTypes.CreateSimpleContentType("simpleChildPage", "Simple Child Page", parent, true);
service.Save(child);
var composition = MockedContentTypes.CreateMetaContentType();
service.Save(composition);
//Adding Meta-composition to child doc type
child.AddContentType(composition);
service.Save(child);
// Act
var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var added = composition.AddPropertyType(duplicatePropertyType, "Meta");
// Assert
Assert.That(added, Is.True);
Assert.Throws<Exception>(() => service.Save(composition));
Assert.DoesNotThrow(() => service.GetContentType("simpleChildPage"));
}
[Test]
public void Cannot_Add_Duplicate_PropertyType_Alias_In_Composition_Graph()
{
// Arrange
var service = ServiceContext.ContentTypeService;
var basePage = MockedContentTypes.CreateSimpleContentType("basePage", "Base Page", null, true);
service.Save(basePage);
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", basePage);
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true);
service.Save(advancedPage);
var metaComposition = MockedContentTypes.CreateMetaContentType();
service.Save(metaComposition);
var seoComposition = MockedContentTypes.CreateSeoContentType();
service.Save(seoComposition);
var metaAdded = contentPage.AddContentType(metaComposition);
service.Save(contentPage);
var seoAdded = advancedPage.AddContentType(seoComposition);
service.Save(advancedPage);
// Act
var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var addedToBasePage = basePage.AddPropertyType(duplicatePropertyType, "Content");
var addedToAdvancedPage = advancedPage.AddPropertyType(duplicatePropertyType, "Content");
var addedToMeta = metaComposition.AddPropertyType(duplicatePropertyType, "Meta");
var addedToSeo = seoComposition.AddPropertyType(duplicatePropertyType, "Seo");
// Assert
Assert.That(metaAdded, Is.True);
Assert.That(seoAdded, Is.True);
Assert.That(addedToBasePage, Is.True);
Assert.That(addedToAdvancedPage, Is.False);
Assert.That(addedToMeta, Is.True);
Assert.That(addedToSeo, Is.True);
Assert.Throws<Exception>(() => service.Save(basePage));
Assert.Throws<Exception>(() => service.Save(metaComposition));
Assert.Throws<Exception>(() => service.Save(seoComposition));
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
Assert.DoesNotThrow(() => service.GetContentType("meta"));
Assert.DoesNotThrow(() => service.GetContentType("seo"));
}
[Test]
public void Cannot_Add_Duplicate_PropertyType_Alias_At_Root_Which_Conflicts_With_Third_Levels_Composition()
{
/*
* BasePage, gets 'Title' added but should not be allowed
* -- Content Page
* ---- Advanced Page -> Content Meta
* Content Meta :: Composition, has 'Title'
*
* Content Meta has 'Title' PropertyType
* Adding 'Title' to BasePage should fail
*/
// Arrange
var service = ServiceContext.ContentTypeService;
var basePage = MockedContentTypes.CreateBasicContentType();
service.Save(basePage);
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
service.Save(advancedPage);
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
service.Save(contentMetaComposition);
// Act
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
service.Save(basePage);
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
service.Save(contentPage);
var compositionAdded = advancedPage.AddContentType(contentMetaComposition);
service.Save(advancedPage);
//NOTE: It should not be possible to Save 'BasePage' with the Title PropertyType added
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var titleAdded = basePage.AddPropertyType(titlePropertyType, "Content");
// Assert
Assert.That(bodyTextAdded, Is.True);
Assert.That(authorAdded, Is.True);
Assert.That(titleAdded, Is.True);
Assert.That(compositionAdded, Is.True);
Assert.Throws<Exception>(() => service.Save(basePage));
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
}
[Test]
public void Cannot_Rename_PropertyType_Alias_On_Composition_Which_Would_Cause_Conflict_In_Other_Composition()
{
/*
* Meta renames alias to 'title'
* Seo has 'Title'
* BasePage
* -- ContentPage
* ---- AdvancedPage -> Seo
* ------ MoreAdvanedPage -> Meta
*/
// Arrange
var service = ServiceContext.ContentTypeService;
var basePage = MockedContentTypes.CreateBasicContentType();
service.Save(basePage);
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
service.Save(advancedPage);
var moreAdvancedPage = MockedContentTypes.CreateBasicContentType("moreAdvancedPage", "More Advanced Page", advancedPage);
service.Save(moreAdvancedPage);
var seoComposition = MockedContentTypes.CreateSeoContentType();
service.Save(seoComposition);
var metaComposition = MockedContentTypes.CreateMetaContentType();
service.Save(metaComposition);
// Act
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
service.Save(basePage);
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
service.Save(contentPage);
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var subtitleAdded = advancedPage.AddPropertyType(subtitlePropertyType, "Content");
service.Save(advancedPage);
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var titleAdded = seoComposition.AddPropertyType(titlePropertyType, "Content");
service.Save(seoComposition);
var seoCompositionAdded = advancedPage.AddContentType(seoComposition);
var metaCompositionAdded = moreAdvancedPage.AddContentType(metaComposition);
service.Save(advancedPage);
service.Save(moreAdvancedPage);
var keywordsPropertyType = metaComposition.PropertyTypes.First(x => x.Alias.Equals("metakeywords"));
keywordsPropertyType.Alias = "title";
// Assert
Assert.That(bodyTextAdded, Is.True);
Assert.That(subtitleAdded, Is.True);
Assert.That(authorAdded, Is.True);
Assert.That(titleAdded, Is.True);
Assert.That(seoCompositionAdded, Is.True);
Assert.That(metaCompositionAdded, Is.True);
Assert.Throws<Exception>(() => service.Save(metaComposition));
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
Assert.DoesNotThrow(() => service.GetContentType("moreAdvancedPage"));
}
[Test]
public void Can_Add_Additional_Properties_On_Composition_Once_Composition_Has_Been_Saved()
{
/*
* Meta renames alias to 'title'
* Seo has 'Title'
* BasePage
* -- ContentPage
* ---- AdvancedPage -> Seo
* ------ MoreAdvancedPage -> Meta
*/
// Arrange
var service = ServiceContext.ContentTypeService;
var basePage = MockedContentTypes.CreateBasicContentType();
service.Save(basePage);
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
service.Save(advancedPage);
var moreAdvancedPage = MockedContentTypes.CreateBasicContentType("moreAdvancedPage", "More Advanced Page", advancedPage);
service.Save(moreAdvancedPage);
var seoComposition = MockedContentTypes.CreateSeoContentType();
service.Save(seoComposition);
var metaComposition = MockedContentTypes.CreateMetaContentType();
service.Save(metaComposition);
// Act
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
service.Save(basePage);
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
service.Save(contentPage);
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var subtitleAdded = advancedPage.AddPropertyType(subtitlePropertyType, "Content");
service.Save(advancedPage);
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var titleAdded = seoComposition.AddPropertyType(titlePropertyType, "Content");
service.Save(seoComposition);
var seoCompositionAdded = advancedPage.AddContentType(seoComposition);
var metaCompositionAdded = moreAdvancedPage.AddContentType(metaComposition);
service.Save(advancedPage);
service.Save(moreAdvancedPage);
// Assert
Assert.That(bodyTextAdded, Is.True);
Assert.That(subtitleAdded, Is.True);
Assert.That(authorAdded, Is.True);
Assert.That(titleAdded, Is.True);
Assert.That(seoCompositionAdded, Is.True);
Assert.That(metaCompositionAdded, Is.True);
var testPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "test", Name = "Test", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var testAdded = seoComposition.AddPropertyType(testPropertyType, "Content");
service.Save(seoComposition);
Assert.That(testAdded, Is.True);
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
Assert.DoesNotThrow(() => service.GetContentType("moreAdvancedPage"));
}
[Test]
public void Cannot_Rename_PropertyGroup_On_Child_Avoiding_Conflict_With_Parent_PropertyGroup()
{
// Arrange
var service = ServiceContext.ContentTypeService;
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, true, "Content");
service.Save(page);
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true, "Content_");
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true, "Details");
service.Save(advancedPage);
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
service.Save(contentMetaComposition);
// Act
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
service.Save(contentPage);
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
service.Save(contentPage);
//Change the name of the tab on the "root" content type 'page'.
var propertyGroup = contentPage.PropertyGroups["Content_"];
Assert.Throws<Exception>(() => contentPage.PropertyGroups.Add(new PropertyGroup
{
Id = propertyGroup.Id,
Name = "Content",
SortOrder = 0
}));
// Assert
Assert.That(compositionAdded, Is.True);
Assert.That(subtitleAdded, Is.True);
Assert.That(authorAdded, Is.True);
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
}
[Test]
public void Cannot_Rename_PropertyType_Alias_Causing_Conflicts_With_Parents()
{
// Arrange
var service = ServiceContext.ContentTypeService;
var basePage = MockedContentTypes.CreateBasicContentType();
service.Save(basePage);
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
service.Save(advancedPage);
// Act
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var titleAdded = basePage.AddPropertyType(titlePropertyType, "Content");
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var bodyTextAdded = contentPage.AddPropertyType(bodyTextPropertyType, "Content");
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var authorAdded = advancedPage.AddPropertyType(authorPropertyType, "Content");
service.Save(basePage);
service.Save(contentPage);
service.Save(advancedPage);
//Rename the PropertyType to something that already exists in the Composition - NOTE this should not be allowed and Saving should throw an exception
var authorPropertyTypeToRename = advancedPage.PropertyTypes.First(x => x.Alias.Equals("author"));
authorPropertyTypeToRename.Alias = "title";
// Assert
Assert.That(bodyTextAdded, Is.True);
Assert.That(authorAdded, Is.True);
Assert.That(titleAdded, Is.True);
Assert.That(subtitleAdded, Is.True);
Assert.Throws<Exception>(() => service.Save(advancedPage));
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
}
[Test]
public void Can_Add_PropertyType_Alias_Which_Exists_In_Composition_Outside_Graph()
{
/*
* Meta (Composition)
* Content Meta (Composition) has 'Title' -> Meta
* BasePage
* -- ContentPage gets 'Title' added -> Meta
* ---- Advanced Page
*/
// Arrange
var service = ServiceContext.ContentTypeService;
var basePage = MockedContentTypes.CreateSimpleContentType("basePage", "Base Page", null, true);
service.Save(basePage);
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", basePage, true);
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true);
service.Save(advancedPage);
var metaComposition = MockedContentTypes.CreateMetaContentType();
service.Save(metaComposition);
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
service.Save(contentMetaComposition);
var metaAdded = contentPage.AddContentType(metaComposition);
service.Save(contentPage);
var metaAddedToComposition = contentMetaComposition.AddContentType(metaComposition);
service.Save(contentMetaComposition);
// Act
var propertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var addedToContentPage = contentPage.AddPropertyType(propertyType, "Content");
// Assert
Assert.That(metaAdded, Is.True);
Assert.That(metaAddedToComposition, Is.True);
Assert.That(addedToContentPage, Is.True);
Assert.DoesNotThrow(() => service.Save(contentPage));
}
[Test]
public void Can_Rename_PropertyGroup_With_Inherited_PropertyGroups()
{
//Related the first issue in screencast from this post http://issues.umbraco.org/issue/U4-5986
// Arrange
var service = ServiceContext.ContentTypeService;
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, false, "Content_");
service.Save(page);
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true);
service.Save(contentPage);
var composition = MockedContentTypes.CreateMetaContentType();
composition.AddPropertyGroup("Content");
service.Save(composition);
//Adding Meta-composition to child doc type
contentPage.AddContentType(composition);
service.Save(contentPage);
// Act
var propertyTypeOne = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "testTextbox", Name = "Test Textbox", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var firstOneAdded = contentPage.AddPropertyType(propertyTypeOne, "Content_");
var propertyTypeTwo = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "anotherTextbox", Name = "Another Test Textbox", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var secondOneAdded = contentPage.AddPropertyType(propertyTypeTwo, "Content");
service.Save(contentPage);
Assert.That(page.PropertyGroups.Contains("Content_"), Is.True);
var propertyGroup = page.PropertyGroups["Content_"];
page.PropertyGroups.Add(new PropertyGroup{ Id = propertyGroup.Id, Name = "ContentTab", SortOrder = 0});
service.Save(page);
// Assert
Assert.That(firstOneAdded, Is.True);
Assert.That(secondOneAdded, Is.True);
var contentType = service.GetContentType("contentPage");
Assert.That(contentType, Is.Not.Null);
var compositionPropertyGroups = contentType.CompositionPropertyGroups;
Assert.That(compositionPropertyGroups.Count(x => x.Name.Equals("Content_")), Is.EqualTo(0));
var propertyTypeCount = contentType.PropertyTypes.Count();
var compPropertyTypeCount = contentType.CompositionPropertyTypes.Count();
Assert.That(propertyTypeCount, Is.EqualTo(5));
Assert.That(compPropertyTypeCount, Is.EqualTo(10));
}
[Test]
public void Can_Rename_PropertyGroup_On_Parent_Without_Causing_Duplicate_PropertyGroups()
{
// Arrange
var service = ServiceContext.ContentTypeService;
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, true, "Content_");
service.Save(page);
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true, "Contentx");
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true, "Contenty");
service.Save(advancedPage);
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
service.Save(contentMetaComposition);
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
service.Save(contentPage);
// Act
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var bodyTextAdded = contentPage.AddPropertyType(bodyTextPropertyType, "Content_");//Will be added to the parent tab
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");//Will be added to the "Content Meta" composition
service.Save(contentPage);
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var descriptionPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "description", Name = "Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var keywordsPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "keywords", Name = "Keywords", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var authorAdded = advancedPage.AddPropertyType(authorPropertyType, "Content_");//Will be added to an ancestor tab
var descriptionAdded = advancedPage.AddPropertyType(descriptionPropertyType, "Contentx");//Will be added to a parent tab
var keywordsAdded = advancedPage.AddPropertyType(keywordsPropertyType, "Content");//Will be added to the "Content Meta" composition
service.Save(advancedPage);
//Change the name of the tab on the "root" content type 'page'.
var propertyGroup = page.PropertyGroups["Content_"];
page.PropertyGroups.Add(new PropertyGroup { Id = propertyGroup.Id, Name = "Content", SortOrder = 0 });
service.Save(page);
// Assert
Assert.That(compositionAdded, Is.True);
Assert.That(bodyTextAdded, Is.True);
Assert.That(subtitleAdded, Is.True);
Assert.That(authorAdded, Is.True);
Assert.That(descriptionAdded, Is.True);
Assert.That(keywordsAdded, Is.True);
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
var advancedPageReloaded = service.GetContentType("advancedPage");
var contentUnderscoreTabExists = advancedPageReloaded.CompositionPropertyGroups.Any(x => x.Name.Equals("Content_"));
Assert.That(contentUnderscoreTabExists, Is.False);
var numberOfContentTabs = advancedPageReloaded.CompositionPropertyGroups.Count(x => x.Name.Equals("Content"));
Assert.That(numberOfContentTabs, Is.EqualTo(4));
}
[Test]
public void Can_Rename_PropertyGroup_On_Parent_Without_Causing_Duplicate_PropertyGroups_v2()
{
// Arrange
var service = ServiceContext.ContentTypeService;
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, true, "Content_");
service.Save(page);
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true, "Content");
service.Save(contentPage);
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
service.Save(contentMetaComposition);
// Act
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var bodyTextAdded = page.AddPropertyType(bodyTextPropertyType, "Content_");
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content_");
service.Save(page);
service.Save(contentPage);
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
service.Save(contentPage);
//Change the name of the tab on the "root" content type 'page'.
var propertyGroup = page.PropertyGroups["Content_"];
page.PropertyGroups.Add(new PropertyGroup { Id = propertyGroup.Id, Name = "Content", SortOrder = 0 });
service.Save(page);
// Assert
Assert.That(compositionAdded, Is.True);
Assert.That(bodyTextAdded, Is.True);
Assert.That(subtitleAdded, Is.True);
Assert.That(authorAdded, Is.True);
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
}
[Test]
public void Can_Remove_PropertyGroup_On_Parent_Without_Causing_Duplicate_PropertyGroups()
{
// Arrange
var service = ServiceContext.ContentTypeService;
var basePage = MockedContentTypes.CreateBasicContentType();
service.Save(basePage);
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
service.Save(advancedPage);
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
service.Save(contentMetaComposition);
// Act
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
service.Save(basePage);
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
service.Save(contentPage);
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
service.Save(contentPage);
basePage.RemovePropertyGroup("Content");
service.Save(basePage);
// Assert
Assert.That(bodyTextAdded, Is.True);
Assert.That(authorAdded, Is.True);
Assert.That(compositionAdded, Is.True);
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
var contentType = service.GetContentType("contentPage");
var propertyGroup = contentType.PropertyGroups["Content"];
Assert.That(propertyGroup.ParentId.HasValue, Is.False);
}
[Test]
public void Can_Add_PropertyGroup_With_Same_Name_On_Parent_and_Child()
{
/*
* BasePage
* - Content Page
* -- Advanced Page
* Content Meta :: Composition
*/
// Arrange
var service = ServiceContext.ContentTypeService;
var basePage = MockedContentTypes.CreateBasicContentType();
service.Save(basePage);
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
service.Save(contentPage);
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
service.Save(advancedPage);
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
service.Save(contentMetaComposition);
// Act
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
service.Save(contentPage);
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
};
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
service.Save(basePage);
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
service.Save(contentPage);
// Assert
Assert.That(bodyTextAdded, Is.True);
Assert.That(authorAdded, Is.True);
Assert.That(compositionAdded, Is.True);
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
var contentType = service.GetContentType("contentPage");
var propertyGroup = contentType.PropertyGroups["Content"];
Assert.That(propertyGroup.ParentId.HasValue, Is.False);
var numberOfContentTabs = contentType.CompositionPropertyGroups.Count(x => x.Name.Equals("Content"));
Assert.That(numberOfContentTabs, Is.EqualTo(3));
//Ensure that adding a new PropertyType to the "Content"-tab also adds it to the right group
var descriptionPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
{
Alias = "description", Name = "Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 1,DataTypeDefinitionId = -88
};
var descriptionAdded = contentType.AddPropertyType(descriptionPropertyType, "Content");
service.Save(contentType);
Assert.That(descriptionAdded, Is.True);
var contentPageReloaded = service.GetContentType("contentPage");
var propertyGroupReloaded = contentPageReloaded.PropertyGroups["Content"];
var hasDescriptionPropertyType = propertyGroupReloaded.PropertyTypes.Contains("description");
Assert.That(hasDescriptionPropertyType, Is.True);
Assert.That(propertyGroupReloaded.ParentId.HasValue, Is.False);
var descriptionPropertyTypeReloaded = propertyGroupReloaded.PropertyTypes["description"];
Assert.That(descriptionPropertyTypeReloaded.PropertyGroupId.IsValueCreated, Is.False);
}
private ContentType CreateComponent()
@@ -487,9 +1251,10 @@ namespace Umbraco.Tests.Services
private ContentType CreateBannerComponent(ContentType parent)
{
var banner = new ContentType(parent)
const string contentTypeAlias = "banner";
var banner = new ContentType(parent, contentTypeAlias)
{
Alias = "banner",
Alias = contentTypeAlias,
Name = "Banner Component",
Description = "ContentType used for Banner Component",
Icon = ".sprTreeDoc3",
@@ -535,9 +1300,10 @@ namespace Umbraco.Tests.Services
private ContentType CreateHomepage(ContentType parent)
{
var contentType = new ContentType(parent)
const string contentTypeAlias = "homepage";
var contentType = new ContentType(parent, contentTypeAlias)
{
Alias = "homepage",
Alias = contentTypeAlias,
Name = "Homepage",
Description = "ContentType used for the Homepage",
Icon = ".sprTreeDoc3",
@@ -571,7 +1337,7 @@ namespace Umbraco.Tests.Services
{
var contentType = MockedContentTypes.CreateSimpleContentType("childType" + i, "ChildType" + i,
//make the last entry in the list, this one's parent
list.Last());
list.Last(), true);
list.Add(contentType);
}
@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<umbPackage>
<files />
<info>
<package>
<name>Composite Test</name>
<version>dfsfd</version>
<license url="http://opensource.org/licenses/MIT">MIT License</license>
<url>ddsff</url>
<requirements>
<major>3</major>
<minor>0</minor>
<patch>0</patch>
</requirements>
</package>
<author>
<name>fsdfds</name>
<website>sfdf</website>
</author>
<readme><![CDATA[sdffds]]></readme>
</info>
<Documents>
<DocumentSet importMode="root">
<CompositeTest id="1083" parentID="-1" level="1" creatorID="0" sortOrder="1" createDate="2014-11-26T15:02:43" updateDate="2014-11-26T15:02:43" nodeName="Composite test" urlName="composite-test" path="-1,1083" isDoc="" nodeType="1082" creatorName="Niels Hartvig" writerName="Niels Hartvig" writerID="0" template="1081" nodeTypeAlias="CompositeTest">
<description><![CDATA[Description]]></description>
<tags><![CDATA[umbraco,7.2]]></tags>
<fancy><![CDATA[Fancy pancy]]></fancy>
<content><![CDATA[<p>Hello World</p>]]></content>
</CompositeTest>
</DocumentSet>
</Documents>
<DocumentTypes>
<DocumentType>
<Info>
<Name>Composite Test</Name>
<Alias>CompositeTest</Alias>
<Icon>.sprTreeFolder</Icon>
<Thumbnail>folder.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Compositions>
<Composition>Meta</Composition>
<Composition>Seo</Composition>
<Composition>Content</Composition>
</Compositions>
<AllowedTemplates>
<Template>CompositeTest</Template>
</AllowedTemplates>
<DefaultTemplate>CompositeTest</DefaultTemplate>
</Info>
<Structure />
<GenericProperties />
<Tabs />
</DocumentType>
<DocumentType>
<Info>
<Name>Content</Name>
<Alias>Content</Alias>
<Icon>.sprTreeFolder</Icon>
<Thumbnail>folder.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Compositions />
<AllowedTemplates />
<DefaultTemplate />
</Info>
<Structure />
<GenericProperties>
<GenericProperty>
<Name>Content</Name>
<Alias>content</Alias>
<Type>Umbraco.TinyMCEv3</Type>
<Definition>ca90c950-0aff-4e72-b976-a30b1ac57dad</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
</GenericProperties>
<Tabs>
<Tab>
<Id>21</Id>
<Caption>Content</Caption>
<SortOrder>0</SortOrder>
</Tab>
</Tabs>
</DocumentType>
<DocumentType>
<Info>
<Name>Meta</Name>
<Alias>Meta</Alias>
<Icon>.sprTreeFolder</Icon>
<Thumbnail>folder.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Compositions />
<AllowedTemplates />
<DefaultTemplate />
</Info>
<Structure />
<GenericProperties>
<GenericProperty>
<Name>Description</Name>
<Alias>description</Alias>
<Type>Umbraco.TextboxMultiple</Type>
<Definition>c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3</Definition>
<Tab>Meta</Tab>
<Mandatory>True</Mandatory>
<Validation />
<Description><![CDATA[Enter a description]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Tags</Name>
<Alias>tags</Alias>
<Type>Umbraco.Tags</Type>
<Definition>b6b73142-b9c1-4bf8-a16d-e1c23320b549</Definition>
<Tab>Meta</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
</GenericProperties>
<Tabs>
<Tab>
<Id>19</Id>
<Caption>Meta</Caption>
<SortOrder>0</SortOrder>
</Tab>
</Tabs>
</DocumentType>
<DocumentType>
<Info>
<Name>SEO</Name>
<Alias>Seo</Alias>
<Icon>.sprTreeFolder</Icon>
<Thumbnail>folder.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Compositions />
<AllowedTemplates />
<DefaultTemplate />
</Info>
<Structure />
<GenericProperties>
<GenericProperty>
<Name>Fancy</Name>
<Alias>fancy</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>SEO</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
</GenericProperties>
<Tabs>
<Tab>
<Id>20</Id>
<Caption>SEO</Caption>
<SortOrder>0</SortOrder>
</Tab>
</Tabs>
</DocumentType>
</DocumentTypes>
<Templates />
<Stylesheets />
<Macros />
<DictionaryItems />
<Languages />
<DataTypes />
</umbPackage>
@@ -0,0 +1,924 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<umbPackage>
<files />
<info>
<package>
<name>Compositions Packaged</name>
<version>1.0</version>
<license url="http://opensource.org/licenses/MIT">MIT License</license>
<url>http://blog.sitereactor.dk</url>
<requirements>
<major>3</major>
<minor>0</minor>
<patch>0</patch>
</requirements>
</package>
<author>
<name>Morten Christensen</name>
<website>http://blog.sitereactor.dk</website>
</author>
<readme><![CDATA[This is a test of packaging compositions]]></readme>
</info>
<Documents>
<DocumentSet importMode="root">
<umbHomePage id="1068" parentID="-1" level="1" creatorID="0" sortOrder="0" createDate="2014-11-26T12:52:35" updateDate="2014-11-26T12:52:36" nodeName="Home" urlName="home" path="-1,1068" isDoc="" nodeType="1056" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1051" nodeTypeAlias="umbHomePage">
<umbracoNaviHide>0</umbracoNaviHide>
<title><![CDATA[Txt: A responsive starter kit for Umbraco]]></title>
<facebookLink><![CDATA[http://facebook.com/Umbraco]]></facebookLink>
<twitterLink><![CDATA[http://twitter.com/UmbracoProject]]></twitterLink>
<rssLink><![CDATA[http://feeds.feedburner.com/umbracoblog]]></rssLink>
<googleLink><![CDATA[https://google.com/+Umbraco]]></googleLink>
<hideBanner>0</hideBanner>
<bannerHeader><![CDATA[This is some text that needs to pop]]></bannerHeader>
<bannerSubheader><![CDATA[It will lead to a call-to-action, just click the button...]]></bannerSubheader>
<bannerLinkText><![CDATA[You know you want to click me]]></bannerLinkText>
<bannerLink>1054</bannerLink>
<bannerBackgroundImage><![CDATA[/media/SampleImages/1008/banner.jpg]]></bannerBackgroundImage>
<aboutTitle><![CDATA[What's this about?]]></aboutTitle>
<aboutText><![CDATA[<p>This is <a href="http://html5up.net/txt/">TXT</a>, a free site template designed by <a href="http://n33.co">n33</a> for <a href="http://html5up.net/">HTML5 UP</a>. It's built on the <a href="http://skeljs.org">skelJS</a> framework, uses well-thought out HTML5 and CSS3, and is fully responsive making it a great starting point for your own projects. And, like everything else we make, it's also free to use for pretty much any personal or commercial work under the <a href="http://html5up.net/license/">Creative Commons Attribution</a> license, so go ahead and use it just don't forget to credit us!</p>]]></aboutText>
<siteName><![CDATA[Umbraco Txt]]></siteName>
<byline><![CDATA[A responsive starter kit for Umbraco]]></byline>
<copyright><![CDATA[Umbraco]]></copyright>
<umbTextPage id="1069" parentID="1068" level="2" creatorID="0" sortOrder="0" createDate="2014-11-26T12:52:36" updateDate="2014-11-26T12:52:36" nodeName="Getting Started" urlName="getting-started" path="-1,1068,1069" isDoc="" nodeType="1059" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1054" nodeTypeAlias="umbTextPage">
<umbracoNaviHide>0</umbracoNaviHide>
<featuredPage>1</featuredPage>
<image><![CDATA[/media/SampleImages/1063/pic01.jpg]]></image>
<bodyText>
<![CDATA[<p>You've installed Umbraco and the "Txt" Starter Kit.</p>
<p>Edit the text on the homepage and create a site structure by adding new texpages to your site. This is all done in the <strong>Content</strong> section.</p>
<p>If you find the editing options provided by the Txt site too limited for you needs, simply add more properties to the page by going to the <strong>Settings</strong> section, expanding the <strong>Document Types</strong> item and adding new properties on the <strong>Generic Properties</strong> tab. You can find more information about <a href="http://umbraco.org/help-and-support/video-tutorials/introduction-to-umbraco/sitebuilder-introduction/document-types" title="About Umbraco Document Types">document types and properties</a> at the <a href="http://umbraco.com" title="The Umbraco Website">Umbraco website</a>.</p>
<p>You'll probably want to personalize your site by changing the current design. This is also done in the <strong>Settings</strong> section, by editing the CSS styles and HTML templates. Umbraco uses master templates, so the main, common markup is placed in the <strong>Starterkit Master</strong> template, while the Homeage and Textpage have separate templates for their unique layouts. You can find more information about <a href="http://umbraco.org/help-and-support/video-tutorials/introduction-to-umbraco/sitebuilder-introduction/templates" title="Umbraco Templates and Stylesheets">templates and css</a> in umbraco at the umbraco website.</p>
<p>Once you're happy with your site's design, you might want to add more functionality, such as maps, image galleries or forms. This is done by <a href="http://umbraco.org/help-and-support/video-tutorials/getting-started" title="Umbraco Modules">installing Umbraco modules</a>.</p>]]>
</bodyText>
</umbTextPage>
<umbTextPage id="1070" parentID="1068" level="2" creatorID="0" sortOrder="1" createDate="2014-11-26T12:52:36" updateDate="2014-11-26T12:52:36" nodeName="Go Further" urlName="go-further" path="-1,1068,1070" isDoc="" nodeType="1059" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1054" nodeTypeAlias="umbTextPage">
<umbracoNaviHide>0</umbracoNaviHide>
<featuredPage>1</featuredPage>
<image><![CDATA[/media/SampleImages/1060/pic02.jpg]]></image>
<bodyText>
<![CDATA[<p>The Txt Starter Kit only scratches the surface of what's possible with Umbraco. Below the Txt Starter Kit and its modules lies a great architecture that lets you implement whatever you need.</p>
<p>With Umbraco you've finally got a solid, open and reliable platform for websites as basic as the Txt site, and Umbraco can be rapidly expanded to support multi-language websites, collaboration platforms and intra/extranets, to name just a few.</p>
<p>Advanced functionality is created with Umbraco macros, built with Umbraco's award-winning .NET integration, including full support for any .NET User or Custom control and ASP.NET MVC. Create and integrate your own .NET macros in mere minutes with point and click simplicity. Simply copy your controls to the Umbraco website, go to the <strong>Developer</strong> section and create a new macro, selecting your control from the list.</p>
<p>You can also use <a href="http://umbraco.org/help-and-support/video-tutorials/getting-started/working-with-webmatrix" title="Working with Razor">Microsoft's Razor</a> syntax to quickly add dynamic functionality to your site.</p>
<p>We've also gathered the best community macros into a repository that's also accessed from the <strong>Developer</strong> section, in the <strong>Packages</strong> area. You can find more information <a href="http://umbraco.org/help-and-support/video-tutorials/introduction-to-umbraco/sitebuilder-introduction/what-are-macros" title="About creating Umbraco macros">about creating macros</a>, on the Umbraco website.</p>
<p>The sky is the limit with Umbraco, and you have the benefit a friendly community, training, and guaranteed support. Find out how to <a href="http://umbraco.org/help-and-support" title="Get Umbraco Support">get help</a>.</p>]]>
</bodyText>
</umbTextPage>
<umbTextPage id="1071" parentID="1068" level="2" creatorID="0" sortOrder="2" createDate="2014-11-26T12:52:36" updateDate="2014-11-26T12:52:36" nodeName="Installing Modules" urlName="installing-modules" path="-1,1068,1071" isDoc="" nodeType="1059" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1054" nodeTypeAlias="umbTextPage">
<umbracoNaviHide>0</umbracoNaviHide>
<featuredPage>1</featuredPage>
<image><![CDATA[/media/SampleImages/1061/pic04.jpg]]></image>
<bodyText>
<![CDATA[<p>Umbraco modules encapsulate specific bits of advanced functionality that are easily added to your website.</p>
<p>Once installed, Umbraco modules are open source and easy to customize if you want to modify the behavior for your specific needs.</p>
<p>Because Umbraco modules are provided under the MIT license you are free to use and modify them any way you want, with no strings attached.</p>
<p>To add Umbraco modules to your website, go to the <strong>Settings</strong> section, expand the <strong>Templates</strong> item, select the <strong>Starterkit Master</strong> template, then click the <strong>Customize Skin</strong> button on the toolbar.</p>
<p>Umbraco modules are available for various kinds of navigation, a sitemap, social media feeds, and a contact form. The list of available Umbraco modules is growing rapidly and is automatically updated from a central source, always fresh and current.</p>
<p><a href="http://umbraco.org/get-started" title="Get Started with Umbraco">Get more information</a> about the umbraco way.</p>]]>
</bodyText>
</umbTextPage>
<umbTextPage id="1072" parentID="1068" level="2" creatorID="0" sortOrder="3" createDate="2014-11-26T12:52:36" updateDate="2014-11-26T12:52:36" nodeName="About" urlName="about" path="-1,1068,1072" isDoc="" nodeType="1059" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1054" nodeTypeAlias="umbTextPage">
<umbracoNaviHide>0</umbracoNaviHide>
<featuredPage>1</featuredPage>
<image><![CDATA[/media/SampleImages/1001/pic03.jpg]]></image>
<bodyText>
<![CDATA[<p>The Txt Starter Kit gives you a small website that introduces you to a set of well-defined conventions for building an Umbraco website.</p>
<p>Now that you know what the Txt Starter Kit is, it is time to get started using Umbraco.</p>]]>
</bodyText>
</umbTextPage>
<umbNewsOverview id="1073" parentID="1068" level="2" creatorID="0" sortOrder="4" createDate="2014-11-26T12:52:36" updateDate="2014-11-26T12:52:36" nodeName="News" urlName="news" path="-1,1068,1073" isDoc="" nodeType="1058" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1053" nodeTypeAlias="umbNewsOverview">
<umbracoNaviHide>0</umbracoNaviHide>
<title><![CDATA[Adventure log]]></title>
<umbNewsItem id="1074" parentID="1073" level="3" creatorID="0" sortOrder="0" createDate="2014-11-26T12:52:36" updateDate="2014-11-26T12:52:36" nodeName="The 10 remarkable features of object" urlName="the-10-remarkable-features-of-object" path="-1,1068,1073,1074" isDoc="" nodeType="1057" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1052" nodeTypeAlias="umbNewsItem">
<umbracoNaviHide>0</umbracoNaviHide>
<bodyText>
<![CDATA[<p>Ita prorsus, inquam; Hanc ergo intuens debet institutum illud quasi signum absolvere. Ergo adhuc, quantum equidem intellego, causa non videtur fuisse mutandi nominis. Quia dolori non voluptas contraria est, sed doloris privatio. Nos autem non solum beatae vitae istam esse oblectationem videmus, sed etiam levamentum miseriarum. Quodsi ipsam honestatem undique pertectam atque absolutam. Nos cum te, M. Quod vestri non item.</p>
<p>Cum id quoque, ut cupiebat, audivisset, evelli iussit eam, qua erat transfixus, hastam. Quarum ambarum rerum cum medicinam pollicetur, luxuriae licentiam pollicetur. Quid iudicant sensus? Quo tandem modo?</p>]]>
</bodyText>
</umbNewsItem>
<umbNewsItem id="1075" parentID="1073" level="3" creatorID="0" sortOrder="1" createDate="2014-11-26T12:52:36" updateDate="2014-11-26T12:52:36" nodeName="This is a wonderful news item" urlName="this-is-a-wonderful-news-item" path="-1,1068,1073,1075" isDoc="" nodeType="1057" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1052" nodeTypeAlias="umbNewsItem">
<umbracoNaviHide>0</umbracoNaviHide>
<bodyText>
<![CDATA[<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Commoda autem et incommoda in eo genere sunt, quae praeposita et reiecta diximus; Bestiarum vero nullum iudicium puto. Est enim effectrix multarum et magnarum voluptatum. Duo Reges: constructio interrete. Claudii libidini, qui tum erat summo ne imperio, dederetur. Quarum ambarum rerum cum medicinam pollicetur, luxuriae licentiam pollicetur. Sed virtutem ipsam inchoavit, nihil amplius.</p>
<p>Ita redarguitur ipse a sese, convincunturque scripta eius probitate ipsius ac moribus. Istam voluptatem, inquit, Epicurus ignorat? Sed venio ad inconstantiae crimen, ne saepius dicas me aberrare; Sic, et quidem diligentius saepiusque ista loquemur inter nos agemusque communiter. Primum in nostrane potestate est, quid meminerimus? Consequens enim est et post oritur, ut dixi. Hoc mihi cum tuo fratre convenit. Immo videri fortasse. Itaque in rebus minime obscuris non multus est apud eos disserendi labor. Aliud igitur esse censet gaudere, aliud non dolere.</p>]]>
</bodyText>
</umbNewsItem>
<umbNewsItem id="1076" parentID="1073" level="3" creatorID="0" sortOrder="2" createDate="2014-11-26T12:52:36" updateDate="2014-11-26T12:52:36" nodeName="You really need to read this!" urlName="you-really-need-to-read-this" path="-1,1068,1073,1076" isDoc="" nodeType="1057" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1052" nodeTypeAlias="umbNewsItem">
<umbracoNaviHide>0</umbracoNaviHide>
<bodyText>
<![CDATA[<p><span>Ut aliquid scire se gaudeant? Hanc ergo intuens debet institutum illud quasi signum absolvere. Vestri haec verecundius, illi fortasse constantius. Itaque sensibus rationem adiunxit et ratione effecta sensus non reliquit. Sed ea mala virtuti magnitudine obruebantur. Quasi ego id curem, quid ille aiat aut neget. Verum tamen cum de rebus grandioribus dicas, ipsae res verba rapiunt; Apparet statim, quae sint officia, quae actiones.</span></p>
<p><span><span>Virtutibus igitur rectissime mihi videris et ad consuetudinem nostrae orationis vitia posuisse contraria. Nonne videmus quanta perturbatio rerum omnium consequatur, quanta confusio? Sed eum qui audiebant, quoad poterant, defendebant sententiam suam. Ut necesse sit omnium rerum, quae natura vigeant, similem esse finem, non eundem.</span></span></p>]]>
</bodyText>
</umbNewsItem>
<umbNewsItem id="1077" parentID="1073" level="3" creatorID="0" sortOrder="3" createDate="2014-11-26T12:52:36" updateDate="2014-11-26T12:52:36" nodeName="Txt Starter Kit For Umbraco Released" urlName="txt-starter-kit-for-umbraco-released" path="-1,1068,1073,1077" isDoc="" nodeType="1057" creatorName="Morten Christensen" writerName="Morten Christensen" writerID="0" template="1052" nodeTypeAlias="umbNewsItem">
<umbracoNaviHide>0</umbracoNaviHide>
<publishDate>2021-09-20T00:00:00</publishDate>
<image><![CDATA[/media/SampleImages/1077/pic05.jpg]]></image>
<subheader><![CDATA[In all it's MVC Views goodness]]></subheader>
<bodyText>
<![CDATA[<p><span>Sed ad haec, nisi molestum est, habeo quae velim. Neque enim disputari sine reprehensione nec cum iracundia aut pertinacia recte disputari potest. Nec vero alia sunt quaerenda contra Carneadeam illam sententiam. Deinde disputat, quod cuiusque generis animantium statui deceat extremum. Facit igitur Lucius noster prudenter, qui audire de summo bono potissimum velit; Quis non odit sordidos, vanos, leves, futtiles?</span></p>
<p><span><span>Negat enim summo bono afferre incrementum diem. Haec mihi videtur delicatior, ut ita dicam, molliorque ratio, quam virtutis vis gravitasque postulat. Haec quo modo conveniant, non sane intellego. Quis enim confidit semper sibi illud stabile et firmum permansurum, quod fragile et caducum sit? Multoque hoc melius nos veriusque quam Stoici. Igitur neque stultorum quisquam beatus neque sapientium non beatus. De hominibus dici non necesse est. Non enim iam stirpis bonum quaeret, sed animalis. Nobis Heracleotes ille Dionysius flagitiose descivisse videtur a Stoicis propter oculorum dolorem. At, illa, ut vobis placet, partem quandam tuetur, reliquam deserit.</span></span></p>]]>
</bodyText>
</umbNewsItem>
</umbNewsOverview>
</umbHomePage>
</DocumentSet>
</Documents>
<DocumentTypes>
<DocumentType>
<Info>
<Name>Master</Name>
<Alias>umbMaster</Alias>
<Icon>folder.gif</Icon>
<Thumbnail>folder.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Compositions />
<AllowedTemplates />
<DefaultTemplate />
</Info>
<Structure />
<GenericProperties>
<GenericProperty>
<Name>Hide in navigation?</Name>
<Alias>umbracoNaviHide</Alias>
<Type>Umbraco.TrueFalse</Type>
<Definition>92897bc6-a5f3-4ffe-ae27-f2e7e33dda49</Definition>
<Tab />
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[If set to "Yes", this page will be hidden from the navigation menu at the top.]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Page title</Name>
<Alias>title</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[The page title overrules the name this page was given. So if the page name is "About us" the title could be "About Our Company Name".]]></Description>
</GenericProperty>
</GenericProperties>
<Tabs>
<Tab>
<Id>12</Id>
<Caption>Content</Caption>
<SortOrder>0</SortOrder>
</Tab>
</Tabs>
</DocumentType>
<DocumentType>
<Info>
<Name>Home</Name>
<Alias>umbHomePage</Alias>
<Icon>.sprTreeSettingDomain</Icon>
<Thumbnail>docWithImage.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Master>umbMaster</Master>
<Compositions>
<Composition>umbMaster</Composition>
</Compositions>
<AllowedTemplates>
<Template>umbHomePage</Template>
</AllowedTemplates>
<DefaultTemplate>umbHomePage</DefaultTemplate>
</Info>
<Structure>
<DocumentType>umbTextPage</DocumentType>
</Structure>
<GenericProperties>
<GenericProperty>
<Name>Facebook link</Name>
<Alias>facebookLink</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Social</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Twitter link</Name>
<Alias>twitterLink</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Social</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Rss link</Name>
<Alias>rssLink</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Social</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Dribbble link</Name>
<Alias>dribbbleLink</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Social</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>LinkedIn link</Name>
<Alias>linkedInLink</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Social</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Google+ link</Name>
<Alias>googleLink</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Social</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Hide banner?</Name>
<Alias>hideBanner</Alias>
<Type>Umbraco.TrueFalse</Type>
<Definition>92897bc6-a5f3-4ffe-ae27-f2e7e33dda49</Definition>
<Tab>Banner</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Banner Header</Name>
<Alias>bannerHeader</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Banner</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Banner Subheader</Name>
<Alias>bannerSubheader</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Banner</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Banner link text</Name>
<Alias>bannerLinkText</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Banner</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Banner link</Name>
<Alias>bannerLink</Alias>
<Type>Umbraco.ContentPickerAlias</Type>
<Definition>a6857c73-d6e9-480c-b6e6-f15f6ad11125</Definition>
<Tab>Banner</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Banner background image</Name>
<Alias>bannerBackgroundImage</Alias>
<Type>Umbraco.UploadField</Type>
<Definition>84c6b441-31df-4ffe-b67e-67d5bc3ae65a</Definition>
<Tab>Banner</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>About Title</Name>
<Alias>aboutTitle</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>About</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>AboutText</Name>
<Alias>aboutText</Alias>
<Type>Umbraco.TinyMCEv3</Type>
<Definition>ca90c950-0aff-4e72-b976-a30b1ac57dad</Definition>
<Tab>About</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Site Name</Name>
<Alias>siteName</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Byline</Name>
<Alias>byline</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Copyright</Name>
<Alias>copyright</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
</GenericProperties>
<Tabs>
<Tab>
<Id>13</Id>
<Caption>Social</Caption>
<SortOrder>0</SortOrder>
</Tab>
<Tab>
<Id>14</Id>
<Caption>Banner</Caption>
<SortOrder>1</SortOrder>
</Tab>
<Tab>
<Id>15</Id>
<Caption>About</Caption>
<SortOrder>2</SortOrder>
</Tab>
<Tab>
<Id>16</Id>
<Caption>Content</Caption>
<SortOrder>3</SortOrder>
</Tab>
</Tabs>
</DocumentType>
<DocumentType>
<Info>
<Name>Meta</Name>
<Alias>Meta</Alias>
<Icon>icon-truck</Icon>
<Thumbnail>folder.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Compositions />
<AllowedTemplates />
<DefaultTemplate />
</Info>
<Structure />
<GenericProperties>
<GenericProperty>
<Name>Meta Keywords</Name>
<Alias>metaKeywords</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Meta</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
</GenericProperties>
<Tabs>
<Tab>
<Id>19</Id>
<Caption>Meta</Caption>
<SortOrder>9</SortOrder>
</Tab>
</Tabs>
</DocumentType>
<DocumentType>
<Info>
<Name>News Item</Name>
<Alias>umbNewsItem</Alias>
<Icon>.sprTreeDocPic</Icon>
<Thumbnail>docWithImage.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Master>umbMaster</Master>
<Compositions>
<Composition>umbMaster</Composition>
</Compositions>
<AllowedTemplates>
<Template>umbNewsItem</Template>
</AllowedTemplates>
<DefaultTemplate>umbNewsItem</DefaultTemplate>
</Info>
<Structure />
<GenericProperties>
<GenericProperty>
<Name>Publish date</Name>
<Alias>publishDate</Alias>
<Type>Umbraco.DateTime</Type>
<Definition>e4d66c0f-b935-4200-81f0-025f7256b89a</Definition>
<Tab />
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[You can overrule the date shown on the site by changing it here. If you don't set a date explicitly here then the news item's create date will be shown.]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Image</Name>
<Alias>image</Alias>
<Type>Umbraco.UploadField</Type>
<Definition>84c6b441-31df-4ffe-b67e-67d5bc3ae65a</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Subheader</Name>
<Alias>subheader</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Content</Name>
<Alias>bodyText</Alias>
<Type>Umbraco.TinyMCEv3</Type>
<Definition>ca90c950-0aff-4e72-b976-a30b1ac57dad</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
</GenericProperties>
<Tabs>
<Tab>
<Id>17</Id>
<Caption>Content</Caption>
<SortOrder>0</SortOrder>
</Tab>
</Tabs>
</DocumentType>
<DocumentType>
<Info>
<Name>News Overview</Name>
<Alias>umbNewsOverview</Alias>
<Icon>package.png</Icon>
<Thumbnail>folder_media.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Master>umbMaster</Master>
<Compositions>
<Composition>umbMaster</Composition>
</Compositions>
<AllowedTemplates>
<Template>umbNewsOverview</Template>
</AllowedTemplates>
<DefaultTemplate>umbNewsOverview</DefaultTemplate>
</Info>
<Structure>
<DocumentType>umbNewsItem</DocumentType>
</Structure>
<GenericProperties />
<Tabs />
</DocumentType>
<DocumentType>
<Info>
<Name>Seo</Name>
<Alias>Seo</Alias>
<Icon>icon-wifi</Icon>
<Thumbnail>folder.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Compositions />
<AllowedTemplates />
<DefaultTemplate />
</Info>
<Structure />
<GenericProperties>
<GenericProperty>
<Name>Seo Pimp Title</Name>
<Alias>seoPimpTitle</Alias>
<Type>Umbraco.Textbox</Type>
<Definition>0cc0eba1-9960-42c9-bf9b-60e150b429ae</Definition>
<Tab>Seo</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
</GenericProperties>
<Tabs>
<Tab>
<Id>20</Id>
<Caption>Seo</Caption>
<SortOrder>10</SortOrder>
</Tab>
</Tabs>
</DocumentType>
<DocumentType>
<Info>
<Name>Text Page</Name>
<Alias>umbTextyPage</Alias>
<Icon>.sprTreeDoc</Icon>
<Thumbnail>doc.png</Thumbnail>
<Description />
<AllowAtRoot>False</AllowAtRoot>
<IsListView>False</IsListView>
<Master>umbMaster</Master>
<Compositions>
<Composition>umbMaster</Composition>
<Composition>Meta</Composition>
<Composition>Seo</Composition>
</Compositions>
<AllowedTemplates>
<Template>umbTextyPage</Template>
</AllowedTemplates>
<DefaultTemplate>umbTextyPage</DefaultTemplate>
</Info>
<Structure>
<DocumentType>umbTextyPage</DocumentType>
</Structure>
<GenericProperties>
<GenericProperty>
<Name>Featured Page?</Name>
<Alias>featuredPage</Alias>
<Type>Umbraco.TrueFalse</Type>
<Definition>92897bc6-a5f3-4ffe-ae27-f2e7e33dda49</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[Is this a page that should be featured on the home page?]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Image</Name>
<Alias>image</Alias>
<Type>Umbraco.UploadField</Type>
<Definition>84c6b441-31df-4ffe-b67e-67d5bc3ae65a</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
<GenericProperty>
<Name>Content</Name>
<Alias>bodyText</Alias>
<Type>Umbraco.TinyMCEv3</Type>
<Definition>ca90c950-0aff-4e72-b976-a30b1ac57dad</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
<Validation />
<Description><![CDATA[]]></Description>
</GenericProperty>
</GenericProperties>
<Tabs>
<Tab>
<Id>18</Id>
<Caption>Content</Caption>
<SortOrder>0</SortOrder>
</Tab>
</Tabs>
</DocumentType>
</DocumentTypes>
<Templates>
<Template>
<Name>HomePage</Name>
<Alias>umbHomePage</Alias>
<Master>umbLayout</Master>
<Design>
<![CDATA[@inherits UmbracoTemplatePage
@{
Layout = "umbLayout.cshtml";
}
@{ Html.RenderPartial("umbHomepageBanner"); }
<!-- Main -->
<div id="main-wrapper">
<div id="main" class="container">
<div class="row">
<div class="12u">
@{ Html.RenderPartial("umbFeatures"); }
</div>
</div>
<div class="row">
<div class="12u">
@{ Html.RenderPartial("umbNewsOverviewWidget"); }
</div>
</div>
</div>
</div>
<!-- /Main -->
]]>
</Design>
</Template>
<Template>
<Name>Layout</Name>
<Alias>umbLayout</Alias>
<Design>
<![CDATA[@inherits UmbracoTemplatePage
@{
Layout = null;
}<!DOCTYPE html>
<!--
TXT 2.0 by HTML5 UP
html5up.net | twitter.com/n33co
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
<head>
<title>@Umbraco.Field("title", altFieldAlias: "pageName") | @Umbraco.Field("siteName", recursive: true)</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<link href="http://fonts.googleapis.com/css?family=Open+Sans:400,700|Open+Sans+Condensed:700" rel="stylesheet" />
<script src="/js/jquery.min.js"></script>
<script src="/js/config.js"></script>
<script src="/js/skel.min.js"></script>
<script src="/js/skel-panels.min.js"></script>
<noscript>
<link rel="stylesheet" href="/css/skel-noscript.css" />
<link rel="stylesheet" href="/css/style.css" />
<link rel="stylesheet" href="/css/style-desktop.css" />
</noscript>
<!--[if lte IE 9]><link rel="stylesheet" href="/css/ie9.css" /><![endif]-->
<!--[if lte IE 8]><script src="/js/html5shiv.js"></script><link rel="stylesheet" href="/css/ie8.css" /><![endif]-->
<!--[if lte IE 7]><link rel="stylesheet" href="/css/ie7.css" /><![endif]-->
</head>
<body class="homepage">
<!-- Header -->
<header id="header">
<div class="logo">
<div>
<h1><a href="/" id="logo">@Umbraco.Field("siteName", recursive: true)</a></h1>
<span class="byline">@Umbraco.Field("byline", recursive: true)</span>
</div>
</div>
</header>
<!-- /Header -->
@{ Html.RenderPartial("umbTopNavigation"); }
@RenderBody()
<!-- Footer -->
<footer id="footer" class="container">
<div class="row">
<div class="12u">
@{ Html.RenderPartial("umbAbout"); }
</div>
</div>
<div class="row">
<div class="12u">
@{ Html.RenderPartial("umbSocial"); }
</div>
</div>
<div class="row">
<!-- Copyright -->
<div id="copyright">
&copy; @DateTime.Now.Year @Umbraco.Field("copyright", recursive: true) | Images: <a href="http://fotogrph.com">fotogrph</a> + <a href="http://iconify.it">Iconify.it</a> | Design: <a href="http://html5up.net/">HTML5 UP</a>
</div>
<!-- /Copyright -->
</div>
</footer>
<!-- /Footer -->
</body>
</html>]]>
</Design>
</Template>
<Template>
<Name>News Item</Name>
<Alias>umbNewsItem</Alias>
<Master>umbLayout</Master>
<Design>
<![CDATA[@inherits UmbracoTemplatePage
@{
Layout = "umbLayout.cshtml";
// If the editor has not explicitly provided the "Page title" property page
// then just show the name of the page otherwise show the provided title
var pageTitle = string.IsNullOrWhiteSpace(CurrentPage.Title)
? CurrentPage.Name
: CurrentPage.Title;
}
<div id="main-wrapper">
<div id="main" class="container">
<div class="row">
<div class="9u skel-cell-mainContent">
<div class="content content-left">
<!-- Content -->
<article class="is-page-content">
<header>
<h2>@pageTitle</h2>
</header>
<section>
@if (string.IsNullOrWhiteSpace(CurrentPage.Image) == false)
{
<span class="image image-full"><img src="@CurrentPage.Image" alt="" /></span>
}
@CurrentPage.BodyText
</section>
</article>
<!-- /Content -->
</div>
</div>
<div class="3u">
<div class="sidebar">
<!-- Sidebar -->
@{ Html.RenderPartial("umbLatestNewsWidget"); }
<!-- /Sidebar -->
</div>
</div>
</div>
<div class="row">
<div class="12u">
@{ Html.RenderPartial("umbFeatures"); }
</div>
</div>
</div>
</div>
<!-- /Main -->]]>
</Design>
</Template>
<Template>
<Name>News Overview</Name>
<Alias>umbNewsOverview</Alias>
<Master>umbLayout</Master>
<Design>
<![CDATA[@inherits UmbracoTemplatePage
@{
Layout = "umbLayout.cshtml";
// If the editor has not explicitly provided the "Page title" property page
// then just show the name of the page otherwise show the provided title
var pageTitle = string.IsNullOrWhiteSpace(CurrentPage.Title)
? CurrentPage.Name
: CurrentPage.Title;
// Model.Content is the current page that we're on
// AncestorsOrSelf is all of the ancestors this page has in the tree
// (1) means: go up to level 1 and stop looking for more ancestors when you get there
// First() gets the first ancestor found (the home page, on level 1)
var homePage = CurrentPage.AncestorsOrSelf(1).First();
// Find all pages with document type alias umbNewsOverview
// We do that using the plural, umbNewsOverviews (note the extra "s" in the end)
// Then take the first one, as we know there will only be on news overview page
var newsOverview = homePage.umbNewsOverviews.First();
// Similar to above: find all pages with document type umbNewsItem under the news overview page
// Then order them, first by publishDate (a property the editor can explicitly set on the news item)
// and then by createDate, which is set by Umbraco automatically when a page gets created.
var newsItems = newsOverview.umbNewsItems.OrderBy("publishDate desc, createDate desc").Take(5);
}
<!-- Main -->
<div id="main-wrapper">
<div id="main" class="container">
<div class="row">
<div class="12u skel-cell-mainContent">
<div class="content">
<!-- Content -->
<article class="is-page-content">
<header>
<h2>@pageTitle</h2>
</header>
@foreach (var item in newsItems)
{
// If the editor has not explicitly provided the "Page title" property page
// then just show the name of the page otherwise show the provided title
var title = string.IsNullOrWhiteSpace(item.Title)
? item.Name
: item.Title;
// If the editor has not explicitly set the publishDate property then show the create date
var dateTime = item.PublishDate == default(DateTime)
? item.CreateDate
: item.PublishDate;
<section>
<h3><a href="@item.Url">@title</a></h3>
<span class="byline">@item.SubHeader</span>
<ul class="meta">
<li class="timestamp">@dateTime.ToString("f")</li>
</ul>
@if (string.IsNullOrWhiteSpace(item.Image) == false)
{
<a href="@item.Url" class="image image-full"><img src="@item.Image" alt="" /></a>
}
@Umbraco.Truncate(item.BodyText, 200)
<a href="@item.Url" class="button">Continue Reading</a>
</section>
}
</article>
<!-- /Content -->
</div>
</div>
</div>
<div class="row">
<div class="12u">
@{ Html.RenderPartial("umbFeatures"); }
</div>
</div>
</div>
</div>
<!-- /Main -->
]]>
</Design>
</Template>
<Template>
<Name>Text Page</Name>
<Alias>umbTextyPage</Alias>
<Master>umbLayout</Master>
<Design>
<![CDATA[@inherits UmbracoTemplatePage
@{
Layout = "umbLayout.cshtml";
// If the editor has not explicitly provided the "Page title" property page
// then just show the name of the page otherwise show the provided title
var pageTitle = string.IsNullOrWhiteSpace(CurrentPage.Title)
? CurrentPage.Name
: CurrentPage.Title;
}
<div id="main-wrapper">
<div id="main" class="container">
<div class="row">
<div class="9u skel-cell-mainContent">
<div class="content content-left">
<!-- Content -->
<article class="is-page-content">
<header>
<h2>@pageTitle</h2>
</header>
<section>
@if (string.IsNullOrWhiteSpace(CurrentPage.Image) == false)
{
<span class="image image-full"><img src="@CurrentPage.Image" alt="" /></span>
}
@CurrentPage.BodyText
</section>
</article>
<!-- /Content -->
</div>
</div>
<div class="3u">
<div class="sidebar">
<!-- Sidebar -->
@{ Html.RenderPartial("umbLatestNewsWidget"); }
<!-- /Sidebar -->
</div>
</div>
</div>
<div class="row">
<div class="12u">
@{ Html.RenderPartial("umbFeatures"); }
</div>
</div>
</div>
</div>
<!-- /Main -->]]>
</Design>
</Template>
</Templates>
<Stylesheets />
<Macros />
<DictionaryItems />
<Languages />
<DataTypes />
</umbPackage>
File diff suppressed because one or more lines are too long
+103 -21
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18051
// Runtime Version:4.0.30319.34209
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -88,6 +88,88 @@ namespace Umbraco.Tests.Services.Importing {
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
///&lt;umbPackage&gt;
/// &lt;files /&gt;
/// &lt;info&gt;
/// &lt;package&gt;
/// &lt;name&gt;CheckboxListTest&lt;/name&gt;
/// &lt;version&gt;1&lt;/version&gt;
/// &lt;license url=&quot;http://www.opensource.org/licenses/mit-license.php&quot;&gt;MIT license&lt;/license&gt;
/// &lt;url&gt;1&lt;/url&gt;
/// &lt;requirements&gt;
/// &lt;major&gt;3&lt;/major&gt;
/// &lt;minor&gt;0&lt;/minor&gt;
/// &lt;patch&gt;0&lt;/patch&gt;
/// &lt;/requirements&gt;
/// &lt;/package&gt;
/// &lt;author&gt;
/// &lt;name&gt;1&lt;/name&gt;
/// &lt;website&gt;1&lt;/website&gt;
/// &lt;/author&gt;
/// &lt;r [rest of string was truncated]&quot;;.
/// </summary>
internal static string CheckboxList_Content_Package_LegacyIds {
get {
return ResourceManager.GetString("CheckboxList_Content_Package_LegacyIds", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
///&lt;umbPackage&gt;
/// &lt;files /&gt;
/// &lt;info&gt;
/// &lt;package&gt;
/// &lt;name&gt;Compositions Packaged&lt;/name&gt;
/// &lt;version&gt;1.0&lt;/version&gt;
/// &lt;license url=&quot;http://opensource.org/licenses/MIT&quot;&gt;MIT License&lt;/license&gt;
/// &lt;url&gt;http://blog.sitereactor.dk&lt;/url&gt;
/// &lt;requirements&gt;
/// &lt;major&gt;3&lt;/major&gt;
/// &lt;minor&gt;0&lt;/minor&gt;
/// &lt;patch&gt;0&lt;/patch&gt;
/// &lt;/requirements&gt;
/// &lt;/package&gt;
/// &lt;author&gt;
/// &lt;name&gt;Morten Christensen&lt;/name&gt;
/// &lt;website&gt;h [rest of string was truncated]&quot;;.
/// </summary>
internal static string CompositionsTestPackage {
get {
return ResourceManager.GetString("CompositionsTestPackage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
///&lt;umbPackage&gt;
/// &lt;files /&gt;
/// &lt;info&gt;
/// &lt;package&gt;
/// &lt;name&gt;Composite Test&lt;/name&gt;
/// &lt;version&gt;dfsfd&lt;/version&gt;
/// &lt;license url=&quot;http://opensource.org/licenses/MIT&quot;&gt;MIT License&lt;/license&gt;
/// &lt;url&gt;ddsff&lt;/url&gt;
/// &lt;requirements&gt;
/// &lt;major&gt;3&lt;/major&gt;
/// &lt;minor&gt;0&lt;/minor&gt;
/// &lt;patch&gt;0&lt;/patch&gt;
/// &lt;/requirements&gt;
/// &lt;/package&gt;
/// &lt;author&gt;
/// &lt;name&gt;fsdfds&lt;/name&gt;
/// &lt;website&gt;sfdf&lt;/website&gt;
/// &lt;/author&gt;
/// &lt;rea [rest of string was truncated]&quot;;.
/// </summary>
internal static string CompositionsTestPackage_Random {
get {
return ResourceManager.GetString("CompositionsTestPackage_Random", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
///&lt;umbPackage&gt;
@@ -117,28 +199,28 @@ namespace Umbraco.Tests.Services.Importing {
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
///&lt;umbPackage&gt;
/// &lt;files /&gt;
/// &lt;info&gt;
/// &lt;package&gt;
/// &lt;name&gt;CheckboxListTest&lt;/name&gt;
/// &lt;version&gt;1&lt;/version&gt;
/// &lt;license url=&quot;http://www.opensource.org/licenses/mit-license.php&quot;&gt;MIT license&lt;/license&gt;
/// &lt;url&gt;1&lt;/url&gt;
/// &lt;requirements&gt;
/// &lt;major&gt;3&lt;/major&gt;
/// &lt;minor&gt;0&lt;/minor&gt;
/// &lt;patch&gt;0&lt;/patch&gt;
/// &lt;/requirements&gt;
/// &lt;/package&gt;
/// &lt;author&gt;
/// &lt;name&gt;1&lt;/name&gt;
/// &lt;website&gt;1&lt;/website&gt;
/// &lt;/author&gt;
/// &lt;r [rest of string was truncated]&quot;;.
/// &lt;files&gt;
/// &lt;file&gt;
/// &lt;guid&gt;bootstrap.min.js&lt;/guid&gt;
/// &lt;orgPath&gt;/js&lt;/orgPath&gt;
/// &lt;orgName&gt;bootstrap.min.js&lt;/orgName&gt;
/// &lt;/file&gt;
/// &lt;file&gt;
/// &lt;guid&gt;jquery.min.js&lt;/guid&gt;
/// &lt;orgPath&gt;/js&lt;/orgPath&gt;
/// &lt;orgName&gt;jquery.min.js&lt;/orgName&gt;
/// &lt;/file&gt;
/// &lt;file&gt;
/// &lt;guid&gt;top-image.jpg&lt;/guid&gt;
/// &lt;orgPath&gt;/Media/1001&lt;/orgPath&gt;
/// &lt;orgName&gt;top-image.jpg&lt;/orgName&gt;
/// &lt;/file&gt;
/// &lt;file&gt;
/// &lt;guid&gt;top-im [rest of string was truncated]&quot;;.
/// </summary>
internal static string CheckboxList_Content_Package_LegacyIds {
internal static string Fanoe_Package {
get {
return ResourceManager.GetString("CheckboxList_Content_Package_LegacyIds", resourceCulture);
return ResourceManager.GetString("Fanoe_Package", resourceCulture);
}
}
@@ -148,4 +148,13 @@
<data name="Dictionary_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>dictionary-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="CompositionsTestPackage" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>compositionstestpackage.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="CompositionsTestPackage_Random" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>compositionstestpackage-random.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="Fanoe_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>fanoe-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
</root>
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using NUnit.Framework;
@@ -210,6 +211,30 @@ namespace Umbraco.Tests.Services.Importing
Assert.That(templates.Any(), Is.True);
}
[Test]
public void PackagingService_Can_Import_Fanoe_Starterkit_ContentTypes_And_Templates_Xml()
{
// Arrange
string strXml = ImportResources.Fanoe_Package;
var xml = XElement.Parse(strXml);
var dataTypeElement = xml.Descendants("DataTypes").First();
var templateElement = xml.Descendants("Templates").First();
var docTypeElement = xml.Descendants("DocumentTypes").First();
// Act
var dataTypeDefinitions = ServiceContext.PackagingService.ImportDataTypeDefinitions(dataTypeElement);
var templates = ServiceContext.PackagingService.ImportTemplates(templateElement);
var contentTypes = ServiceContext.PackagingService.ImportContentTypes(docTypeElement);
var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count();
//Assert - Re-Import contenttypes doesn't throw
Assert.DoesNotThrow(() => ServiceContext.PackagingService.ImportContentTypes(docTypeElement));
Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes));
Assert.That(dataTypeDefinitions, Is.Not.Null);
Assert.That(dataTypeDefinitions.Any(), Is.True);
Assert.That(templates.Any(), Is.True);
}
[Test]
public void PackagingService_Can_Import_Content_Package_Xml()
{
@@ -554,6 +579,60 @@ namespace Umbraco.Tests.Services.Importing
}
}
[Test]
public void PackagingService_Can_Import_Package_With_Compositions()
{
// Arrange
string strXml = ImportResources.CompositionsTestPackage;
var xml = XElement.Parse(strXml);
var templateElement = xml.Descendants("Templates").First();
var docTypeElement = xml.Descendants("DocumentTypes").First();
var packagingService = ServiceContext.PackagingService;
// Act
var templates = packagingService.ImportTemplates(templateElement);
var contentTypes = packagingService.ImportContentTypes(docTypeElement);
var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count();
// Assert
Assert.That(contentTypes, Is.Not.Null);
Assert.That(contentTypes.Any(), Is.True);
Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes));
Assert.That(contentTypes.Count(x => x.ParentId == -1), Is.EqualTo(3));
var textpage = contentTypes.First(x => x.Alias.Equals("umbTextyPage"));
Assert.That(textpage.ParentId, Is.Not.EqualTo(-1));
Assert.That(textpage.ContentTypeComposition.Count(), Is.EqualTo(3));
Assert.That(textpage.ContentTypeCompositionExists("umbMaster"), Is.True);
Assert.That(textpage.ContentTypeCompositionExists("Meta"), Is.True);
Assert.That(textpage.ContentTypeCompositionExists("Seo"), Is.True);
}
[Test]
public void PackagingService_Can_Import_Package_With_Compositions_Ordered()
{
// Arrange
string strXml = ImportResources.CompositionsTestPackage_Random;
var xml = XElement.Parse(strXml);
var docTypeElement = xml.Descendants("DocumentTypes").First();
var packagingService = ServiceContext.PackagingService;
// Act
var contentTypes = packagingService.ImportContentTypes(docTypeElement);
var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count();
// Assert
Assert.That(contentTypes, Is.Not.Null);
Assert.That(contentTypes.Any(), Is.True);
Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes));
var testContentType = contentTypes.First(x => x.Alias.Equals("CompositeTest"));
Assert.That(testContentType.ContentTypeComposition.Count(), Is.EqualTo(3));
Assert.That(testContentType.ContentTypeCompositionExists("Content"), Is.True);
Assert.That(testContentType.ContentTypeCompositionExists("Meta"), Is.True);
Assert.That(testContentType.ContentTypeCompositionExists("Seo"), Is.True);
}
private void AddLanguages()
{
var norwegian = new Core.Models.Language("nb-NO");
@@ -356,7 +356,7 @@ namespace Umbraco.Tests.TestHelpers
var ctx = new UmbracoContext(
httpContext,
ApplicationContext,
new PublishedCaches(cache, new PublishedMediaCache()),
new PublishedCaches(cache, new PublishedMediaCache(ApplicationContext)),
new WebSecurity(httpContext, ApplicationContext));
if (setSingleton)
@@ -19,10 +19,7 @@ namespace Umbraco.Tests.TestHelpers
[SetUp]
public virtual void Initialize()
{
using (DisposableTimer.TraceDuration<BaseUmbracoConfigurationTest>("init"))
{
SettingsForTests.Reset();
}
SettingsForTests.Reset();
}
@@ -30,10 +27,7 @@ namespace Umbraco.Tests.TestHelpers
public virtual void TearDown()
{
//reset settings
using (DisposableTimer.TraceDuration<BaseUmbracoConfigurationTest>("teardown"))
{
SettingsForTests.Reset();
}
SettingsForTests.Reset();
}
}
@@ -69,7 +69,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
title = name + " textpage",
bodyText = string.Format("This is a textpage based on the {0} ContentType", contentType.Alias),
keywords = "text,page,meta",
metaDescription = "This is the meta description for a textpage"
description = "This is the meta description for a textpage"
};
content.PropertyValues(obj);
@@ -121,7 +121,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
title = name + " title",
bodyText = string.Format("This is a textpage based on the {0} ContentType", contentType.Alias),
keywords = "text,page,meta",
metaDescription = "This is the meta description for a textpage"
description = "This is the meta description for a textpage"
};
content.PropertyValues(obj);
@@ -1,13 +1,30 @@
using System;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
namespace Umbraco.Tests.TestHelpers.Entities
{
public class MockedContentTypes
{
public static ContentType CreateBasicContentType(string alias = "basePage", string name = "Base Page",
ContentType parent = null)
{
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
contentType.Alias = alias;
contentType.Name = name;
contentType.Description = "ContentType used for basic pages";
contentType.Icon = ".sprTreeDoc3";
contentType.Thumbnail = "doc2.png";
contentType.SortOrder = 1;
contentType.CreatorId = 0;
contentType.Trashed = false;
//ensure that nothing is marked as dirty
contentType.ResetDirtyProperties(false);
return contentType;
}
public static ContentType CreateTextpageContentType(string alias = "textPage", string name = "Text Page")
{
@@ -29,7 +46,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
var metaCollection = new PropertyTypeCollection();
metaCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "keywords", Name = "Meta Keywords", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
metaCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "metaDescription", Name = "Meta Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -89 });
metaCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "description", Name = "Meta Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -89 });
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
contentType.PropertyGroups.Add(new PropertyGroup(metaCollection) { Name = "Meta", SortOrder = 2 });
@@ -66,6 +83,57 @@ namespace Umbraco.Tests.TestHelpers.Entities
return contentType;
}
public static ContentType CreateContentMetaContentType()
{
var contentType = new ContentType(-1)
{
Alias = "contentMeta",
Name = "Content Meta",
Description = "ContentType used for Content Meta",
Icon = ".sprTreeDoc3",
Thumbnail = "doc.png",
SortOrder = 1,
CreatorId = 0,
Trashed = false
};
var metaCollection = new PropertyTypeCollection();
metaCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
contentType.PropertyGroups.Add(new PropertyGroup(metaCollection) { Name = "Content", SortOrder = 2 });
//ensure that nothing is marked as dirty
contentType.ResetDirtyProperties(false);
return contentType;
}
public static ContentType CreateSeoContentType()
{
var contentType = new ContentType(-1)
{
Alias = "seo",
Name = "Seo",
Description = "ContentType used for Seo",
Icon = ".sprTreeDoc3",
Thumbnail = "doc.png",
SortOrder = 1,
CreatorId = 0,
Trashed = false
};
var metaCollection = new PropertyTypeCollection();
metaCollection.Add(new PropertyType("seotest", DataTypeDatabaseType.Ntext) { Alias = "seokeywords", Name = "Seo Keywords", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
metaCollection.Add(new PropertyType("seotest", DataTypeDatabaseType.Ntext) { Alias = "seodescription", Name = "Seo Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -89 });
contentType.PropertyGroups.Add(new PropertyGroup(metaCollection) { Name = "Seo", SortOrder = 5 });
//ensure that nothing is marked as dirty
contentType.ResetDirtyProperties(false);
return contentType;
}
public static ContentType CreateSimpleContentType()
{
var contentType = new ContentType(-1)
@@ -93,9 +161,9 @@ namespace Umbraco.Tests.TestHelpers.Entities
return contentType;
}
public static ContentType CreateSimpleContentType(string alias, string name, IContentType parent = null)
public static ContentType CreateSimpleContentType(string alias, string name, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content")
{
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent);
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
contentType.Alias = alias;
contentType.Name = name;
@@ -107,11 +175,11 @@ namespace Umbraco.Tests.TestHelpers.Entities
contentType.Trashed = false;
var contentCollection = new PropertyTypeCollection();
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TinyMCEAlias, DataTypeDatabaseType.Ntext) { Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -87 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = "author", Name = "Author", Description = "Name of the author", HelpText = "", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = RandomAlias("title", randomizeAliases), Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TinyMCEAlias, DataTypeDatabaseType.Ntext) { Alias = RandomAlias("bodyText", randomizeAliases), Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -87 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = RandomAlias("author", randomizeAliases) , Name = "Author", Description = "Name of the author", HelpText = "", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 });
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = propertyGroupName, SortOrder = 1 });
//ensure that nothing is marked as dirty
contentType.ResetDirtyProperties(false);
@@ -168,6 +236,27 @@ namespace Umbraco.Tests.TestHelpers.Entities
return contentType;
}
public static ContentType CreateSimpleContentType(string alias, string name, PropertyTypeCollection collection, string propertyGroupName, IContentType parent = null)
{
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
contentType.Alias = alias;
contentType.Name = name;
contentType.Description = "ContentType used for simple text pages";
contentType.Icon = ".sprTreeDoc3";
contentType.Thumbnail = "doc2.png";
contentType.SortOrder = 1;
contentType.CreatorId = 0;
contentType.Trashed = false;
contentType.PropertyGroups.Add(new PropertyGroup(collection) { Name = propertyGroupName, SortOrder = 1 });
//ensure that nothing is marked as dirty
contentType.ResetDirtyProperties(false);
return contentType;
}
public static ContentType CreateSimpleContentType(string alias, string name, PropertyTypeCollection groupedCollection, PropertyTypeCollection nonGroupedCollection)
{
var contentType = CreateSimpleContentType(alias, name, groupedCollection);
@@ -307,5 +396,15 @@ namespace Umbraco.Tests.TestHelpers.Entities
return contentType;
}
private static string RandomAlias(string alias, bool randomizeAliases)
{
if (randomizeAliases)
{
return string.Concat(alias, Guid.NewGuid().ToString("N"));
}
return alias;
}
}
}
@@ -1,127 +1,123 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using umbraco.cms.presentation.Trees;
namespace Umbraco.Tests.Trees
{
[TestFixture]
public class BaseContentTreeTests
{
[TearDown]
public void TestTearDown()
{
BaseTree.AfterTreeRender -= EventHandler;
BaseTree.BeforeTreeRender -= EventHandler;
}
[Test]
public void Run_Optimized()
{
var tree1 = new MyOptimizedContentTree1("content");
var tree2 = new MyOptimizedContentTree2("content");
Assert.IsTrue(tree1.UseOptimizedRendering);
Assert.IsTrue(tree2.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_AfterRender()
{
var tree = new MyOptimizedContentTree1("content");
BaseTree.AfterTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_BeforeRender()
{
var tree = new MyOptimizedContentTree1("content");
BaseTree.BeforeTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Overriden_Method()
{
var tree = new MyNotOptimizedContentTree("content");
Assert.IsFalse(tree.UseOptimizedRendering);
}
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
{
}
//optimized because we are not overriding OnRenderNode
public class MyOptimizedContentTree1 : BaseContentTree
{
public MyOptimizedContentTree1(string application)
: base(application)
{
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
}
public class MyOptimizedContentTree2 : BaseContentTree
{
public MyOptimizedContentTree2(string application)
: base(application)
{
}
protected override bool LoadMinimalDocument
{
get { return true; }
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
//even if we override it will still be optimized because of the LoadMinimalDocument flag
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
{
base.OnRenderNode(ref xNode, doc);
}
}
public class MyNotOptimizedContentTree : BaseContentTree
{
public MyNotOptimizedContentTree(string application)
: base(application)
{
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
protected override bool LoadMinimalDocument
{
get { return false; }
}
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
{
base.OnRenderNode(ref xNode, doc);
}
}
}
}
using NUnit.Framework;
using umbraco.cms.presentation.Trees;
namespace Umbraco.Tests.TreesAndSections
{
[TestFixture]
public class BaseContentTreeTests
{
[TearDown]
public void TestTearDown()
{
BaseTree.AfterTreeRender -= EventHandler;
BaseTree.BeforeTreeRender -= EventHandler;
}
[Test]
public void Run_Optimized()
{
var tree1 = new MyOptimizedContentTree1("content");
var tree2 = new MyOptimizedContentTree2("content");
Assert.IsTrue(tree1.UseOptimizedRendering);
Assert.IsTrue(tree2.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_AfterRender()
{
var tree = new MyOptimizedContentTree1("content");
BaseTree.AfterTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_BeforeRender()
{
var tree = new MyOptimizedContentTree1("content");
BaseTree.BeforeTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Overriden_Method()
{
var tree = new MyNotOptimizedContentTree("content");
Assert.IsFalse(tree.UseOptimizedRendering);
}
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
{
}
//optimized because we are not overriding OnRenderNode
public class MyOptimizedContentTree1 : BaseContentTree
{
public MyOptimizedContentTree1(string application)
: base(application)
{
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
}
public class MyOptimizedContentTree2 : BaseContentTree
{
public MyOptimizedContentTree2(string application)
: base(application)
{
}
protected override bool LoadMinimalDocument
{
get { return true; }
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
//even if we override it will still be optimized because of the LoadMinimalDocument flag
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
{
base.OnRenderNode(ref xNode, doc);
}
}
public class MyNotOptimizedContentTree : BaseContentTree
{
public MyNotOptimizedContentTree(string application)
: base(application)
{
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
protected override bool LoadMinimalDocument
{
get { return false; }
}
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
{
base.OnRenderNode(ref xNode, doc);
}
}
}
}
@@ -1,65 +1,65 @@
using NUnit.Framework;
using umbraco.cms.presentation.Trees;
namespace Umbraco.Tests.Trees
{
[TestFixture]
public class BaseMediaTreeTests
{
[TearDown]
public void TestTearDown()
{
BaseTree.AfterTreeRender -= EventHandler;
BaseTree.BeforeTreeRender -= EventHandler;
}
[Test]
public void Run_Optimized()
{
var tree = new MyOptimizedMediaTree("media");
Assert.IsTrue(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_AfterRender()
{
var tree = new MyOptimizedMediaTree("media");
BaseTree.AfterTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_BeforeRender()
{
var tree = new MyOptimizedMediaTree("media");
BaseTree.BeforeTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
{
}
public class MyOptimizedMediaTree : BaseMediaTree
{
public MyOptimizedMediaTree(string application)
: base(application)
{
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
}
}
using NUnit.Framework;
using umbraco.cms.presentation.Trees;
namespace Umbraco.Tests.TreesAndSections
{
[TestFixture]
public class BaseMediaTreeTests
{
[TearDown]
public void TestTearDown()
{
BaseTree.AfterTreeRender -= EventHandler;
BaseTree.BeforeTreeRender -= EventHandler;
}
[Test]
public void Run_Optimized()
{
var tree = new MyOptimizedMediaTree("media");
Assert.IsTrue(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_AfterRender()
{
var tree = new MyOptimizedMediaTree("media");
BaseTree.AfterTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_BeforeRender()
{
var tree = new MyOptimizedMediaTree("media");
BaseTree.BeforeTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
{
}
public class MyOptimizedMediaTree : BaseMediaTree
{
public MyOptimizedMediaTree(string application)
: base(application)
{
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
}
}
}
+20 -17
View File
@@ -132,9 +132,9 @@
<Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.30506.0\lib\net40\System.Web.Http.WebHost.dll</HintPath>
</Reference>
<Reference Include="System.Web.Mvc, Version=4.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.40804.0\lib\net40\System.Web.Mvc.dll</HintPath>
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
@@ -282,7 +282,7 @@
<Compile Include="Controllers\WebApiEditors\FilterAllowedOutgoingContentAttributeTests.cs" />
<Compile Include="Controllers\WebApiEditors\MediaControllerUnitTests.cs" />
<Compile Include="CoreXml\FrameworkXmlTests.cs" />
<Compile Include="Dynamics\QueryableExtensionTests.cs" />
<Compile Include="DynamicsAndReflection\QueryableExtensionTests.cs" />
<Compile Include="DynamicsAndReflection\ExtensionMethodFinderTests.cs" />
<Compile Include="DynamicsAndReflection\ReflectionTests.cs" />
<Compile Include="Integration\CreateContent.cs" />
@@ -318,6 +318,8 @@
<Compile Include="PublishedContent\StronglyTypedModels\Textpage.cs" />
<Compile Include="PublishedContent\StronglyTypedModels\TypedModelBase.cs" />
<Compile Include="PublishedContent\StronglyTypedModels\UmbracoTemplatePage`T.cs" />
<Compile Include="Scheduling\BackgroundTaskRunnerTests.cs" />
<Compile Include="ServerEnvironmentHelperTests.cs" />
<Compile Include="Services\TagServiceTests.cs" />
<Compile Include="Services\LocalizationServiceTests.cs" />
<Compile Include="Resolvers\XsltExtensionsResolverTests.cs" />
@@ -382,7 +384,7 @@
<Compile Include="PublishedContent\PublishedContentTests.cs" />
<Compile Include="PublishedContent\PublishedMediaTests.cs" />
<Compile Include="HashCodeCombinerTests.cs" />
<Compile Include="HtmlHelperExtensionMethodsTests.cs" />
<Compile Include="Mvc\HtmlHelperExtensionMethodsTests.cs" />
<Compile Include="IO\IOHelperTest.cs" />
<Compile Include="LibraryTests.cs" />
<Compile Include="PropertyEditors\PropertyEditorValueConverterTests.cs" />
@@ -470,15 +472,15 @@
<DependentUpon>ImportResources.resx</DependentUpon>
</Compile>
<Compile Include="Services\ThreadSafetyServiceTest.cs" />
<Compile Include="Surface\PluginControllerAreaTests.cs" />
<Compile Include="Sync\DistributedCacheTests.cs" />
<Compile Include="Controllers\PluginControllerAreaTests.cs" />
<Compile Include="DistributedCache\DistributedCacheTests.cs" />
<Compile Include="Templates\MasterPageHelperTests.cs" />
<Compile Include="TestHelpers\BaseDatabaseFactoryTest.cs" />
<Compile Include="TestHelpers\BaseRoutingTest.cs" />
<Compile Include="TestHelpers\BaseUmbracoApplicationTest.cs" />
<Compile Include="TestHelpers\DatabaseBehavior.cs" />
<Compile Include="TestHelpers\SettingsForTests.cs" />
<Compile Include="GlobalSettingsTests.cs" />
<Compile Include="Configurations\GlobalSettingsTests.cs" />
<Compile Include="Routing\ContentFinderByAliasTests.cs" />
<Compile Include="Routing\ContentFinderByIdTests.cs" />
<Compile Include="Routing\ContentFinderByNiceUrlAndTemplateTests.cs" />
@@ -496,11 +498,11 @@
<Compile Include="TestHelpers\Entities\MockedEntity.cs" />
<Compile Include="TestHelpers\Entities\MockedMedia.cs" />
<Compile Include="TestHelpers\DisposableUmbracoTest.cs" />
<Compile Include="Trees\BaseContentTreeTests.cs" />
<Compile Include="Trees\BaseMediaTreeTests.cs" />
<Compile Include="TreesAndSections\BaseContentTreeTests.cs" />
<Compile Include="TreesAndSections\BaseMediaTreeTests.cs" />
<Compile Include="UmbracoExamine\ContentServiceTest.cs" />
<Compile Include="UmbracoExamine\EventsTest.cs" />
<Compile Include="TypeHelperTests.cs" />
<Compile Include="Plugins\TypeHelperTests.cs" />
<Compile Include="UmbracoExamine\ExamineBaseTest.cs" />
<Compile Include="UmbracoExamine\IndexInitializer.cs" />
<Compile Include="UmbracoExamine\IndexTest.cs" />
@@ -520,11 +522,11 @@
<Compile Include="UriExtensionsTests.cs" />
<Compile Include="UriUtilityTests.cs" />
<Compile Include="Resolvers\MacroFieldEditorsResolverTests.cs" />
<Compile Include="MacroEngineFactoryTests.cs" />
<Compile Include="Macros\MacroEngineFactoryTests.cs" />
<Compile Include="MediaFactoryTests.cs" />
<Compile Include="Resolvers\PackageActionsResolverTests.cs" />
<Compile Include="PluginManagerExtensions.cs" />
<Compile Include="PluginManagerTests.cs" />
<Compile Include="Plugins\PluginManagerExtensions.cs" />
<Compile Include="Plugins\PluginManagerTests.cs" />
<Compile Include="TestHelpers\Stubs\FakeLastChanceFinder.cs" />
<Compile Include="TestHelpers\TestHelper.cs" />
<Compile Include="EnumerableExtensionsTests.cs" />
@@ -534,7 +536,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="CoreStrings\StringExtensionsTests.cs" />
<Compile Include="TestHelpers\FakeHttpContextFactory.cs" />
<Compile Include="TypeFinderTests.cs" />
<Compile Include="Plugins\TypeFinderTests.cs" />
<Compile Include="Routing\UmbracoModuleTests.cs" />
<Compile Include="XmlExtensionsTests.cs" />
<Compile Include="XmlHelperTests.cs" />
@@ -692,7 +694,10 @@
<Content Include="Services\Importing\CheckboxList-Content-Package.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="Services\Importing\CompositionsTestPackage-Random.xml" />
<Content Include="Services\Importing\CompositionsTestPackage.xml" />
<Content Include="Services\Importing\Dictionary-Package.xml" />
<Content Include="Services\Importing\Fanoe-Package.xml" />
<Content Include="UmbracoExamine\TestFiles\media.xml" />
<Content Include="Services\Importing\InheritedDocTypes-Package.xml" />
<Content Include="Services\Importing\SingleDocType.xml" />
@@ -704,9 +709,7 @@
<Content Include="Services\Importing\uBlogsy-Package.xml" />
<Content Include="Services\Importing\XsltSearch-Package.xml" />
</ItemGroup>
<ItemGroup>
<Folder Include="Install\" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
+1 -1
View File
@@ -5,7 +5,7 @@
<package id="Examine" version="0.1.57.2941" targetFramework="net40" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
<package id="Microsoft.AspNet.Mvc" version="4.0.40804.0" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.1" targetFramework="net40" />
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net40" />
<package id="Microsoft.AspNet.WebApi" version="4.0.30506.0" targetFramework="net45" />
-1
View File
@@ -17,7 +17,6 @@
],
"dependencies": {
"typeahead.js": "~0.10.5",
"ace-builds": "~1.1.3",
"rgrove-lazyload": "*"
}
}
+10 -6
View File
@@ -18,8 +18,9 @@ module.exports = function (grunt) {
//triggered from grunt dev or grunt
grunt.registerTask('build', ['clean', 'concat', 'recess:min', 'recess:installer', 'recess:canvasdesigner', 'bower', 'copy']);
//build-dev doesn't min - we are trying to speed this up and we don't want minified stuff when we are in dev mode
grunt.registerTask('build-dev', ['clean', 'concat', 'recess:build', 'recess:installer', 'copy']);
//build-dev doesn't min - we are trying to speed this up and we don't want minified stuff when we are in dev mode
grunt.registerTask('build-dev', ['clean', 'concat', 'recess:build', 'recess:installer', 'copy']);
//utillity tasks
grunt.registerTask('docs', ['ngdocs']);
@@ -31,9 +32,9 @@ module.exports = function (grunt) {
grunt.log.subhead(Date());
});
// Custom task to run the bower dependency installer
// tried, a few other things but this seems to work the best.
// https://coderwall.com/p/xnkdqw
// Custom task to run the bower dependency installer
// tried, a few other things but this seems to work the best.
// https://coderwall.com/p/xnkdqw
grunt.registerTask('bower', 'Get js packages listed in bower.json',
function () {
var bower = require('bower');
@@ -108,7 +109,7 @@ module.exports = function (grunt) {
vsdir: '../Umbraco.Web.UI/umbraco',
pkg: grunt.file.readJSON('package.json'),
banner:
'/*! <%= pkg.title || pkg.name %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
'/*! <%= pkg.title || pkg.name %>\n' +
'<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
@@ -137,6 +138,9 @@ module.exports = function (grunt) {
files: [{ dest: '<%= distdir %>/assets', src : '**', expand: true, cwd: 'src/assets/' }]
},
config: {
files: [{ dest: '<%= distdir %>/../config', src : '**', expand: true, cwd: 'src/config/' }]
},
// Copies over the files downloaded by bower
bower: {
@@ -1 +1,7 @@
tinymce.PluginManager.add("code",function(e){function o(){e.windowManager.open({title:"Source code",body:{type:"textbox",name:"code",multiline:!0,minWidth:e.getParam("code_dialog_width",600),minHeight:e.getParam("code_dialog_height",Math.min(tinymce.DOM.getViewPort().h-200,500)),value:e.getContent({source_view:!0}),spellcheck:!1,style:"direction: ltr; text-align: left"},onSubmit:function(o){e.focus(),e.undoManager.transact(function(){e.setContent(o.data.code)}),e.selection.setCursorLocation(),e.nodeChanged()}})}e.addCommand("mceCodeEditor",o),e.addButton("code",{icon:"code",tooltip:"Source code",onclick:o}),e.addMenuItem("code",{icon:"code",text:"Source code",context:"tools",onclick:o})});
tinymce.PluginManager.add("code", function(e) {
function o() {
e.windowManager.open({ title: "Source code", body: { type: "textbox", name: "code", multiline: !0, minWidth: e.getParam("code_dialog_width", 600), minHeight: e.getParam("code_dialog_height", Math.min(tinymce.DOM.getViewPort().h - 200, 500)), value: e.getContent({ source_view: !0 }), spellcheck: !1, style: "direction: ltr; text-align: left" }, onSubmit: function(o) { e.focus(), e.undoManager.transact(function() { e.setContent(o.data.code) }), e.selection.setCursorLocation(), e.nodeChanged() } })
}
e.addCommand("mceCodeEditor", o), e.addButton("code", { icon: "code", tooltip: "Source code", onclick: o }), e.addMenuItem("code", { icon: "code", text: "Source code", context: "tools", onclick: o })
});

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