Compare commits

...

409 Commits

Author SHA1 Message Date
Sebastiaan Janssen 2bc33e0115 Merge 2013-03-27 08:58:34 -01:00
Sebastiaan Janssen 8576d9c67e Bump version to 4.11.6 2013-03-27 08:56:30 -01:00
Shannon Deminick 9452d5fd09 adds patch for #U4-1754 and updates 2013-03-27 03:08:37 +06:00
Shannon Deminick 1f40d726de adds patch for #U4-1754 2013-03-27 02:59:42 +06:00
Shannon Deminick 2699611ba3 adds patch for #U4-1754 2013-03-27 02:58:59 +06:00
Shannon Deminick b1fa06bfe8 Removes unused code. 2013-03-26 22:02:49 +06:00
Shannon Deminick 4dc22b6ce4 Applies patch for #U4-497 for getting exceptions for xslt 2013-03-26 22:02:08 +06:00
Sebastiaan Janssen 883277125a Can't use parameters here as the query gets butchered. 2013-03-26 13:27:46 -01:00
Sebastiaan Janssen ff961abaab Actual fix for U4-1987 Error when attempting to save document type 2013-03-26 09:50:48 -01:00
Sebastiaan Janssen b2414c1ab8 Fixes U4-1987 Error when attempting to save document type 2013-03-26 09:33:08 -01:00
Stephen Roberts 0e392b398c Fixed Property order for document types with Master document types. 2013-03-14 11:08:02 +00:00
Sebastiaan Janssen 5914690ad8 Allow leading sign in number field so that negative numbers are supported 2013-03-25 10:09:02 -01:00
Shannon Deminick dbbdd16bb9 Fixes: #U4-497 2013-03-23 02:34:34 +06:00
Shannon Deminick 762cca145f Fixes: #U4-1931 - allow empty string in dictionary item. 2013-03-22 21:59:21 +06:00
Morten Christensen 5cd2d568e3 Fixes U4-1938 by actually calling and checking the Before/AfterDelete events for DataTypeDefinitions.
Backported from 32fb51f603a3
2013-03-22 11:12:32 -01:00
Sebastiaan Janssen 259fbcb8f0 Fixed U4-1934 Error in comments of config files 2013-03-18 08:50:24 -01:00
Shannon Deminick db3f21429e Fixes infinite loop bug with string trimming. 2013-03-15 11:31:11 +06:00
Shannon Deminick 04b9607741 Fixes: #U4-1916 and another issue for vdirs, added unit tests, changed UI web project to always
launch in a VDIR.
2013-03-15 08:03:19 +04:00
Shannon Deminick 5bd2571395 Merge 2013-03-12 00:01:14 +04:00
Shannon Deminick c0cd157e60 applies patch for #U4-1890 2013-03-12 00:00:55 +04:00
Sebastiaan Janssen ac2f9b172c .transformed files are auto-generated and shouldn't be under source control 2013-03-11 17:15:30 -01:00
Sebastiaan Janssen b8e4a73c3b Revert Casey's mistakenly added files 2013-03-11 15:55:35 -01:00
Shannon Deminick 68c4255a51 updates proper error handling for razor script macros 2013-03-11 21:49:04 +06:00
Shannon Deminick d07212c89b Fixed changes with new MacroErrors config and how macros are rendered so it supports all macro types and also fixes up a bit of code
in the umbraco.macro class.
2013-03-11 21:06:02 +06:00
Shannon Deminick 28c55320a1 Updates the pull request for handling macro errors.
Backports fixes for partial view macros from 6.x - U4-1488, U4-1844, U4-1730, U4-1843
2013-03-11 20:11:11 +06:00
Shannon Deminick fd58017e97 imported patches for pull request spudstuff/u4497 2013-03-11 18:49:45 +06:00
Casey Neehouse 09408b898e Merge 2013-03-08 19:38:33 +05:00
Morten Christensen d1b05332c5 Manually adds fix for U4-1869 from 6.0.3 branch 2013-03-07 20:28:13 -01:00
Casey Neehouse caad0afed8 Corrects u4-1870 - Refactor Load Content SQL to check if ID is in published list
versus using a join that can cause duplicate entries.
2013-03-07 21:00:31 +05:00
Shannon Deminick 62d365573f Back ports fixes for: #U4-1614, #U4-793 - preview working properly in mvc 2013-03-06 03:17:18 +06:00
Shannon Deminick f3b7a8a581 Fixes: #U4-1471 - issue with having NewRelic installed and some sort of conflict with shutting down
our logger.
2013-03-05 23:49:45 +06:00
Shannon Deminick a765f36d24 Adds unit tests for DynamicNode and DynamicPublishedContent, fixes both when querying for recursive properties.
Fixes: #U4-1839
2013-03-05 21:00:16 +06:00
Shannon Deminick 046da1a8ce Fixes: #U4-1824 - issue with razor dynamic node property access performance enhancements. 2013-03-05 07:06:41 +06:00
Shannon Deminick ca7abd6c78 Merge 2013-03-05 06:08:59 +06:00
Shannon Deminick 7cc0f2a514 Fixes: #U4-1819 2013-03-05 05:56:53 +06:00
Shannon Deminick 4882df43bd Back merged from 6.1 the changes required for #U4-1822 and #U4-1797 2013-03-02 01:50:53 +06:00
Sebastiaan Janssen ee2943b9fb Created branch 4.11.6 2013-03-01 06:56:34 -01:00
Sebastiaan Janssen c250fa560e Restrict the NuGet .Core dependency to the same version. 2013-02-28 15:08:30 -01:00
Sebastiaan Janssen b017e8690a Fix errors in log caused by no prevalues beind selected. 2013-02-28 09:53:57 -01:00
Shannon Deminick 8a9680e75c updated unit test logic 2013-02-27 23:13:48 +06:00
Shannon Deminick 36c66e676a Fixed unit tests 2013-02-27 22:35:27 +06:00
Sebastiaan Janssen ba530061a0 Merge 2013-02-27 13:53:14 -01:00
Sebastiaan Janssen 89ae3bc143 Add RevertToCleanInstall.bat to 4.11.5 too, it's handy. 2013-02-27 13:51:58 -01:00
Shannon Deminick 3951f59d09 Merge 2013-02-27 20:46:06 +06:00
Shannon Deminick cd8c998ebf Fixes: U4-1788 - ensures internal reserved paths and urls (that cannot be modified) are stored staticly in code,
Also fixes that the _reservedPathsCache and _reservedUrlsCache actually works, before we were doing an
object.ReferenceEquals comparison which would never have worked and it was also not thread safe.
2013-02-27 20:42:11 +06:00
Sebastiaan Janssen 2cb544591b Pull in new translations 2013-02-27 12:43:21 -01:00
Stephan 1b1b5c047c U4-1779 - Web.BaseRest supports rest extensions over multiple classes 2013-02-26 16:52:06 -01:00
Sebastiaan Janssen fa5b9e5689 Typo: U4-512 "Memebertype saved" 2013-02-26 17:29:53 -01:00
Sebastiaan Janssen c26df8da6f U4-591 Access bug in dashboard 2013-02-26 15:48:22 -01:00
Shannon Deminick 1e02d85fca Fixes: #U4-1773 (backport fix from 6.0.1) 2013-02-26 21:35:09 +06:00
Shannon Deminick d1dc2331f8 Merge 2013-02-26 21:15:31 +06:00
Shannon Deminick d503deb8c5 reverted member index config, for pre 6.1 we will still need to manually set the member fields. 2013-02-26 21:07:59 +06:00
Morten Christensen 0859b92aaf Fixes U4-1781 so Saved is called when saving a DataTypeDefinition in the backoffice 2013-02-26 13:59:08 -01:00
Sebastiaan Janssen 695d26434c U4-600 Wrong membersearch.png path in MemberSearch.ascx 2013-02-26 09:48:14 -01:00
Shannon Deminick a19de645e4 Merge 2013-02-26 00:59:06 +06:00
Shannon Deminick de9a27db10 Updates to latest Examine lib (another bug fixed) 2013-02-26 00:45:42 +06:00
Sebastiaan Janssen b6d5b7d603 Fixes U4-1776 SafeAlias culture problem 2013-02-25 13:33:51 -01:00
Sebastiaan Janssen 93d7cf4dc3 Fixes U4-1776 SafeAlias culture problem 2013-02-25 13:28:54 -01:00
Tom Fulton 0c42596dc8 Fixed: U4-1678 Saving a Media should show a SpeechBubble 2013-02-25 08:39:18 -01:00
Sebastiaan Janssen 8cf9c1ba97 Fixes: U4-1769 Dictionary Item with "Illigal" character can not be deleted 2013-02-22 14:15:22 -01:00
Shannon Deminick 7a47d63b48 Fixed remaining tests 2013-02-22 19:55:22 +06:00
Sebastiaan Janssen 4648a8c103 Fixes U4-1746 Duplicate image source (src) when inserting resized image in tiny
mce (richtext editor)
2013-02-22 11:41:01 -01:00
Sebastiaan Janssen 87947871d1 Have to add new Examine version to Web.UI as well, else the build output from
build.bat file will not be able to find it.
2013-02-22 09:57:58 -01:00
Sebastiaan Janssen 87fee572ff Enable nuget package restore for teamcity, upgrade examine dll 2013-02-22 09:47:23 -01:00
Shannon Deminick 89f7a3ec63 Clearly these files shouldn't be deleted :P 2013-02-22 06:23:03 +06:00
Shannon Deminick 7092a9ccbb Reverted the macro engines and web proj's, it would seem as though 4.x on the build server hasn't
been configured for nuget package restor (or something like that)
2013-02-22 06:05:10 +06:00
Shannon Deminick e9ea9b5e1b Updates DynamicNode with some performance enhancements especially around things like HasProperty and GetProperty.
Also when it returned children, it was actually re-iterating over all children (going to the repo to find them even though
they were already resolved).
2013-02-22 05:44:17 +06:00
Shannon Deminick fd1efb29ec Fixes issue when saving settings to web.config, not sure how this error never came up before. Was missing a "\" between the path and "web.config".
Using Path.Combine is much safer than just string.Concat!
2013-02-22 04:45:20 +06:00
Shannon Deminick cf4781153e Fixes: #U4-873, #U4-888 - fixes media sorting in razor + MVC. Updates Nunit libs and Examine lib. Adds unit tests to
support new sorting fixes. Fixes up a few other issues with the legacy ExamineBackedMedia class, it will now handle all data
stored in Examine. Simplifies the Examine internal index sets to include all data.
2013-02-22 04:12:24 +06:00
Shannon Deminick ebed142cd5 Another fix for file sys test 2013-02-21 23:47:16 +06:00
Shannon Deminick d162aba14a Fix for file system test 2013-02-21 23:07:37 +06:00
Shannon Deminick ec075f5807 Merge 2013-02-21 22:38:38 +06:00
Sebastiaan Janssen dca90e6316 Merge 2013-02-21 15:09:20 -01:00
Sebastiaan Janssen df31fafec5 Update en_us umbracoembed file, had the wrong content 2013-02-21 15:06:37 -01:00
Shannon Deminick 828dc64035 Backports fix for FullpathToRoot in GlobalSettings... not sure how some unit tests have been working this whole time.
Changes UseLegacySchema default value to false... was set to true!?
un-ignores LookupByNiceUrl tests and still ensures it doesn't require a database to test by passing in an optional parameter
to LookupByNiceUrl to specify if we want to include domain lookups or not (default is true)
2013-02-21 22:02:56 +06:00
Shannon Deminick 0b74164a8e New base test class for anything relating to published content/media, un-ignores strongly typed tests. 2013-02-21 21:01:00 +06:00
Shannon Deminick 62be1b1267 un-ignores Can_Get_File_Dates in AbstractFileSystemTests... not sure why it was ignored seems to work properly. 2013-02-21 20:42:49 +06:00
Sebastiaan Janssen 85ae7e764f Merge 2013-02-21 08:52:48 -01:00
Sebastiaan Janssen 3daa624627 Fixes U4-1668 4.11.4 NiceUrl property on dynamicnode does not work until a
property has been requested from the dynamic node
2013-02-21 08:52:23 -01:00
Shannon Deminick d8af1aaf7b Changed logging in unit tests to filter out things we don't need to see 2013-02-21 03:13:16 +06:00
Shannon Deminick f2d105d8b9 Fixed #U4-814 and got all possible unit tests that were not working for DynamicNode but were working for
DynamicPublishedContent working. And fixed up the DynamicPublishedContent unit tests as these weren't working at all...
but seemed to say they did on the build server. strange.
2013-02-21 05:44:44 +06:00
Stephan 5b0a8c0668 Tests - fix build broken by back-porting 6.x code 2013-02-20 10:12:41 -01:00
Stephan c3ccf3a609 Tests - cleanup settings handling for more reliable tests 2013-02-19 18:01:52 -01:00
Stephan 60bbede408 U4-1441 - fix, fix and fix! 2013-02-19 17:49:49 -01:00
Stephan 1d0299af89 U4-1611 - bugfix 2013-02-19 13:58:16 -01:00
Shannon Deminick c2d0e255df Fixes: #U4-1537 2013-02-19 20:17:17 +06:00
Shannon Deminick 005d3e7d64 Removes area routing for local surface controllers and BeginUmbracoForm, adds strongly typed Html.Action<T>
method for rendering SurfaceController child actions regardless of area (so you don't have to specify).
All relates to #U4-1727
2013-02-19 06:19:26 +06:00
Shannon Deminick 12f8638223 Fixes: #U4-1727 2013-02-19 06:18:51 +06:00
Shannon Deminick e3f9e8c842 Fixes: #U4-552 2013-02-19 03:42:19 +06:00
Shannon Deminick a475f72d50 Fixes: #U4-1695 2013-02-19 02:25:57 +06:00
Shannon Deminick a559ef9f90 Fixes: #U4-1732 2013-02-19 00:59:21 +06:00
Sebastiaan Janssen be83302b14 Fixes U4-1451 2013-02-18 13:22:12 -01:00
Sebastiaan Janssen 83d7ea9ef1 Ignoring wrong unit test for now 2013-02-18 12:53:15 -01:00
Sebastiaan Janssen 95024442de Copy the umbracoSettings for PublishMediaStoreTests as well 2013-02-18 12:22:53 -01:00
Sebastiaan Janssen 69f54b5f22 Copy the umbracoSettings for LibraryTests as well 2013-02-18 11:57:58 -01:00
Sebastiaan Janssen 3404f95b2e Forgot one trailing slash in previous commit 2013-02-18 11:42:45 -01:00
Sebastiaan Janssen e56738481b Adding trailing slash to failing routing tests.
The issue with these tests might again be because of the UmbracoSettings file, which has the trailing slash setting. But with the settings being reset after teardown the tests were still failing, so made these minor corrections which shoudl correspond to the default setting.
2013-02-18 11:38:07 -01:00
Sebastiaan Janssen cb59dc353b Update version to 4.11.5 2013-02-18 10:31:43 -01:00
Sebastiaan Janssen d1b75eac08 Update wrong config path in unit tests 2013-02-18 10:31:17 -01:00
Sebastiaan Janssen 8fabd4e4ed Merge 2013-02-15 12:05:46 -01:00
Sebastiaan Janssen 564d92bed7 Possible fix for TeamCity 2013-02-15 12:05:25 -01:00
Shannon Deminick 95f103ccc2 Merge 2013-02-15 18:55:50 +06:00
Stephan 0ace2fdae7 U4-1611 - fix xpath special chars escaping issues in published content store 2013-02-14 16:31:45 -01:00
Stephan 5da3541584 U4-1441 - bugfix 2013-02-14 16:27:27 -01:00
Shannon Deminick ef86d2f1f1 Manually applies patch for #U4-1718 2013-02-14 23:26:29 +06:00
Sebastiaan Janssen a10a6d1af8 Need to wrap the login javascript in a placeholder for Concorde 2013-02-14 09:06:15 -01:00
Stephan 6d87174cc1 U4-1441 - improve logging 2013-02-08 07:54:16 -01:00
Stephan 9af9c3fe77 U4-1441 - change trySkipIisCustomError config key 2013-02-08 07:36:35 -01:00
Stephan 9cedf5da4c U4-1441 - make trySkipIisCustomError value a setting 2013-02-08 08:08:36 -01:00
Shannon Deminick 906d675dca Merge 2013-02-07 02:09:32 +06:00
Shannon Deminick f1b3105202 Patch for #U4-1653 - media library cache refresh issue 2013-02-06 20:56:47 +06:00
Shannon Deminick 3ebb213916 Patches installer issue. 2013-02-06 19:18:42 +06:00
Stephan a65ca205de U4-1441 - fix issue with IIS taking over custom errors 2013-02-05 16:29:10 -01:00
Stephan 3e1120612b Update version number 2013-02-04 12:00:58 -01:00
Stephan 8d06d39a62 Create branch for 4.11.5 2013-02-04 11:59:30 -01:00
Stephan da7fea47c6 U4-1441 - refactor (fix) legacy NotFoundHandler support 2013-02-03 14:34:04 -01:00
Shannon Deminick f2442b25f6 Close 4.11.4 branch 2013-02-01 19:25:12 +06:00
Sebastiaan Janssen 300d3ff09b Added tag Release-4.11.4 for changeset e02f5aebb87e 2013-02-01 08:41:26 -01:00
Sebastiaan Janssen e6337b8f14 Properly reference uGoLive MyGet package 2013-02-01 08:38:13 -01:00
Sebastiaan Janssen 2be785ace3 Merge 2013-02-01 08:16:18 -01:00
Sebastiaan Janssen 5e2d991fab Update uGoLive 2013-02-01 08:16:10 -01:00
Morten Christensen 536cb4caf1 Fixes U4-1571 2013-02-01 07:42:51 -01:00
Morten Christensen 27745ea141 Fixes U4-1483 2013-02-01 07:35:48 -01:00
Sebastiaan Janssen 5289c55740 Translation updates 2013-02-01 07:24:21 -01:00
Sebastiaan Janssen 791773fc8a Add some more translations 2013-02-01 07:23:33 -01:00
Shannon Deminick 1da27e6c2b Removes all upgrade script stuff since we've deployed the fix in a package. 2013-02-01 06:42:42 +06:00
Shannon Deminick a909b7904e Fixes uGoLive ascx 2013-02-01 05:29:54 +06:00
Shannon Deminick 1b1abce7da Merge 2013-01-31 04:48:29 +06:00
Shannon Deminick fbc10be381 Reverted logic of Document to be what it used to be... Published and HasPublishedVersion() are the same and will
return the same thing, though we've kept the lazy loading and optimizations.
2013-01-31 04:46:51 +06:00
Shannon Deminick 61f2647b62 missing file 2013-01-31 04:26:47 +06:00
Shannon Deminick a5bea7fc59 Added the ability to automate any c# scripts for an upgrade process. I realize this is superceded already in 6.0
but we need a way to do this in 4.x too especially for this release since we need to run a script to fix some db
issues. I've added a framework using an UpgradeScriptManager and another install step + unit tests for some of the
UpgradeScriptManager methods.
2013-01-31 04:26:37 +06:00
Sebastiaan Janssen b9be5c2561 Also implement optimization in fdfa687e6f41 to v4: no need to try and republish
the child pages if the page you are trying to publish was already published
2013-01-30 15:01:38 -01:00
Shannon Deminick 97556de447 Changed methods created yesterday to internal so we can port to 6+ nicely. 2013-01-30 18:58:42 +06:00
netaddicts d5bde0d8df Makes sure preview is not using cached versions of any macro 2013-01-24 11:00:15 -01:00
Sebastiaan Janssen cc5ca0b5fe Fixing U4-359 Previewing new nested pages doesn't work 2013-01-30 09:21:43 -01:00
Shannon Deminick 0cb9cc6840 just cleaned up some code formatting. 2013-01-30 07:59:15 +06:00
Shannon Deminick d38d7b1ff4 Updates all code calling UnPublishSingleNode & UpdateDocumentCache to pass in the already existing Document object if there is one
instead of the ID... this'll save a another ton of SQL calls.
2013-01-30 07:59:03 +06:00
Shannon Deminick 2d87f933d5 Updates Document's Published property to return true if the document is 100% published (viewable on the front-end)
Reverts Document's HasPublishedVersion() to return true if the document has any published version (may or may not be viewable on the front-end)
Updates the Document's new UpdatePublishedOnDescendants to set both the Published and PathPublished fields.
Reverts some stuff in the editContent to use HasPublishedContent() to set the _documentHasPublishedVersion field.
Reverts the BaseContentTree to use the Published property now that it returns the correct value.
Updates the editContent method to use the UpdateDocumentCache overload accepting an object so there's not another N+1 SQL call made.
2013-01-30 07:57:31 +06:00
Shannon Deminick a734a0cff7 Fixes unit tests for Umbraco_Route_User_Defined_Controller_Action 2013-01-30 05:37:32 +06:00
Shannon Deminick d0ace55d03 Fixes: #U4-1593 - Content tree doesn't check for correct publish state. 2013-01-30 05:04:31 +06:00
Shannon Deminick 3fda0308ac Fixes: #U4-1594 - SQL for SqlOptimizedSingle not correct for published state
Fixes: #U4-1596 - new GetPathPublishedDescendants method on Document for optimizations
Fixes: #U4-1595 - Obsoletes HasPublishedVersion() method and ensures lazy loading of Published property,
as well as ensuring that the backing property is set correctly on first load (optmization)
Fixes: #U4-1597 - PathPublished property should be set in an optimized way and/or lazy loaded if it cannot be
2013-01-30 04:56:28 +06:00
Shannon Deminick d796b2afc1 Fixes: #U4-1170 - template with hyphen or dash 2013-01-29 21:19:16 +06:00
Shannon Deminick f95cfc2ee0 Changes v4.x config transforms 2013-01-29 21:18:17 +06:00
Shannon Deminick c5d1439422 Fixes: #U4-1458 - due to a null check on PublishedContentRequest on UmbracoContext 2013-01-29 08:35:09 +06:00
Shannon Deminick 5e9f4559b6 Fixes: #U4-1536 2013-01-29 07:49:14 +06:00
Shannon Deminick 4bbb0441a6 Merge 2013-01-29 05:50:50 +06:00
Shannon Deminick 4cf1d7d9a4 Fixes: #U4-1577 - HasPublishedVersion checks for trashed 2013-01-29 05:48:18 +06:00
Shannon Deminick a6a3ddca75 Fixes: #U4-1580 - m_SQLOptimizedMany includes the 'trashed' flag which can be used by business logic. 2013-01-29 05:37:14 +06:00
Shannon Deminick 27cfa85d3a Fixes: #U4-1579 - moving a node doesn't update the descendants of that node's level or path. 2013-01-29 04:39:44 +06:00
Shannon Deminick a9e1e7b634 Updating: #U4-1491 - Updated HasPublishedVersion() to ensure it checks for 'newest' 2013-01-29 03:42:58 +06:00
leekelleher 9f5f920c81 MNTP: Corrected a typo in the example XPath (additional apostrophe) 2013-01-28 17:18:20 +00:00
Shannon Deminick f9a0d91299 Fixes: #U4-1527 - Creates a public property on UmbracoHelper to return the currently assigned IPublishedContent of the UmbracoHelper. 2013-01-25 06:04:10 +03:00
Shannon Deminick 82c2560822 Ensures all resolvers are sealed. Changes CacheRefreshersResolver, DataTypesResolver, MacroFieldEditorsResolver, PackageActionsResolver, ActionsResolver
to all be lazy resolvers as they are not needed instantly on app startup (not needed by the front-end) This will
make app startup a lot quicker. Fixes ActionsResolver to not use the PluginManager to resolve the types when it
is instantiating them since these are passed in the ctor. Updates all unit tests to use lazy delegate for these resolvers
and they are all passing.
2013-01-23 18:40:40 +03:00
Shannon Deminick f467b8cb6c Adds more functionality for LazyManyObjectsResolverBase - adding type list delegates for lazy resolution. 2013-01-23 17:39:07 +03:00
Shannon Deminick aea1a03453 Updates ManyObjectsResolverBase to properly check for resolution freezing and fixes a few issues found regarding
inheritance in complex situations like the new LazyManyObjectsResolverBase.
Creates the new LazyManyObjectsResolverBase to lazily resolve types in order to create them. This is for
work item : #U4-1522
Adds unit test to support.
2013-01-23 07:45:00 +03:00
Shannon Deminick 1568e5f19c updated comments. 2013-01-23 01:44:01 +03:00
Shannon Deminick 8dff47db78 Merge 2013-01-23 01:39:45 +03:00
Shannon Deminick 987e48733a Merge 2013-01-23 01:39:25 +03:00
pcw@pcw-PC.shout.local ac5142443a Fixed EncryptWithMachineKey to handle values longer than FormsAuthentication.Encrypt max length limit
http://issues.umbraco.org/issue/U4-1455
2013-01-15 20:40:28 +00:00
pcw@pcw-PC.shout.local 44360d83aa Fixed EncryptWithMachineKey to handle values longer than FormsAuthentication.Encrypt max length limit
http://issues.umbraco.org/issue/U4-1455
2013-01-15 20:20:05 +00:00
pcw@pcw-PC.shout.local 021cb817d4 Fixed EncryptWithMachineKey to handle values longer than FormsAuthentication.Encrypt max length limit
http://issues.umbraco.org/issue/U4-1455
2013-01-15 20:17:12 +00:00
pcw@pcw-PC.shout.local f4f91fba78 Fixed EncryptWithMachineKey to handle values longer than FormsAuthentication.Encrypt max length limit
http://issues.umbraco.org/issue/U4-1455
2013-01-15 20:09:29 +00:00
pcw@pcw-PC.shout.local dec5e8ad6c Fixed EncryptWithMachineKey to handle values longer than FormsAuthentication.Encrypt max length limit
http://issues.umbraco.org/issue/U4-1455
2013-01-15 20:07:07 +00:00
Sebastiaan Janssen a6b2196c10 Make sure the filename gets set correctly if we're building the release locally 2013-01-15 16:18:24 -01:00
Max Rotvel 4321c8d24e Fix part of U4-1355 by making umbracoembed translatable and supply da lang files 2013-01-15 14:33:25 -01:00
NielsHartvig@UMBRACORATI.localdomain 4cff3a3c28 Fixed U4-1439 4.11.2 DataEditorSetting not working for UserControl wrapper. 2013-01-15 13:18:37 -01:00
Shannon Deminick 5458c9a310 Adds Encryption/Decryption string extension methods that work in medium trust, with unit tests. 2013-01-15 01:35:10 +03:00
Shannon Deminick 0045ec353f Apply patch for #U4-1156 - IFileSystem public changes. 2013-01-15 01:27:44 +03:00
Shannon Deminick 716d3e95f1 Imported patches from 6.0 for #U4-1453, #U4-1454 2013-01-15 00:58:11 +03:00
Shannon Deminick beeb28f390 Fixes #U4-1467 2013-01-15 00:23:40 +03:00
Sebastiaan Janssen 080e8816a5 Remove non-existing files from project.. 2013-01-14 17:01:32 -01:00
Sebastiaan Janssen f7eb323bd5 Updated razor templates 2013-01-14 14:04:33 -01:00
Sebastiaan Janssen 0f484fdf49 Improve build so that you can't forget to set the version number, the version in
GlobalSettings.cs will be updated with the version configured in build.bat
2013-01-14 10:55:59 -01:00
Sebastiaan Janssen d779422bf4 U4-1457 Missing File for "English (US)" Language Option 2013-01-14 09:08:23 -01:00
Stephan 11ea698969 U4-1017 - more explicit error message on internal cache errors 2013-01-12 10:40:42 -01:00
Shannon Deminick 0e0e6b5c41 Fixes: #U4-1451 2013-01-13 23:24:02 +03:00
Sebastiaan Janssen 4c218621c6 Fixes: #U4-1405 - Added DynamicXmlConverter's 2013-01-14 08:57:49 -01:00
Sebastiaan Janssen c150a91e50 Update uGoLive & Fixes U4-1447 uGolive result: Unable to find node
/configuration/system.web/compilation/@debug in config file web.config
2013-01-14 08:43:50 -01:00
Sebastiaan Janssen 7be9a0a987 Update version to 4.11.4 2013-01-14 08:42:54 -01:00
Sebastiaan Janssen 50589c0911 Removed tag Release-4.11.3.1 2013-01-12 17:30:08 -01:00
Sebastiaan Janssen e61ae618e8 Added tag Release-4.11.3.1 for changeset e4d0c7e74055 2013-01-12 17:30:05 -01:00
Sebastiaan Janssen 930e6a0989 Forgot some parenthesis .. 2013-01-12 17:29:48 -01:00
Sebastiaan Janssen 7c50b32684 Merge with 4.11.3 2013-01-12 17:06:10 -01:00
Sebastiaan Janssen 0f7daf7ebd Closing branch 4.11.3 2013-01-12 17:05:45 -01:00
Sebastiaan Janssen 12cbc2a9c5 Added tag Release-4.11.3 for changeset baa44b79cf90 2013-01-12 17:04:25 -01:00
Sebastiaan Janssen 959d263619 Update the build files to build more automatically (like v6) 2013-01-12 17:02:52 -01:00
Sebastiaan Janssen 6a1fb52b25 Fixes U4-1442 This must be a bug. 4.11.2.2 can't create Macro. 2013-01-12 14:41:21 -01:00
Sebastiaan Janssen 18cd043421 Open branch for 4.11.3 and updated version number 2013-01-12 14:24:27 -01:00
Sebastiaan Janssen ddb2f82aba Added tag Release-4.11.2.2 for changeset 54cde33b809d 2013-01-11 12:31:27 -01:00
Sebastiaan Janssen 6c99e7951f Forgot to update the version for 4.11.2.1 - oops.. Updating again! 2013-01-11 12:25:23 -01:00
Sebastiaan Janssen e44e745761 Merge with 4.11.2 2013-01-11 09:35:46 -01:00
Sebastiaan Janssen 30c11439e4 Re-closing branch 4.11.2 2013-01-11 09:34:55 -01:00
Sebastiaan Janssen 0883f621f6 Update NuGet and making automation better for the dummy files 2013-01-11 09:24:47 -01:00
Sebastiaan Janssen 2d0784d1e5 Added tag Release-4.11.2.1 for changeset 77db220b89e1 2013-01-11 08:31:58 -01:00
Sebastiaan Janssen af0011f32a Fixes U4-1432 4.11.2 - Tinymce strips 'src' attribute from images 2013-01-11 08:23:31 -01:00
Sebastiaan Janssen ab6c5ac21a Added tag Release-4.11.2 for changeset 73711b806a40 2013-01-10 11:05:52 -01:00
Sebastiaan Janssen 227a38fb98 Removed tag 4.11.2 2013-01-10 11:05:43 -01:00
Sebastiaan Janssen 06f9dee649 Added tag 4.11.2 for changeset 73711b806a40 2013-01-10 11:05:34 -01:00
Sebastiaan Janssen 75680192bb Merge 4.11.2 into default 2013-01-10 11:05:13 -01:00
Sebastiaan Janssen a53efb394f Closing 4.11.2 branch 2013-01-10 10:54:56 -01:00
Sebastiaan Janssen 98ed32c8cf Include the new translation files in the project so they get in the build too 2013-01-10 09:55:35 -01:00
Sebastiaan Janssen df10ebebca Get latest translations in 2013-01-10 08:21:27 -01:00
Sebastiaan Janssen 88dc73cd66 Fix the unpublished/pendinchanges/published display 2013-01-10 07:29:04 -01:00
Sebastiaan Janssen cd0919aeeb Update version to 4.11.2 2013-01-09 16:03:56 -01:00
Sebastiaan Janssen ce6711b587 Duplicate fix (ce2f47c11322) #U4-1366 - conflict with partial view macro engine. 2013-01-09 13:58:55 -01:00
Stephan 6cb3fcf9ad U4-1411 - fix post-4.9 regression in NotFoundHandler url 2013-01-08 16:41:31 -01:00
Sebastiaan Janssen e5878554bd Fixes U4-1482 Regression - RTE unable to edit hyperlink on image 2013-01-21 14:21:29 -01:00
Sebastiaan Janssen 44c8c4b5b8 Revert 024896ba7bcf as it's a breaking change 2013-01-18 08:47:38 -01:00
Shannon Deminick c0b5525dd7 Removed 'Boot' method from WebBootManager as it was never supposed to be there in the first place.
Removed test code from 'SurfaceController'.
Added comments to IApplicationEventHandler.
2013-01-18 02:31:51 +03:00
Sebastiaan Janssen 36f8a8e1dd Fixed U4-1492 Insert image in RTE gives null reference error 2013-01-17 14:17:04 -01:00
Sebastiaan Janssen 16f73b56ab Weird failing test for getting the date of a file, works only 10% of the time.. 2013-01-17 09:53:47 -01:00
Sebastiaan Janssen 47dc2e6214 Merge 2013-01-17 09:18:12 -01:00
Sebastiaan Janssen c6483f0380 Revert e4bb9041cf54 as it was a breaking change 2013-01-17 09:16:45 -01:00
NielsHartvig@UMBRACORATI.localdomain 168b38b2a3 Update to U4-1485 for 4.11.4 2013-01-17 08:47:42 -01:00
NielsHartvig@UMBRACORATI.localdomain 70ca4ac913 Fixes U4-1485 Booting.aspx has potential Open Redirect flaw 2013-01-17 08:38:09 -01:00
Sebastiaan Janssen 72099192b5 My bad, teamcity wasn't building the test project before running tests :) 2013-01-16 17:01:00 -01:00
Sebastiaan Janssen ea48128869 The nunit console runner is being such a tease, ignoring the [Ignore] attribute 2013-01-16 16:44:50 -01:00
Sebastiaan Janssen f0b22146c8 Ignore tests that have been failing for AGES 2013-01-16 16:31:15 -01:00
Sebastiaan Janssen fe0d94687a Use the original workaround for now 2013-01-16 16:25:54 -01:00
Sebastiaan Janssen 238c3d38e8 Un-ignore .exe files 2013-01-16 15:37:31 -01:00
Sebastiaan Janssen 6af4f1f2c6 Corrected the path for the tools folder 2013-01-16 15:21:43 -01:00
Sebastiaan Janssen e215fb056f Work around for TeamCity NUnit test runner see:
http://umbraco.com/follow-us/blog-archive/2013/1/16/make-teamcity-respect-failing-nunit-tests-and-stop-the-build.aspx
2013-01-16 15:19:45 -01:00
Sebastiaan Janssen e6178efcfb Duplicating fix for U4-483 so that this also fixes U4-1391 in the 4.11.x branch 2013-01-07 08:12:53 -01:00
Sebastiaan Janssen 30cf0e2040 Add some logging to PhysicalFileSystem 2012-12-26 06:49:54 -01:00
Sebastiaan Janssen 48d620cdb0 Cleanup RTE ImageHelper a little bit, still bad code but more readable now 2012-12-26 06:27:30 -01:00
Sebastiaan Janssen 3bd487d092 Fixed #U4-1323 Stripping umbraco path out of source is not needed any more 2012-12-26 05:54:34 -01:00
Sebastiaan Janssen 6c8c37256b Cleanup media uploader in RTE a little 2012-12-26 05:50:48 -01:00
Sebastiaan Janssen 37b1fcbaf0 Fix image uploader in RTE, when used in VDir it returns the right path now
no need for relative path hacks
2012-12-26 05:49:03 -01:00
Sebastiaan Janssen dc111768e3 Slight MediaFactory refactors, mostly to fix issue U4-1344 where files wouldn't
upload if the "magic" umbraco props don't exist (witdth, height, bytes)
2012-12-23 11:46:04 -01:00
leekelleher 6589d5d5d3 MNTP: Fixed an long-time CSS bug. Aligned the header with the right-panel. 2012-12-21 15:58:02 +00:00
Sebastiaan Janssen e6975a71d5 Additional fix for U4-1312 Cant publish child node, because parent not published
When you unpublish a node which it's descendants also get unpublished, but as
soon as you publish the parent node again, they don't end up in the XML cache
any more, leading to this error again. Now putting all previously published
documents back into the XML cache when the parent gets published
2012-12-20 14:05:28 -01:00
Sebastiaan Janssen 33b497e5f4 Additional fix for U4-1341 - nodes should appear dimmed when unpublished, but
they appeared as changed (and not dimmed, therefore looked published)
2012-12-20 13:42:30 -01:00
Sebastiaan Janssen c5e7c81c19 Notification and tree refresh when unpublishing content 2012-12-20 09:25:50 -01:00
Sebastiaan Janssen 47d1fe7082 Fixed U4-703 - Updating or re-installing package causes duplicate trees 2012-12-19 09:05:23 -01:00
Sebastiaan Janssen 735bd574ff Didn't mean to commit test code, sorry! 2012-12-17 12:29:43 -01:00
Sebastiaan Janssen 5c0d9785e0 Don't check log comment length if it is null.. helped with a broken recycle bin
not deleting content because sometimes the title of the content would be null
2012-12-17 09:25:55 -01:00
Sebastiaan Janssen db14868324 attributes["macroalias"] would YSOD instead of give back a null 2012-12-14 13:51:01 -01:00
Stephan 06952833ef U4-1212, U4-1312 - fix Document.PathPublished 2012-12-13 15:48:46 -01:00
Shannon Deminick 2a90e93a6f Updated partial view macro engine to support storing the files in the App_Plugins/[packagename]/Views/MacroPartials
so they can be stored with a package and not pollute the main file system.
2012-12-07 07:04:11 +05:00
Shannon Deminick 0d94ddb96e Got macro parameters working with Partial View Macros, changed PartialViewMacroPage to inherit from
UmbracoViewPage<PartialViewMacroModel> so that UmbracoHelper, etc... are available.
2012-12-07 06:31:53 +05:00
Shannon Deminick c7645b55ba Partial View Macros now being rendered, now to implement the remaining parts with things like
parameters, etc...
2012-12-04 22:06:55 +05:00
Shannon Deminick 208806c027 Updated more partial view macro engine and its rendering... nearly there. 2012-12-04 11:31:03 +05:00
Shannon Deminick 8024610364 Fixes up some logging API issues. Fixed up tracing in the macro class. Added support for Partial View macro rendering in the macro class. 2012-12-04 11:08:02 +05:00
Shannon Deminick 8e4644568b Updated loghelper to be able to Warn and also trace Warn with an exception. Updated the macro control to check for the
Partial View Macro, added Partial View macro to the enum.
2012-12-04 05:58:24 +05:00
Shannon Deminick e0a71830fa Updated macro editor to support Partial view macros. Improves the JS in the editor (no more c# based js) which auto clears
other fields and drop downs when other files are selected.
2012-12-04 05:42:15 +05:00
Shannon Deminick 5b0057c258 Added missing files. 2012-12-04 03:29:02 +05:00
Shannon Deminick fb61c55fa7 Started on PartialViewMacros 2012-12-04 03:26:04 +05:00
Stephan a70ef52964 fix xpath syntax error with legacy XML schema 2012-11-30 13:33:24 -01:00
Stephan 51204ee401 U4-1212 - bugfix Document.PathPublished 2012-12-11 17:37:33 -01:00
Sebastiaan Janssen 657f165ffb Created branch 4.11.2 2012-12-17 12:22:11 -01:00
Casey Neehouse 3bd98d851a Reverting the config files that inadvertently got committed. 2012-11-29 21:42:37 +05:00
Casey Neehouse 9eea46b19b Modification of UserControl usage to allow for Virtual Path to be used correctly. 2012-11-29 21:27:42 +05:00
Sebastiaan Janssen 76fb5d260f Moved tag Release-4.11.1 to changeset 6eb5f2fb5a88 (from changeset 7f827760cb49) 2012-11-28 13:35:30 -01:00
Sebastiaan Janssen 267cd46ea0 Another additional fix to make the reloading of trees work after package install 2012-11-28 13:34:35 -01:00
Sebastiaan Janssen 96f6a0161f Merge with 4.11.1 2012-11-28 13:08:13 -01:00
Sebastiaan Janssen 7bc53adc67 Closing 4.11.1 branch 2012-11-28 13:06:01 -01:00
Sebastiaan Janssen 8ecff73c18 Added tag Release-4.11.1 for changeset 7f827760cb49 2012-11-28 13:05:21 -01:00
Stephan 35e65ad18c add support for "/foo" hostnames ONLY for backward compat.
fix invalid hostname message
2012-11-28 12:43:19 -01:00
Sebastiaan Janssen 8def8eaa86 Bumping the version to 4.11.1 2012-11-28 09:44:03 -01:00
Sebastiaan Janssen c0774ad9b9 Merge 2012-11-28 09:24:54 -01:00
Sebastiaan Janssen f306cbe457 Move invalidDomain entry to the correct area. 2012-11-28 09:24:40 -01:00
Sebastiaan Janssen 577b989c4c Aha, string needs to start all the way to the left to appear nicely in the editor 2012-11-28 08:41:54 -01:00
Sebastiaan Janssen e6b162f4f6 Add translation for invalid hostname 2012-11-28 08:37:08 -01:00
Stephan b40cc1879f missing entry in language file 2012-11-28 07:36:08 -01:00
Shannon Deminick 8a7c7bf77d Merge 2012-11-27 21:47:20 +05:00
Shannon Deminick 38a1179de5 applied patch from rev 189f37a1dd63 which reverts the last minute changes before 4.11
release, namely changes to the ApplicationTreeRegistrar, TreeDefinitionCollection, theend installer step.
2012-11-27 21:45:57 +05:00
Sebastiaan Janssen f263b4d92b Fixes U4-1162 - In MVC mode, creating a child template doesn't set the layout
correctly (it's missing the .cshtml extension)
2012-11-27 15:36:54 -01:00
Sebastiaan Janssen c612727116 Add translations that got lost in merge, fixes U4-1254 2012-11-27 14:07:13 -01:00
Sebastiaan Janssen ab9c9df7d6 Reverting last minute hacks around the pluginmanager and adding Shannon's fixes
from changeset 85f9e5879e60
2012-11-27 13:27:33 -01:00
Stephan c607e50433 U4-1245, U4-1186... fix the mess I created with hostnames 2012-11-27 12:43:57 -01:00
Stephan df5555bdf1 Opened branch 4.11.1 2012-11-27 12:40:42 -01:00
Sebastiaan Janssen 9506339e6f Merge with 4.11.0 2012-11-23 13:37:17 -01:00
Sebastiaan Janssen 68605a7560 Closed branch 4.11.0 2012-11-23 13:36:14 -01:00
Sebastiaan Janssen 839dd7315a Added tag Release-4.11.0 for changeset 20e4dff821d8 2012-11-23 13:33:15 -01:00
Sebastiaan Janssen f1314628d7 One last hack to get the the macroengines to show up after install. 2012-11-23 12:01:43 -01:00
Sebastiaan Janssen e23ed30b0c Took out the temporary tree fixes and put another temp fix in (reverts to the 4.10.x code)
Also removed dependency on ClientDependency.Mvc for now to make upgrades easier (no requirement to do assembly redirects in web.config)
2012-11-23 11:45:51 -01:00
PerPloug 55cb46927e Changes to template and masterpages helper 2012-11-23 09:37:35 -01:00
Sebastiaan Janssen 654c3b7403 Another temporary fix for trees being unavailable after install, the context is null during upgrades in the installer, so would cause a YSOD 2012-11-23 08:02:23 -01:00
Sebastiaan Janssen 4195754b0c Pull in new translations before release 2012-11-23 07:36:58 -01:00
Sebastiaan Janssen 96a6f17bd7 Update for the WebPI build, should now automatically be good
Fixes U4-132
2012-11-22 16:06:06 -01:00
Sebastiaan Janssen 61d99c4061 Of course we also need the assembly redirect for MVC2 -> 3 in the template config to start with (so the build.bat picks it up as well) 2012-11-22 15:45:14 -01:00
Sebastiaan Janssen 0a6e91a2f9 Fixed U4-1235 Changing document type alias YSOD's on SQL CE 2012-11-22 15:04:27 -01:00
jeavonleopold cf9e786e45 U4-1241 Fix - BaseTreePicker GetItemBreadcrumbs causes YSOD for Property Editors that do not store numeric ID's 2012-11-22 15:17:12 +00:00
Sebastiaan Janssen ba1d3fd3e6 Fix Library.Search not giving back an list of DynamicNodes any more, breaking accessibility to custom properties 2012-11-22 13:23:20 -01:00
Sebastiaan Janssen ac01fd48fa Some refactoring of the Umbraco:image implementation after code review 2012-11-22 12:30:58 -01:00
Sebastiaan Janssen f53fb694be Tightened up and renamed the ReadPublished method (relating to pull request for U4-606) 2012-11-22 09:53:11 -01:00
Sebastiaan Janssen 1ecd8fa87d Temporary fix for trees being unavailable after install 2012-11-22 09:34:05 -01:00
Sebastiaan Janssen ce1c9d697b Add assemblyredirect for System.Web.Mvc because ClientDependency.Core.Mvc relies on Mvc v2 while we're using 3. 2012-11-22 09:30:07 -01:00
Sebastiaan Janssen c67a76fb03 json2.js was not included in VS, so not in the build 2012-11-22 08:06:39 -01:00
Shannon Deminick 3d72a4497c Merge 2012-11-22 02:56:53 +05:00
Sebastiaan Janssen 30cc8e0861 Merge 2012-11-21 11:05:38 -01:00
Sebastiaan Janssen 30ca3f6df9 Bump the version to 4.11.0 2012-11-21 11:05:30 -01:00
Stephan cccfed6efe U4-1222 - improve alternate template consistency 2012-11-21 10:12:04 -01:00
Sebastiaan Janssen 82c148e997 Fixed U4-596 with thanks to firepol! 2012-11-21 09:50:47 -01:00
Sebastiaan Janssen c50a3e7a27 I broke the build, oh noes! Sorry. :-) 2012-11-21 09:46:04 -01:00
callicj@M2UA1450WRW.us.maritz.net 811cbe2339 Added new method to the Document Service named readPublished() which returns the published version of the document.
Added new method to the Document class named GetPublishedVersion() which returns the published version of the document.
2012-11-21 08:03:53 -01:00
ksykora@ksykora-Win7 a8bf881ae1 * Fixed an umbraco bug where the macro editor, if it tried to enumerate over a
property whose value was null, would throw a null reference exception instead
 of just ignoring the property.
2012-11-21 07:53:29 -01:00
ksykora@ksykora-Win7 c446be734c Moved ParseMacros from Init into Load in ItemRenderer to fix an issue where the
NodeId property on the Item control was being set after the ItemRenderer had
already loaded it into memory.
2012-11-21 07:54:17 -01:00
Morten Bock f0f7f6af55 Include some missing files 2012-11-21 07:23:15 -01:00
Shannon Deminick 19bd8ae193 Fixes overloads for TypedMedia, TypedContent, Content, Media calls on UmbracoHelper now that
GetPropertyValue returns 'object'
2012-11-21 09:09:37 +05:00
Shannon Deminick 81d8f74e0d Small update to hashcodecombiner and pluginmanager 2012-11-21 08:39:10 +05:00
Shannon Deminick 0011d568c6 Fixes up HashCodeCombiner with correct long field intead of int with correct initialization.
Adds App_Code and global.asax to be monitored for changes to create the hash code.
2012-11-21 08:28:11 +05:00
Shannon Deminick 159718bf4f Updated sln to use Nuget for ClientDependency references, ensures that all config changes
are backward compatible. Have updated the new ClientDependency.config file with the new
features, though these are not required for existing installs but we should advise to merge
the new changes in.
Added ClientDependency.Core.Mvc to the UI project so that it will now ship with this library.
2012-11-21 08:01:23 +05:00
Shannon Deminick b9ff3ca729 updated proj references, was getting warnings in build that they could not be referenced. Might be a VS 2012 thing. 2012-11-20 07:41:12 +05:00
Shannon Deminick 4f3ac36d7f Merge 2012-11-19 19:57:23 +05:00
Shannon Deminick a9257ad366 Fixes #U4-1213, much better support for ignoring routes in route table. Fixes issue with LogHelper. Adds unit tests
for ignoring routes.
2012-11-19 19:56:52 +05:00
Sebastiaan Janssen 2218459877 Correcting the path for the targets file, should work now even if there are spaces in the path 2012-11-19 08:59:23 -01:00
Sebastiaan Janssen 8f5e2946d6 Merge 2012-11-19 08:10:16 -01:00
Sebastiaan Janssen 19c3b251a0 Include the VS targets file so that the build server can find it as well 2012-11-19 08:09:43 -01:00
Shannon Deminick ce4c855f00 Fixes up the resulting casts when invoking extension methods dynamically in our dynamic objects. 2012-11-19 05:47:34 +05:00
Shannon Deminick 48c45447e4 Fixes: #U4-1207, Enhancements to DynamicXml (legacy and new), now implements proper IEnumerable<T> interfaces.
Added DynamicInstanceHelper for any dynamic object that should find matches on methods, properties and
extension methods. Fixed ExtensionMethodFinder to find the Enumerable extensions (was previously set to IEnumerable which would
find nothing).
2012-11-18 10:28:53 +05:00
Shannon Deminick 4683144987 Changed CacheHelper to be public so it can be exposed publicly by the app context. 2012-11-18 03:34:31 +05:00
Shannon Deminick 238a237cb5 Merge 2012-11-18 03:31:15 +05:00
Shannon Deminick cde1ca9f83 updated some logging on content class. 2012-11-18 03:31:02 +05:00
Shannon Deminick 93e2d8d822 added missing file for tests. 2012-11-18 02:49:55 +05:00
Stephan 8609389bdb U4-1198 - publish dialog does not detect that a parent is not published 2012-11-17 14:55:58 -01:00
Stephan 48f985b70a U4-1212 - can publish grand-child of unpublished node
fixed by introducing Document PathPublished property
2012-11-17 14:37:41 -01:00
Stephan b02afb3af8 u4-1186 - Manage hostnames UI bug with validators 2012-11-17 13:45:53 -01:00
Stephan b9d814c3fb (michielvoo pull request) Consitent new lines in templates 2012-11-17 13:28:38 -01:00
Stephan 1b54ce1d48 U4-1210 - ysod on rollback 2012-11-17 12:29:05 -01:00
Stephan e3efc0d19b U4-1194 - Mvc templates do not work when running in a virtual directory 2012-11-16 15:52:14 -01:00
Sebastiaan Janssen 3ba9e09164 Update obsolete messages to point to the correct classes (instead of being misleading) :-) 2012-11-16 14:41:30 -01:00
NielsHartvig@UMBRACORATI.localdomain d148c10c66 Update to sanitizer 2012-11-16 14:24:24 -01:00
NielsHartvig@UMBRACORATI.localdomain 2b573b9070 The BOSS is fixing U4-367 2012-11-16 14:08:28 -01:00
Shannon Deminick 4cb03ab36c Fixes issue with ChildActions when inherting from UmbracoViewPage<T> and using the @Umbraco helper. 2012-11-16 10:08:12 +05:00
Shannon Deminick 3ebbcc77e9 Merge 2012-11-16 00:45:29 +05:00
Shannon Deminick 8be97295dc Added new method to RenderMvcController for easier return of the current template when hijacking routes.
Added better error checking for media handling in MVC.
2012-11-16 00:38:03 +05:00
Shannon Deminick 3dd411f159 Working on #U4-1174, lots of updates/fixes to media in MVC regarding loading data from the examine cache to return media + lots of unit tests. 2012-11-15 21:46:54 +05:00
Shannon Deminick 8b141dc51a Working on #U4-1174, lots of updates/fixes to media in MVC + unit tests. 2012-11-15 20:11:10 +05:00
Stephan 278aa3f820 U4-1203 - UmbracoHelper.RenderMacro displays trace output at the wrong place 2012-11-15 13:41:44 -01:00
Shannon Deminick a7a38478db Working on #U4-1174 - issue with TypedMedia in MVC, fixes a few things and ensures Children() works
as expected, adds unit tests.
2012-11-15 04:18:23 +05:00
Shannon Deminick b2e004b825 renamed namespace in test proj 2012-11-15 02:04:46 +05:00
Shannon Deminick 10df6e878c updated config 2012-11-14 22:05:58 +05:00
Shannon Deminick eac11c1b80 cleaned up some of the install auth attribute 2012-11-14 21:22:30 +05:00
Shannon Deminick 0ad5da67ea Merge with 4.10.1 2012-11-14 21:18:34 +05:00
Shannon Deminick 3fb9ffca5b Update for installer rest service, updates version 2012-11-14 19:50:39 +05:00
Stephan 8e7fe5ee55 fix f3a3bdaf6329 2012-11-14 06:40:09 -01:00
Shannon Deminick 9554c6a1c6 Fixes #U4-1174 - allows MVC views to render when using RenderTemplate. Added new UmbracoHelper method RenderTemplate. Cleaned up some code and
ensuring that the string writers are disposed. Moved TemplateRenderer to a better namespace.
2012-11-14 10:47:40 +05:00
Shannon Deminick 8597876c92 Fixed up the library calls to RenderTemplate, no longer a ton of duplicated code and removed
the requirement to build up query strings as this is completley not required since we use 'preserveForm'
in the Server.Execute.
2012-11-14 09:31:20 +05:00
Shannon Deminick 3df7d81bde Fixed up the webforms url gen 2012-11-14 09:19:39 +05:00
Shannon Deminick f82ae4fdda Fixes: #U4-1174, this now works for all webforms related templates, however RenderTemplate will currently not work for
MVC templates... this will come soon. If you try to it will just throw a NotImplementedException.
2012-11-14 09:13:53 +05:00
Shannon Deminick 4a981225b3 Merge 2012-11-14 03:52:34 +05:00
Shannon Deminick 0cd115c268 Fixees: #U4-1166, automatically adds parsable routes in the route table to the reserved paths
so you don't have to explicitly add reserved paths to Umbraco config that you are creating routes for.
2012-11-14 03:32:50 +05:00
Sebastiaan Janssen 291b0582e4 Merge 2012-11-12 07:41:40 -01:00
Sebastiaan Janssen f4e48872a2 Imported pull request by Michiel van Oosterhout (consistent line endings)
Removed some commented out code
Pull: http://umbraco.codeplex.com/SourceControl/network/forks/michielvoo/UmbracoU4451/contribution/3482
2012-11-12 07:40:58 -01:00
Shannon Deminick 9e320700e2 Fixes: #U4-1178, adds another strongly typed overload to GetPropertyValue<T> and adds more unit tests. 2012-11-12 10:50:23 +05:00
Shannon Deminick 7f0ff70ca9 Fixes: #U4-1132, this is a bit of a hack fix because the Media should include creatorName/id but it doesn't. 2012-11-12 09:20:54 +05:00
Shannon Deminick 65e3b7f951 Merge 2012-11-12 08:24:36 +05:00
Shannon Deminick 156f145c69 Updated the build manager to find instances based on persisted cache of previous lookups but uses BuildManager to do so, after
some benchmark unit tests against loading a type from an assembly this is about 100% faster. Updated the UmbracoModule to write more diagnostics
for benchmark debugging. Have basically reduced the startup time to approx 50% of what it used to be based on the current
benchmarks run. Previously app startup on my machine was about 5 seconds, now after the first startup it is about 2.5 seconds.
2012-11-12 08:10:12 +05:00
clausjensen a0c941dac2 Fixes U4-1092 - TinyMce breaks script tags by double wrapping in CDATA on save 2012-11-11 09:50:42 -01:00
Bitmapped 33eb9d40f3 Catches exception thrown by native ActiveDirectoryMembershipProvider when there
is no current user.
Fixes U4-709
2012-11-11 09:40:48 -01:00
Sebastiaan Janssen cf8186653c Merge 2012-11-11 09:19:02 -01:00
Sebastiaan Janssen 75403d3b94 Fix by Tom Witherington - U4-1167 tags not saving or deleting in Tags data type
Also cleaned up the usage of obsolete method calls
2012-11-11 09:17:20 -01:00
Shannon Deminick 083bab0528 Added HashCodeCombiner and unit tests to support. Added ability to create a hashed file based on scanned assemblies in the
PluginManager and added a cached plugin xml file to the PluginManager. Now we don't actually scan any assemblies on app startup
during plugin finding if none of the DLLs have changed. Added trace statements to the UmbracoModule for better benchmarking for
how long a full request takes to load from start to finish.
2012-11-11 09:09:06 +05:00
leekelleher ee3e3787a8 PropertyEditorConverters - reusing TryConvertTo<T>, removing duplicate code. 2012-11-10 21:41:40 +00:00
leekelleher a3895ab149 Added unit tests for PropertyEditorValueConverters. 2012-11-10 21:40:37 +00:00
Matt@MBP13-PC c590c6a265 Fixes issue #U4-1169 wherby Umbraco.Field always runs in the context of the current page regardless of whether a custom IPublishedContent is passed in 2012-11-10 16:40:00 +00:00
leekelleher 6c1bf4b85f Added unit test for ObjectExtensions TryConvertTo<DateTime>.
Modified CustomBooleanTypeConverter to accept an empty string as a FALSE.
2012-11-10 14:09:27 +00:00
Sebastiaan Janssen 3632d6b0c6 Opened branch 4.11.0 2012-11-08 15:31:41 -01:00
Sebastiaan Janssen bf95792524 Merge with 4.10.0 2012-11-08 15:00:52 -01:00
Sebastiaan Janssen 885b421201 Closed branch 4.10.0 2012-11-08 14:48:26 -01:00
Sebastiaan Janssen b11143e2c4 Added tag Release-4.10.0 for changeset f6da531fbb4c 2012-11-08 14:46:56 -01:00
Sebastiaan Janssen 0df1ebb83e Merge 4.9.1 into default 2012-11-01 07:12:47 -01:00
Sebastiaan Janssen 204d7a79aa Closed branch 4.9.1 2012-11-01 07:10:42 -01:00
Sebastiaan Janssen e68629b8bc Added tag Release-4.9.1 for changeset 8d7d8609e2e4 2012-11-01 07:10:31 -01:00
Sebastiaan Janssen 84858bea65 Move the Umbraco.Web.UI project up to the first position in the .sln file so
that when you first clone the project and hit F5 it will actually start the
correct project (and not the class library)
2012-10-30 15:27:59 -01:00
Sebastiaan Janssen 243633365e Re-include ItemEditing javascripts 2012-10-23 10:46:26 -02:00
Sebastiaan Janssen dc7e18b97b Re-include splitbutton.js 2012-10-12 11:41:29 -02:00
Shannon Deminick d3c553c945 Fixes issue with wrapping the UmbEditor init in doc ready causing template editing not to work. 2012-10-12 09:15:33 +05:00
Casey Neehouse 05fc15d164 Wraps Code Editor initialization in a document ready call to correct an IE7
sizing bug.
2012-10-11 13:02:36 +04:00
Morten Bock a71961c35b Indenting 2012-10-08 13:33:18 -02:00
tg@umbraco.com da8af696c5 Fixes U4-680: insert Macro split buttons not working 2012-10-08 08:42:47 -02:00
Sebastiaan Janssen 12f5df33da Add z-index too treePickerToolTip to get it on top when media picker preview is on 2012-10-23 08:24:33 -02:00
Sebastiaan Janssen f184276ef8 Moved tree picker tooltip style to default.css so it also works in editMacro (and elsewhere) 2012-10-07 11:45:22 -02:00
funka@WETWIRED c72ab927a6 Resolves redundant BaseTreePicker script initialization (U4-192) 2012-10-17 05:36:22 +07:00
Sebastiaan Janssen 7bc2375a77 Adds a nice tooltip when hovering over the content/media picker
#U4-192 Fixed
2012-10-06 11:46:37 -02:00
funka@WETWIRED 392fbb836f Resolves feature request U4-192 Add more meta data to Content and Media pickers 2012-10-06 01:26:56 +07:00
Sebastiaan Janssen 0cb8603c80 Updating version number to 4.9.1 2012-10-23 07:14:48 -02:00
Sebastiaan Janssen 20fc02053a Made CodeMirror 100% height again 2012-10-09 12:25:36 -02:00
Sebastiaan Janssen e389dc39a7 Upgrade to CodeMirror 2.34 2012-10-10 11:02:59 -02:00
Sebastiaan Janssen fbd4669da8 Unpublished icon in tree with published node
#U4-387 Fixed
2012-10-15 07:16:32 -02:00
Morten Bock c138c6643a Ignore casing, and avoid null http contexts 2012-10-04 14:48:14 -02:00
Morten Bock a2b876608f Refactoring to use object resolver, instead of ProviderBase 2012-11-21 07:14:40 -01:00
Morten Bock c95c1a7038 Add support for thumbs and crops from standard datatypes. 2012-09-30 20:37:05 -02:00
Morten Bock 9e1c5e71e4 Adding the umbraco:image control, and the ImageUrl feature with a some generic ProviderFeature classes, to make it easier to implement future provider based features. 2012-11-21 07:13:31 -01:00
Sebastiaan Janssen aba68720bb Localized the create window for new Scrips (js) 2012-11-21 06:54:52 -01:00
Sebastiaan Janssen 1b1722c875 Renamed method to remove characters that are illegal in XML and made the method internal for now 2012-11-21 06:23:31 -01:00
Michiel van Oosterhout 248af2eaa2 Correct code that validates the user name when the session times out by serializing
user name and password.

Adds a minified 4KB JSON library to umbraco.aspx to support older browsers, namely
https://github.com/douglascrockford/JSON-js (public domain)
2012-10-07 20:54:34 -02:00
Casey Neehouse 0709174560 Merge 2012-11-20 21:11:11 +05:00
Casey Neehouse b0c0ed050d Adds SQL to validate that a node is published before loading the xml.
U4-759, u4-590, U4-589
2012-11-20 21:09:19 +05:00
Sebastiaan Janssen e3a085774c Revert 5c828605ef65 / 8b3a266b2d00 because that would have nasty side effects,
see http://issues.umbraco.org/issue/U4-1061
2012-11-20 14:49:30 -01:00
Sebastiaan Janssen 6f0ddc37a0 Include System.Data.SqlServerCe* should do a copy local 2012-11-20 14:13:47 -01:00
Sebastiaan Janssen d3eb5ceabe Merge 2012-11-20 12:55:17 -01:00
Stephan 1bffb7395c U4-1192 - uQuery.GetNodeIdByUrl should not follow redirects etc 2012-11-20 09:12:45 -01:00
Stephan e636a42744 .hgignore ~/scripts and ~/images 2012-11-20 08:52:56 -01:00
Stephan d3927a1265 code annotation attributes TLC 2012-11-20 08:49:06 -01:00
Stephan d6fc106588 fix DisposableTimer so args can be evaluated _after_ completion 2012-11-20 08:34:32 -01:00
Stephan 68fc833280 U4-1186 - bugfix previous commit 2012-11-19 16:09:43 -01:00
David@David-PC 5a8443fe72 committed wrong version 2012-11-18 18:48:56 -01:00
David@David-PC 153fb4a248 Do a recursive unpublish (fixes U4-462, U4-594, U4-1061) 2012-11-17 14:25:04 -01:00
Michael Wulff Nielsen 72ef5b01d2 Fixes bug 383, inserting macro parameters with quotes fails in macrocontainer 2012-11-20 09:29:38 -01:00
NielsHartvig@UMBRACORATI.localdomain 0854fee4ee Update to sanitizer 2012-11-16 14:24:24 -01:00
NielsHartvig@UMBRACORATI.localdomain e122d40fb9 The BOSS is fixing U4-367 2012-11-16 14:08:28 -01:00
Sebastiaan Janssen b696aa4340 ApplicationContext.Current.ApplicationCache wasn't public due to an oversight, it is now. 2012-11-19 15:31:58 -01:00
Sebastiaan Janssen e32dd303e3 Have to revert Microsoft.WebApplication.target file change as we got weird
results (umbraco.presentation folder and a XmlSerializers dll in the root).
Copied the targets file to the appropriate Program Files folder on the build
server. :-(
2012-11-19 15:02:43 -01:00
Stephan 7c524abb84 U4-1186 - support wildcard domains to change the culture 2012-11-19 14:11:34 -01:00
Stephan 993bac8a29 bugfix LogHelper 2012-11-19 14:09:52 -01:00
dseefeld 51769847ad Error: Delete media item with upload property - empty recycle bin fails
Fixed #U4-771
2012-09-17 04:06:53 -02:00
Sebastiaan Janssen 918e7ad682 Fixed "inception" media tree bug due to recycle bin auto initializing when it shouldn't 2012-10-23 07:06:50 -02:00
466 changed files with 38238 additions and 24907 deletions
+6 -2
View File
@@ -2,7 +2,6 @@
syntax: glob
*.obj
*.exe
*.pdb
*.user
*.aps
@@ -36,6 +35,9 @@ src\Umbraco.Web.UI\media\*
src\Umbraco.Web.UI\masterpages\*
src\Umbraco.Web.UI\macroScripts\*
src\Umbraco.Web.UI\xslt\*
src\Umbraco.Web.UI\images\*
src\Umbraco.Web.UI\scripts\*
src\Umbraco.Web.UI\Web.*.config.transformed
umbraco\presentation\umbraco\plugins\uComponents\uComponentsInstaller.ascx
umbraco\presentation\packages\uComponents\MultiNodePicker\CustomTreeService.asmx
@@ -56,4 +58,6 @@ src/Umbraco.Tests/config/umbracoSettings.config
src/Umbraco.Web.UI/App_Plugins/*
src/Umbraco.Web.UI/Views/*
src\Umbraco.Web.UI\[W]eb.config
src\Umbraco.Web.UI\[W]eb.config
src/packages/
build/*.zip
+17 -4
View File
@@ -10,7 +10,20 @@ d03fcffb8834a9583a56813bb44b6abbd9f042cc Release-4.6.0
096f20bb0575d6199f20fcb3147b63554e765a74 Release-4.8.0
8f8a203857886b373148af29edd57460a42940be Release-4.8.1
de73e687ddf6086ed52b6554676c1632865d07f2 Release-4.9.0
de73e687ddf6086ed52b6554676c1632865d07f2 Release-4.9.0
0000000000000000000000000000000000000000 Release-4.9.0
0000000000000000000000000000000000000000 Release-4.9.0
09f5a69cf19ebf7ddd9501e5258bee1e6a125391 Release-4.9.0
8d7d8609e2e4b971da99cd97f72132ce85ce3333 Release-4.9.1
f6da531fbb4c251ff61d314e2a7effb13c71e74a Release-4.10.0
20e4dff821d8ac2527a5353618fa1a23ea1d8b34 Release-4.11.0
7f827760cb49d749616859f528d19dde64807947 Release-4.11.1
7f827760cb49d749616859f528d19dde64807947 Release-4.11.1
6eb5f2fb5a88aa29ea544499df9160a1b31b5638 Release-4.11.1
73711b806a4044dbf0d7d7c095ddfdda23b09932 4.11.2
73711b806a4044dbf0d7d7c095ddfdda23b09932 4.11.2
0000000000000000000000000000000000000000 4.11.2
73711b806a4044dbf0d7d7c095ddfdda23b09932 Release-4.11.2
77db220b89e166b3c0736ed321ecfd6416cddbcd Release-4.11.2.1
54cde33b809dcb3a1f7e7ae0d5375f6dd0d89c8d Release-4.11.2.2
baa44b79cf90a60631e38e11f771c200b08a4583 Release-4.11.3
e4d0c7e740555d8707ba71f55a623a3f96da8e65 Release-4.11.3.1
e4d0c7e740555d8707ba71f55a623a3f96da8e65 Release-4.11.3.1
0000000000000000000000000000000000000000 Release-4.11.3.1
e02f5aebb87e3f07d27376647756caa9762931d8 Release-4.11.4
-3
View File
@@ -1,3 +0,0 @@
NuGet.exe pack NuSpecs\UmbracoCms.Core.nuspec
NuGet.exe pack NuSpecs\UmbracoCms.nuspec
REM pause
+17 -1
View File
@@ -1,5 +1,21 @@
@ECHO OFF
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj"
set version=4.11.6
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%version%
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\macroScripts\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\xslt\dummy.txt
NuGet.exe pack NuSpecs\UmbracoCms.Core.nuspec -Version %version%
NuGet.exe pack NuSpecs\UmbracoCms.nuspec -Version %version%
if ERRORLEVEL 1 goto :showerror
+11 -1
View File
@@ -24,6 +24,9 @@
<PropertyGroup Condition="'$(BUILD_NUMBER)'!=''">
<DECIMAL_BUILD_NUMBER>.$(BUILD_NUMBER)</DECIMAL_BUILD_NUMBER>
</PropertyGroup>
<PropertyGroup Condition="'$(BUILD_RELEASE)'!=''">
<DECIMAL_BUILD_NUMBER>.$(BUILD_RELEASE)</DECIMAL_BUILD_NUMBER>
</PropertyGroup>
<PropertyGroup>
<BuildConfiguration>Release</BuildConfiguration>
@@ -160,7 +163,7 @@
<Message Text="Finished offsetting timestamps" Importance="high" />
</Target>
<Target Name="CompileProjects">
<Target Name="CompileProjects" DependsOnTargets="SetVersionNumber">
<Message Text="Compiling web project to build\$(BuildFolder)" Importance="high" />
<!-- For UseWPP_CopyWebApplication=True see http://stackoverflow.com/questions/1983575/copywebapplication-with-web-config-transformations -->
@@ -232,6 +235,13 @@
<Message Text="Finished compiling projects" Importance="high" />
</Target>
<Target Name="SetVersionNumber" Condition="'$(BUILD_RELEASE)'!=''">
<!-- Match & replace 3 and 4 digit version numbers and -beta (if it's there) -->
<FileUpdate Files="..\src\Umbraco.Core\Configuration\GlobalSettings.cs"
Regex="(\d+)\.(\d+)\.(\d+)(.(\d+))?(-([a-zA-Z]+))?"
ReplacementText="$(BUILD_RELEASE)"/>
</Target>
<Target Name="AfterBuild">
<Message Text="Hi" />
</Target>
+2 -1
View File
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>UmbracoCms.Core</id>
<version>4.10.0</version>
<version>$version$</version>
<title>Umbraco Cms Core Binaries</title>
<authors>Morten Christensen</authors>
<owners>Umbraco HQ</owners>
@@ -26,6 +26,7 @@
<file src="..\_BuildOutput\WebApp\bin\ICSharpCode.SharpZipLib.dll" target="lib\ICSharpCode.SharpZipLib.dll" />
<file src="..\_BuildOutput\WebApp\bin\interfaces.dll" target="lib\interfaces.dll" />
<file src="..\_BuildOutput\WebApp\bin\Lucene.Net.dll" target="lib\Lucene.Net.dll" />
<file src="..\_BuildOutput\WebApp\bin\log4net.dll" target="lib\log4net.dll" />
<file src="..\_BuildOutput\WebApp\bin\Microsoft.ApplicationBlocks.Data.dll" target="lib\Microsoft.ApplicationBlocks.Data.dll" />
<file src="..\_BuildOutput\WebApp\bin\Microsoft.Web.Helpers.dll" target="lib\Microsoft.Web.Helpers.dll" />
<file src="..\_BuildOutput\WebApp\bin\Microsoft.Web.Infrastructure.dll" target="lib\Microsoft.Web.Infrastructure.dll" />
+5 -2
View File
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>UmbracoCms</id>
<version>4.10.0</version>
<version>$version$</version>
<title>Umbraco Cms</title>
<authors>Morten Christensen</authors>
<owners>Umbraco HQ</owners>
@@ -15,7 +15,7 @@
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="UmbracoCms.Core" version="4.9.0" />
<dependency id="UmbracoCms.Core" version="[$version$]" />
</dependencies>
</metadata>
<files>
@@ -27,16 +27,19 @@
<file src="..\_BuildOutput\WebApp\scripts\**" target="Content\scripts" />
<file src="..\_BuildOutput\WebApp\usercontrols\**" target="Content\usercontrols" />
<file src="..\_BuildOutput\WebApp\xslt\**" target="Content\xslt" />
<file src="..\_BuildOutput\WebApp\Views\**" target="Content\Views" />
<file src="..\_BuildOutput\WebApp\default.aspx" target="Content\default.aspx" />
<file src="..\_BuildOutput\WebApp\Web.config" target="Content\Web.config" />
<file src="..\_BuildOutput\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
<file src="..\_BuildOutput\WebApp\App_Code\**" target="UmbracoFiles\App_Code" />
<file src="..\_BuildOutput\WebApp\App_Data\**" target="UmbracoFiles\App_Data" />
<file src="..\_BuildOutput\WebApp\App_Plugins\**" target="UmbracoFiles\App_Plugins" />
<file src="..\_BuildOutput\WebApp\config\**" target="UmbracoFiles\config" />
<file src="..\_BuildOutput\WebApp\install\**" target="UmbracoFiles\install" />
<file src="..\_BuildOutput\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="..\_BuildOutput\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
<file src="..\_BuildOutput\WebApp\Web.config" target="UmbracoFiles\Web.config" />
<file src="..\_BuildOutput\WebApp\Global.asax" target="UmbracoFiles\Global.asax" />
<file src="tools\install.ps1" target="tools\install.ps1" />
<file src="tools\Readme.txt" target="tools\Readme.txt" />
</files>
+128
View File
@@ -0,0 +1,128 @@
@ECHO OFF
:choice
set /P c=WARNING! Are you sure you want to continue, this will remove all package files, view files, sqlce database, etc... Press 'Y' to auto-remove all files/folders, 'N' to cancel or 'C' to prompt for each folder removal?
if /I "%c%" EQU "C" goto :prompt
if /I "%c%" EQU "Y" goto :auto
if /I "%c%" EQU "N" goto :exit
goto :choice
:prompt
echo Current folder: %CD%
echo Removing sqlce database
del ..\src\Umbraco.Web.UI\App_Data\Umbraco.sdf
echo Resetting installedPackages.config
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
echo Removing plugin cache files
del ..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*
echo Removing cache files and examine index
del ..\src\Umbraco.Web.UI\App_Data\TEMP\*.*
echo Removing log files
del ..\src\Umbraco.Web.UI\App_Data\Logs\*.*
echo Removing packages
del ..\src\Umbraco.Web.UI\App_Data\packages\*.*
echo Removing previews
del ..\src\Umbraco.Web.UI\App_Data\preview\*.*
echo Removing app code files (typically added by starterkits)
del ..\src\Umbraco.Web.UI\App_Code\*.*
echo Removing xslt files
del ..\src\Umbraco.Web.UI\xslt\*.*
echo Removing user control files
del ..\src\Umbraco.Web.UI\UserControls\*.*
echo Removing masterpage files
del ..\src\Umbraco.Web.UI\masterpages\*.*
echo Removing view files
del ..\src\Umbraco.Web.UI\Views\*.*
echo Removing razor files
del ..\src\Umbraco.Web.UI\macroScripts\*.*
echo Removing media files
del ..\src\Umbraco.Web.UI\media\*.*
echo Removing script files
del ..\src\Umbraco.Web.UI\scripts\*.*
echo Removing css files
del ..\src\Umbraco.Web.UI\css\*.*
echo "Umbraco install reverted to clean install"
pause
exit
:auto
echo Current folder: %CD%
echo Removing sqlce database
del ..\src\Umbraco.Web.UI\App_Data\Umbraco.sdf
echo Resetting installedPackages.config
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
echo Removing plugin cache files
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*) DO DEL %%A
echo Removing cache files and examine index
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\TEMP\*.*) DO DEL %%A
echo Removing log files
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\Logs\*.*) DO DEL %%A
echo Removing packages
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\packages\*.*) DO DEL %%A
echo Removing previews
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\preview\*.*) DO DEL %%A
echo Removing app code files (typically added by starterkits)
FOR %%A IN (..\src\Umbraco.Web.UI\App_Code\*.*) DO DEL %%A
echo Removing xslt files
FOR %%A IN (..\src\Umbraco.Web.UI\xslt\*.*) DO DEL %%A
echo Removing masterpage files
FOR %%A IN (..\src\Umbraco.Web.UI\masterpages\*.*) DO DEL %%A
echo Removing user control files
FOR %%A IN (..\src\Umbraco.Web.UI\usercontrols\*.*) DO DEL %%A
echo Removing view files
FOR %%A IN (..\src\Umbraco.Web.UI\Views\*.*) DO DEL %%A
echo Removing razor files
FOR %%A IN (..\src\Umbraco.Web.UI\macroScripts\*.*) DO DEL %%A
echo Removing media files
FOR %%A IN (..\src\Umbraco.Web.UI\media\*.*) DO DEL %%A
echo Removing script files
FOR %%A IN (..\src\Umbraco.Web.UI\scripts\*.*) DO DEL %%A
echo Removing css files
FOR %%A IN (..\src\Umbraco.Web.UI\css\*.*) DO DEL %%A
echo "Umbraco install reverted to clean install"
pause
exit
:exit
exit
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
</configuration>
Binary file not shown.
+152
View File
@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
<!-- Enable the restore command to run before builds -->
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
<!-- Property that enables building a package from a project -->
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
<!-- Determines if package restore consent is required to restore packages -->
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
<!-- Download NuGet.exe if it does not already exist -->
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageSources)' == '' ">
<!-- Package sources used to restore packages. By default will used the registered sources under %APPDATA%\NuGet\NuGet.Config -->
<!--
<PackageSource Include="https://nuget.org/api/v2/" />
<PackageSource Include="https://my-nuget-source/nuget/" />
-->
<PackageSource Include="https://nuget.org/api/v2/" />
<PackageSource Include="http://www.myget.org/F/umbracocore/" />
</ItemGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
<!-- Windows specific commands -->
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
<PackagesConfig>packages.config</PackagesConfig>
</PropertyGroup>
<PropertyGroup>
<!-- NuGet command -->
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\nuget.exe</NuGetExePath>
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
<!-- Commands -->
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -solutionDir "$(SolutionDir) "</RestoreCommand>
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
<!-- We need to ensure packages are restored prior to assembly resolve -->
<ResolveReferencesDependsOn Condition="$(RestorePackages) == 'true'">
RestorePackages;
$(ResolveReferencesDependsOn);
</ResolveReferencesDependsOn>
<!-- Make the build depend on restore packages -->
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
$(BuildDependsOn);
BuildPackage;
</BuildDependsOn>
</PropertyGroup>
<Target Name="CheckPrerequisites">
<!-- Raise an error if we're unable to locate nuget.exe -->
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
<SetEnvironmentVariable EnvKey="VisualStudioVersion" EnvValue="$(VisualStudioVersion)" Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' " />
<!--
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
This effectively acts as a lock that makes sure that the download operation will only happen once and all
parallel builds will have to wait for it to complete.
-->
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT" />
</Target>
<Target Name="_DownloadNuGet">
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
</Target>
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(RestoreCommand)"
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
<Exec Command="$(RestoreCommand)"
LogStandardErrorAsError="true"
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
</Target>
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(BuildCommand)"
Condition=" '$(OS)' != 'Windows_NT' " />
<Exec Command="$(BuildCommand)"
LogStandardErrorAsError="true"
Condition=" '$(OS)' == 'Windows_NT' " />
</Target>
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<OutputFilename ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Net" />
<Using Namespace="Microsoft.Build.Framework" />
<Using Namespace="Microsoft.Build.Utilities" />
<Code Type="Fragment" Language="cs">
<![CDATA[
try {
OutputFilename = Path.GetFullPath(OutputFilename);
Log.LogMessage("Downloading latest version of NuGet.exe...");
WebClient webClient = new WebClient();
webClient.DownloadFile("https://nuget.org/nuget.exe", OutputFilename);
return true;
}
catch (Exception ex) {
Log.LogErrorFromException(ex);
return false;
}
]]>
</Code>
</Task>
</UsingTask>
<UsingTask TaskName="SetEnvironmentVariable" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<EnvKey ParameterType="System.String" Required="true" />
<EnvValue ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
try {
Environment.SetEnvironmentVariable(EnvKey, EnvValue, System.EnvironmentVariableTarget.Process);
}
catch {
}
]]>
</Code>
</Task>
</UsingTask>
</Project>
+4 -4
View File
@@ -9,14 +9,14 @@ namespace Umbraco.Core
/// <summary>
/// A resolver to return all IAction objects
/// </summary>
internal sealed class ActionsResolver : ManyObjectsResolverBase<ActionsResolver, IAction>
internal sealed class ActionsResolver : LazyManyObjectsResolverBase<ActionsResolver, IAction>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="packageActions"></param>
internal ActionsResolver(IEnumerable<Type> packageActions)
internal ActionsResolver(Func<IEnumerable<Type>> packageActions)
: base(packageActions)
{
@@ -34,9 +34,9 @@ namespace Umbraco.Core
}
protected override IEnumerable<IAction> CreateInstances()
{
{
var actions = new List<IAction>();
var foundIActions = PluginManager.Current.ResolveActions();
var foundIActions = InstanceTypes;
foreach (var type in foundIActions)
{
IAction typeInstance;
+2 -1
View File
@@ -43,7 +43,7 @@ namespace Umbraco.Core
/// <remarks>
/// Any caching that is done in the application (app wide) should be done through this property
/// </remarks>
internal CacheHelper ApplicationCache { get; private set; }
public CacheHelper ApplicationCache { get; private set; }
// IsReady is set to true by the boot manager once it has successfully booted
// note - the original umbraco module checks on content.Instance in umbraco.dll
@@ -111,6 +111,7 @@ namespace Umbraco.Core
}
}
}
private string ConfigurationStatus
{
get
+1 -1
View File
@@ -16,7 +16,7 @@ namespace Umbraco.Core
/// <remarks>
/// This class may be opened publicly at some point but needs a review of what is absoletely necessary.
/// </remarks>
internal class CacheHelper
public class CacheHelper
{
private readonly Cache _cache;
+1 -1
View File
@@ -17,7 +17,7 @@ namespace Umbraco.Core
/// Constructor
/// </summary>
/// <param name="refreshers"></param>
internal CacheRefreshersResolver(IEnumerable<Type> refreshers)
internal CacheRefreshersResolver(Func<IEnumerable<Type>> refreshers)
: base(refreshers)
{
@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Umbraco.Core.CodeAnnotations
{
/// <summary>
/// An attribute used to decorate classes or methods that have been marked to be obsoleted
/// </summary>
/// <remarks>
/// This attribute exists because sometimes we may not want to explicitly [Obsolete] a class or method because we
/// know it is still in use and we don't want warning messages showing up in developers output windows when they compile, however
/// we will be able to produce reports declaring which classes/methods/etc... have been marked for being obsoleted in the near future
/// </remarks>
internal class UmbracoDeprecateAttribute : Attribute
{
/// <summary>
/// Constructor requries a description
/// </summary>
/// <param name="description"></param>
public UmbracoDeprecateAttribute(string description)
{
}
}
}
@@ -3,16 +3,30 @@ using System;
namespace Umbraco.Core.CodeAnnotations
{
/// <summary>
/// An attribute used to decorate classes or methods that have been marked to become public but require more testing and review
/// before this is possible.
/// Marks the program elements that Umbraco is experimenting with and could become public.
/// </summary>
internal class UmbracoExperimentalFeatureAttribute : Attribute
/// <remarks>
/// <para>Indicates that Umbraco is experimenting with code that potentially could become
/// public, but we're not sure, and the code is not stable and can be refactored at any time.</para>
/// <para>The issue tracker should contain more details, discussion, and planning.</para>
/// </remarks>
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)]
internal sealed class UmbracoExperimentalFeatureAttribute : Attribute
{
/// <summary>
/// constructor requires a tracker url and a description
/// Initializes a new instance of the <see cref="UmbracoExperimentalFeatureAttribute"/> class with a description.
/// </summary>
/// <param name="trackerUrl"></param>
/// <param name="description"></param>
/// <param name="description">The text string that describes what is intended.</param>
public UmbracoExperimentalFeatureAttribute(string description)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoExperimentalFeatureAttribute"/> class with a tracker url and a description.
/// </summary>
/// <param name="trackerUrl">The url of a tracker issue containing more details, discussion, and planning.</param>
/// <param name="description">The text string that describes what is intended.</param>
public UmbracoExperimentalFeatureAttribute(string trackerUrl, string description)
{
@@ -3,20 +3,31 @@ using System;
namespace Umbraco.Core.CodeAnnotations
{
/// <summary>
/// An attribute used to decorate classes or methods that have potential to become part of the public API
/// Marks the program elements that Umbraco is considering making public.
/// </summary>
/// <remarks>
/// Classes, properties or methods marked with this attribute will have a tracker URL assigned where discussions may take place
/// regarding whether or not this should become part of the public APIs and if/when. Please note that any objects marked with this
/// attribute may not ever become public, this attribute exists to tag code that has potential to become public pending reviews.
/// <para>Indicates that Umbraco considers making the (currently internal) program element public
/// at some point in the future, but the decision is not fully made yet and is still pending reviews.</para>
/// <para>Note that it is not a commitment to make the program element public. It may not ever become public.</para>
/// <para>The issue tracker should contain more details, discussion, and planning.</para>
/// </remarks>
internal class UmbracoProposedPublicAttribute : Attribute
[AttributeUsage(AttributeTargets.All, AllowMultiple=false, Inherited=false)]
internal sealed class UmbracoProposedPublicAttribute : Attribute
{
/// <summary>
/// constructor requires a tracker url and a description
/// Initializes a new instance of the <see cref="UmbracoProposedPublicAttribute"/> class with a description.
/// </summary>
/// <param name="trackerUrl"></param>
/// <param name="description"></param>
/// <param name="description">The text string that describes what is intended.</param>
public UmbracoProposedPublicAttribute(string description)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoProposedPublicAttribute"/> class with a tracker url and a description.
/// </summary>
/// <param name="trackerUrl">The url of a tracker issue containing more details, discussion, and planning.</param>
/// <param name="description">The text string that describes what is intended.</param>
public UmbracoProposedPublicAttribute(string trackerUrl, string description)
{
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Umbraco.Core.CodeAnnotations
{
/// <summary>
/// Marks the program elements that Umbraco will obsolete.
/// </summary>
/// <remarks>
/// Indicates that Umbraco will obsolete the program element at some point in the future, but we do not want to
/// explicitely mark it [Obsolete] yet to avoid warning messages showing when developers compile Umbraco.
/// </remarks>
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)]
internal sealed class UmbracoWillObsoleteAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoWillObsoleteAttribute"/> class with a description.
/// </summary>
/// <param name="description">The text string that describes what is intended.</param>
public UmbracoWillObsoleteAttribute(string description)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoWillObsoleteAttribute"/> class with a tracker url and a description.
/// </summary>
/// <param name="trackerUrl">The url of a tracker issue containing more details, discussion, and planning.</param>
/// <param name="description">The text string that describes what is intended.</param>
public UmbracoWillObsoleteAttribute(string trackerUrl, string description)
{
}
}
}
+117 -47
View File
@@ -1,9 +1,10 @@
using System;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Configuration;
using System.Web.Routing;
using System.Xml;
using System.Xml.Linq;
using Umbraco.Core.IO;
@@ -27,14 +28,31 @@ namespace Umbraco.Core.Configuration
#region Private static fields
// CURRENT UMBRACO VERSION ID
private const string CurrentUmbracoVersion = "4.10.0";
private const string CurrentUmbracoVersion = "4.11.6";
private static string _reservedUrlsCache;
private static readonly object Locker = new object();
//make this volatile so that we can ensure thread safety with a double check lock
private static volatile string _reservedUrlsCache;
private static string _reservedPathsCache;
private static StartsWithContainer _reservedList = new StartsWithContainer();
private static string _reservedPaths;
private static string _reservedUrls;
//ensure the built on (non-changeable) reserved paths are there at all times
private const string StaticReservedPaths = "~/app_plugins/,~/install/,";
private const string StaticReservedUrls = "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd,";
#endregion
/// <summary>
/// used for unit tests
/// </summary>
internal static void ResetCache()
{
_reservedUrlsCache = null;
_reservedPaths = null;
_reservedUrls = null;
}
/// <summary>
/// Gets the reserved urls from web.config.
/// </summary>
@@ -42,11 +60,19 @@ namespace Umbraco.Core.Configuration
public static string ReservedUrls
{
get
{
return ConfigurationManager.AppSettings.ContainsKey("umbracoReservedUrls")
? ConfigurationManager.AppSettings["umbracoReservedUrls"]
: string.Empty;
{
if (_reservedUrls == null)
{
var urls = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedUrls")
? ConfigurationManager.AppSettings["umbracoReservedUrls"]
: string.Empty;
//ensure the built on (non-changeable) reserved paths are there at all times
_reservedUrls = StaticReservedUrls + urls;
}
return _reservedUrls;
}
internal set { _reservedUrls = value; }
}
/// <summary>
@@ -57,10 +83,25 @@ namespace Umbraco.Core.Configuration
{
get
{
return ConfigurationManager.AppSettings.ContainsKey("umbracoReservedPaths")
? ConfigurationManager.AppSettings["umbracoReservedPaths"]
: string.Empty;
if (_reservedPaths == null)
{
var reservedPaths = StaticReservedPaths;
//always add the umbraco path to the list
if (ConfigurationManager.AppSettings.ContainsKey("umbracoPath")
&& !ConfigurationManager.AppSettings["umbracoPath"].IsNullOrWhiteSpace())
{
reservedPaths += ConfigurationManager.AppSettings["umbracoPath"].EnsureEndsWith(',');
}
var allPaths = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedPaths")
? ConfigurationManager.AppSettings["umbracoReservedPaths"]
: string.Empty;
_reservedPaths = reservedPaths + allPaths;
}
return _reservedPaths;
}
internal set { _reservedPaths = value; }
}
/// <summary>
@@ -115,6 +156,9 @@ namespace Umbraco.Core.Configuration
/// This will return the MVC area that we will route all custom routes through like surface controllers, etc...
/// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin
/// we will convert the '/' to '-' and use that as the path. its a bit lame but will work.
///
/// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something
/// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco".
/// </remarks>
internal static string UmbracoMvcArea
{
@@ -124,7 +168,7 @@ namespace Umbraco.Core.Configuration
{
throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified");
}
return Path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim();
return Path.TrimStart(SystemDirectories.Root).TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
}
}
@@ -180,7 +224,7 @@ namespace Umbraco.Core.Configuration
SaveSetting("umbracoConfigurationStatus", value);
}
}
/// <summary>
/// Saves a setting into the configuration file.
/// </summary>
@@ -190,16 +234,16 @@ namespace Umbraco.Core.Configuration
{
var webConfig = new WebConfigurationFileMap();
var vDirs = webConfig.VirtualDirectories;
var vDir = FullpathToRoot;
var physicalPathToRoot = FullpathToRoot;
foreach (VirtualDirectoryMapping v in webConfig.VirtualDirectories)
{
if (v.IsAppRoot)
{
vDir = v.PhysicalDirectory;
physicalPathToRoot = v.PhysicalDirectory;
}
}
string fileName = String.Concat(vDir, "web.config");
string fileName = System.IO.Path.Combine(physicalPathToRoot, "web.config");
var xml = XDocument.Load(fileName);
var appSettings = xml.Root.Descendants("appSettings").Single();
@@ -220,7 +264,7 @@ namespace Umbraco.Core.Configuration
/// <value>The fullpath to root.</value>
public static string FullpathToRoot
{
get { return HttpRuntime.AppDomainAppPath; }
get { return IOHelper.GetRootDirectorySafe(); }
}
/// <summary>
@@ -549,7 +593,29 @@ namespace Umbraco.Core.Configuration
}
}
/// <summary>
/// <summary>
/// Determines whether the current request is reserved based on the route table and
/// whether the specified URL is reserved or is inside a reserved path.
/// </summary>
/// <param name="url"></param>
/// <param name="httpContext"></param>
/// <param name="routes">The route collection to lookup the request in</param>
/// <returns></returns>
public static bool IsReservedPathOrUrl(string url, HttpContextBase httpContext, RouteCollection routes)
{
if (httpContext == null) throw new ArgumentNullException("httpContext");
if (routes == null) throw new ArgumentNullException("routes");
//check if the current request matches a route, if so then it is reserved.
var route = routes.GetRouteData(httpContext);
if (route != null)
return true;
//continue with the standard ignore routine
return IsReservedPathOrUrl(url);
}
/// <summary>
/// Determines whether the specified URL is reserved or is inside a reserved path.
/// </summary>
/// <param name="url">The URL to check.</param>
@@ -557,39 +623,43 @@ namespace Umbraco.Core.Configuration
/// <c>true</c> if the specified URL is reserved; otherwise, <c>false</c>.
/// </returns>
public static bool IsReservedPathOrUrl(string url)
{
// check if GlobalSettings.ReservedPaths and GlobalSettings.ReservedUrls are unchanged
if (!object.ReferenceEquals(_reservedPathsCache, GlobalSettings.ReservedPaths)
|| !object.ReferenceEquals(_reservedUrlsCache, GlobalSettings.ReservedUrls))
{
if (_reservedUrlsCache == null)
{
// store references to strings to determine changes
_reservedPathsCache = GlobalSettings.ReservedPaths;
_reservedUrlsCache = GlobalSettings.ReservedUrls;
string _root = SystemDirectories.Root.Trim().ToLower();
// add URLs and paths to a new list
StartsWithContainer _newReservedList = new StartsWithContainer();
foreach (string reservedUrl in _reservedUrlsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
lock (Locker)
{
//resolves the url to support tilde chars
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl).Trim().ToLower();
if (reservedUrlTrimmed.Length > 0)
_newReservedList.Add(reservedUrlTrimmed);
if (_reservedUrlsCache == null)
{
// store references to strings to determine changes
_reservedPathsCache = GlobalSettings.ReservedPaths;
_reservedUrlsCache = GlobalSettings.ReservedUrls;
string _root = SystemDirectories.Root.Trim().ToLower();
// add URLs and paths to a new list
StartsWithContainer _newReservedList = new StartsWithContainer();
foreach (string reservedUrl in _reservedUrlsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
//resolves the url to support tilde chars
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl).Trim().ToLower();
if (reservedUrlTrimmed.Length > 0)
_newReservedList.Add(reservedUrlTrimmed);
}
foreach (string reservedPath in _reservedPathsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
bool trimEnd = !reservedPath.EndsWith("/");
//resolves the url to support tilde chars
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath).Trim().ToLower();
if (reservedPathTrimmed.Length > 0)
_newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/"));
}
// use the new list from now on
_reservedList = _newReservedList;
}
}
foreach (string reservedPath in _reservedPathsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
bool trimEnd = !reservedPath.EndsWith("/");
//resolves the url to support tilde chars
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath).Trim().ToLower();
if (reservedPathTrimmed.Length > 0)
_newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/"));
}
// use the new list from now on
_reservedList = _newReservedList;
}
//The url should be cleaned up before checking:
+145 -89
View File
@@ -25,6 +25,43 @@ namespace Umbraco.Core.Configuration
/// </summary>
internal class UmbracoSettings
{
private static bool GetKeyValue(string key, bool defaultValue)
{
bool value;
string stringValue = GetKey(key);
if (string.IsNullOrWhiteSpace(stringValue))
return defaultValue;
if (bool.TryParse(stringValue, out value))
return value;
return defaultValue;
}
private static int GetKeyValue(string key, int defaultValue)
{
int value;
string stringValue = GetKey(key);
if (string.IsNullOrWhiteSpace(stringValue))
return defaultValue;
if (int.TryParse(stringValue, out value))
return value;
return defaultValue;
}
/// <summary>
/// Used in unit testing to reset all config items that were set with property setters (i.e. did not come from config)
/// </summary>
internal static void ResetSetters()
{
_addTrailingSlash = null;
_forceSafeAliases = null;
_useLegacySchema = null;
_useDomainPrefixes = null;
_umbracoLibraryCacheDuration = null;
_trySkipIisCustomErrors = null;
}
internal const string TempFriendlyXmlChildContainerNodename = ""; // "children";
/// <summary>
@@ -113,11 +150,32 @@ namespace Umbraco.Core.Configuration
{
EnsureSettingsDocument();
string attrName = null;
var pos = key.IndexOf('@');
if (pos > 0)
{
attrName = key.Substring(pos + 1);
key = key.Substring(0, pos - 1);
}
var node = UmbracoSettingsXmlDoc.DocumentElement.SelectSingleNode(key);
if (node == null || node.FirstChild == null || node.FirstChild.Value == null)
return string.Empty;
return node.FirstChild.Value;
}
if (node == null)
return string.Empty;
if (pos < 0)
{
if (node.FirstChild == null || node.FirstChild.Value == null)
return string.Empty;
return node.FirstChild.Value;
}
else
{
var attr = node.Attributes[attrName];
if (attr == null)
return string.Empty;
return attr.Value;
}
}
/// <summary>
/// Gets a value indicating whether the media library will create new directories in the /media directory.
@@ -190,6 +248,7 @@ namespace Umbraco.Core.Configuration
return value != null ? value.Attributes["assembly"].Value : "";
}
}
/// <summary>
/// Gets the type of an external logger that can be used to store log items in 3rd party systems
/// </summary>
@@ -338,24 +397,13 @@ namespace Umbraco.Core.Configuration
{
get
{
try
{
if (_useDomainPrefixes.HasValue)
return _useDomainPrefixes.Value;
bool result;
if (bool.TryParse(GetKey("/settings/requestHandler/useDomainPrefixes"), out result))
return result;
return false;
}
catch
{
return false;
}
// default: false
return _useDomainPrefixes ?? GetKeyValue("/settings/requestHandler/useDomainPrefixes", false);
}
// for unit tests only
internal set
{
_useDomainPrefixes = value;
// for unit tests only
_useDomainPrefixes = value;
}
}
@@ -369,31 +417,14 @@ namespace Umbraco.Core.Configuration
{
get
{
try
{
if (GlobalSettings.UseDirectoryUrls)
{
if (_addTrailingSlash.HasValue)
return _addTrailingSlash.Value;
bool result;
if (bool.TryParse(GetKey("/settings/requestHandler/addTrailingSlash"), out result))
return result;
return false;
}
else
{
return false;
}
}
catch
{
return false;
}
// default: false
return GlobalSettings.UseDirectoryUrls
&& (_addTrailingSlash ?? GetKeyValue("/settings/requestHandler/addTrailingSlash", false));
}
// for unit tests only
internal set
{
_addTrailingSlash = value;
// for unit tests only
_addTrailingSlash = value;
}
}
@@ -601,6 +632,8 @@ namespace Umbraco.Core.Configuration
}
}
private static bool? _forceSafeAliases;
/// <summary>
/// Whether to force safe aliases (no spaces, no special characters) at businesslogic level on contenttypes and propertytypes
/// </summary>
@@ -608,24 +641,34 @@ namespace Umbraco.Core.Configuration
{
get
{
string forceSafeAlias = GetKey("/settings/content/ForceSafeAliases");
if (String.IsNullOrEmpty(forceSafeAlias))
return true;
else
{
try
{
return bool.Parse(forceSafeAlias);
}
catch
{
return true;
}
}
// default: true
return _forceSafeAliases ?? GetKeyValue("/settings/content/ForceSafeAliases", true);
}
internal set
{
// used for unit testing
_forceSafeAliases = value;
}
}
private static bool? _trySkipIisCustomErrors;
/// <summary>
/// Gets or sets a value indicating where to try to skip IIS custom errors.
/// </summary>
public static bool TrySkipIisCustomErrors
{
get
{
// default: false
return _trySkipIisCustomErrors ?? GetKeyValue("/settings/web.routing/@trySkipIisCustomErrors", false);
}
internal set
{
// used for unit testing
_trySkipIisCustomErrors = value;
}
}
/// <summary>
/// Gets the allowed image file types.
@@ -645,6 +688,8 @@ namespace Umbraco.Core.Configuration
get { return GetKey("/settings/content/scripteditor/scriptFileTypes"); }
}
private static int? _umbracoLibraryCacheDuration;
/// <summary>
/// Gets the duration in seconds to cache queries to umbraco library member and media methods
/// Default is 1800 seconds (30 minutes)
@@ -653,22 +698,14 @@ namespace Umbraco.Core.Configuration
{
get
{
string libraryCacheDuration = GetKey("/settings/content/UmbracoLibraryCacheDuration");
if (String.IsNullOrEmpty(libraryCacheDuration))
return 1800;
else
{
try
{
return int.Parse(libraryCacheDuration);
}
catch
{
return 1800;
}
}
// default: 1800
return _umbracoLibraryCacheDuration ?? GetKeyValue("/settings/content/UmbracoLibraryCacheDuration", 1800);
}
internal set
{
// for unit tests only
_umbracoLibraryCacheDuration = value;
}
}
/// <summary>
@@ -1024,27 +1061,12 @@ namespace Umbraco.Core.Configuration
{
get
{
try
{
if (_useLegacySchema.HasValue)
return _useLegacySchema.Value;
string value = GetKey("/settings/content/UseLegacyXmlSchema");
bool result;
if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
return result;
return true;
}
catch (Exception)
{
//default. TODO: When we change this to a real config section we won't have to worry about parse errors
// and should handle defaults with unit tests properly.
return false;
}
// default: true
return _useLegacySchema ?? GetKeyValue("/settings/content/UseLegacyXmlSchema", false);
}
internal set
{
//used for unit testing
// used for unit testing
_useLegacySchema = value;
}
}
@@ -1193,6 +1215,40 @@ namespace Umbraco.Core.Configuration
}
}
private static MacroErrorBehaviour? _macroErrorBehaviour;
/// <summary>
/// This configuration setting defines how to handle macro errors:
/// - Inline - Show error within macro as text (default and current Umbraco 'normal' behavior)
/// - Silent - Suppress error and hide macro
/// - Throw - Throw an exception and invoke the global error handler (if one is defined, if not you'll get a YSOD)
/// </summary>
/// <value>MacroErrorBehaviour enum defining how to handle macro errors.</value>
public static MacroErrorBehaviour MacroErrorBehaviour
{
get
{
if (_macroErrorBehaviour == null)
{
try
{
var behaviour = MacroErrorBehaviour.Inline;
var value = GetKey("/settings/content/MacroErrors");
if (value != null)
{
Enum<MacroErrorBehaviour>.TryParse(value, true, out behaviour);
}
_macroErrorBehaviour = behaviour;
}
catch (Exception ex)
{
LogHelper.Error<UmbracoSettings>("Could not load /settings/content/MacroErrors from umbracosettings.config", ex);
_macroErrorBehaviour = MacroErrorBehaviour.Inline;
}
}
return _macroErrorBehaviour.Value;
}
}
/// <summary>
/// Configuration regarding webservices
+24 -9
View File
@@ -32,8 +32,7 @@ namespace Umbraco.Core
LogHelper.Info<CoreBootManager>("Umbraco application starting");
_timer = DisposableTimer.Start(x => LogHelper.Info<CoreBootManager>("Umbraco application startup complete" + " (took " + x + "ms)"));
//create the ApplicationContext
ApplicationContext = ApplicationContext.Current = new ApplicationContext();
CreateApplicationContext();
InitializeResolvers();
@@ -42,6 +41,15 @@ namespace Umbraco.Core
return this;
}
/// <summary>
/// Creates and assigns the application context singleton
/// </summary>
protected virtual void CreateApplicationContext()
{
//create the ApplicationContext
ApplicationContext = ApplicationContext.Current = new ApplicationContext();
}
/// <summary>
/// Fires after initialization and calls the callback to allow for customizations to occur
/// </summary>
@@ -72,8 +80,7 @@ namespace Umbraco.Core
if (_isComplete)
throw new InvalidOperationException("The boot manager has already been completed");
//freeze resolution to not allow Resolvers to be modified
Resolution.Freeze();
FreezeResolution();
//stop the timer and log the output
_timer.Dispose();
@@ -88,25 +95,33 @@ namespace Umbraco.Core
return this;
}
/// <summary>
/// Freeze resolution to not allow Resolvers to be modified
/// </summary>
protected virtual void FreezeResolution()
{
Resolution.Freeze();
}
/// <summary>
/// Create the resolvers
/// </summary>
protected virtual void InitializeResolvers()
{
CacheRefreshersResolver.Current = new CacheRefreshersResolver(
PluginManager.Current.ResolveCacheRefreshers());
() => PluginManager.Current.ResolveCacheRefreshers());
DataTypesResolver.Current = new DataTypesResolver(
PluginManager.Current.ResolveDataTypes());
() => PluginManager.Current.ResolveDataTypes());
MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver(
PluginManager.Current.ResolveMacroRenderings());
() => PluginManager.Current.ResolveMacroRenderings());
PackageActionsResolver.Current = new PackageActionsResolver(
PluginManager.Current.ResolvePackageActions());
() => PluginManager.Current.ResolvePackageActions());
ActionsResolver.Current = new ActionsResolver(
PluginManager.Current.ResolveActions());
() => PluginManager.Current.ResolveActions());
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
PluginManager.Current.ResolvePropertyEditorValueConverters());
@@ -23,7 +23,7 @@ namespace Umbraco.Core
{
var str = (string)value;
if (str == "1") return true;
if (str == "0") return false;
if (str == "0" || str == "") return false;
}
return base.ConvertFrom(context, culture, value);
+1 -1
View File
@@ -16,7 +16,7 @@ namespace Umbraco.Core
/// Constructor
/// </summary>
/// <param name="dataTypes"></param>
internal DataTypesResolver(IEnumerable<Type> dataTypes)
internal DataTypesResolver(Func<IEnumerable<Type>> dataTypes)
: base(dataTypes)
{
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Dictionary
/// <summary>
/// Resolves the current CultureDictionaryFactory
/// </summary>
internal class CultureDictionaryFactoryResolver : SingleObjectResolverBase<CultureDictionaryFactoryResolver, ICultureDictionaryFactory>
internal sealed class CultureDictionaryFactoryResolver : SingleObjectResolverBase<CultureDictionaryFactoryResolver, ICultureDictionaryFactory>
{
internal CultureDictionaryFactoryResolver(ICultureDictionaryFactory factory)
: base(factory)
+2 -1
View File
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web;
namespace Umbraco.Core
{
@@ -158,7 +159,7 @@ namespace Umbraco.Core
var builder = new StringBuilder();
foreach (var i in d)
{
builder.Append(String.Format("{0}={1}&", i.Key, i.Value));
builder.Append(String.Format("{0}={1}&", HttpUtility.UrlEncode(i.Key), i.Value == null ? string.Empty : HttpUtility.UrlEncode(i.Value.ToString())));
}
return builder.ToString().TrimEnd('&');
}
+123 -87
View File
@@ -4,99 +4,135 @@ using Umbraco.Core.Logging;
namespace Umbraco.Core
{
/// <summary>
/// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a <code>using</code> (C#) statement.
/// </summary>
/// <example>
/// <code>
/// Console.WriteLine("Testing Stopwatchdisposable, should be 567:");
// using (var timer = new DisposableTimer(result => Console.WriteLine("Took {0}ms", result)))
// {
// Thread.Sleep(567);
// }
/// </code>
/// </example>
public class DisposableTimer : DisposableObject
{
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
private readonly Action<long> _callback;
/// <summary>
/// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a <code>using</code> (C#) statement.
/// </summary>
/// <example>
/// <code>
/// Console.WriteLine("Testing Stopwatchdisposable, should be 567:");
// using (var timer = new DisposableTimer(result => Console.WriteLine("Took {0}ms", result)))
// {
// Thread.Sleep(567);
// }
/// </code>
/// </example>
public class DisposableTimer : DisposableObject
{
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
private readonly Action<long> _callback;
protected DisposableTimer(Action<long> callback)
{
_callback = callback;
}
protected DisposableTimer(Action<long> callback)
{
_callback = callback;
}
public Stopwatch Stopwatch
{
get { return _stopwatch; }
}
public Stopwatch Stopwatch
{
get { return _stopwatch; }
}
/// <summary>
/// Starts the timer and invokes the specified callback upon disposal.
/// </summary>
/// <param name="callback">The callback.</param>
/// <returns></returns>
public static DisposableTimer Start(Action<long> callback)
{
return new DisposableTimer(callback);
}
/// <summary>
/// Starts the timer and invokes the specified callback upon disposal.
/// </summary>
/// <param name="callback">The callback.</param>
/// <returns></returns>
public static DisposableTimer Start(Action<long> callback)
{
return new DisposableTimer(callback);
}
/// <summary>
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer TraceDuration<T>(string startMessage, string completeMessage)
{
return TraceDuration(typeof(T), startMessage, completeMessage);
}
public static DisposableTimer TraceDuration<T>(Func<string> startMessage, Func<string> completeMessage)
{
return TraceDuration(typeof(T), startMessage, completeMessage);
}
/// <summary>
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
/// </summary>
/// <param name="loggerType"></param>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage)
{
LogHelper.Info(loggerType, () => startMessage);
return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage + " (took " + x + "ms)"));
}
public static DisposableTimer TraceDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
{
LogHelper.Debug(loggerType, startMessage);
return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage() + " (took " + x + "ms)"));
}
/// <summary>
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer DebugDuration<T>(string startMessage, string completeMessage)
{
return DebugDuration(typeof(T), startMessage, completeMessage);
}
/// <summary>
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer TraceDuration<T>(string startMessage, string completeMessage)
{
return TraceDuration(typeof(T), startMessage, completeMessage);
}
/// <summary>
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
/// </summary>
/// <param name="loggerType"></param>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage)
{
LogHelper.Debug(loggerType, () => startMessage);
return new DisposableTimer(x => LogHelper.Debug(loggerType, () => completeMessage + " (took " + x + "ms)"));
}
/// <summary>
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
/// </summary>
/// <param name="loggerType"></param>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage)
{
LogHelper.Info(loggerType, () => startMessage);
return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage + " (took " + x + "ms)"));
}
/// <summary>
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
/// </summary>
protected override void DisposeResources()
{
_callback.Invoke(Stopwatch.ElapsedMilliseconds);
}
}
/// <summary>
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer DebugDuration<T>(string startMessage, string completeMessage)
{
return DebugDuration(typeof(T), startMessage, completeMessage);
}
/// <summary>
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer DebugDuration<T>(Func<string> startMessage, Func<string> completeMessage)
{
return DebugDuration(typeof(T), startMessage, completeMessage);
}
/// <summary>
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
/// </summary>
/// <param name="loggerType"></param>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage)
{
LogHelper.Debug(loggerType, () => startMessage);
return new DisposableTimer(x => LogHelper.Debug(loggerType, () => completeMessage + " (took " + x + "ms)"));
}
/// <summary>
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
/// </summary>
/// <param name="loggerType"></param>
/// <param name="startMessage"></param>
/// <param name="completeMessage"></param>
/// <returns></returns>
public static DisposableTimer DebugDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
{
LogHelper.Debug(loggerType, startMessage);
return new DisposableTimer(x => LogHelper.Debug(loggerType, () => completeMessage() + " (took " + x + "ms)"));
}
/// <summary>
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
/// </summary>
protected override void DisposeResources()
{
_callback.Invoke(Stopwatch.ElapsedMilliseconds);
}
}
}
@@ -0,0 +1,178 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Reflection;
using System.Text;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Dynamics
{
/// <summary>
/// A helper class to try invoke members, find properties, etc...
/// </summary>
internal class DynamicInstanceHelper
{
internal class TryInvokeMemberResult
{
public object ObjectResult { get; private set; }
public TryInvokeMemberSuccessReason Reason { get; private set; }
public TryInvokeMemberResult(object result, TryInvokeMemberSuccessReason reason)
{
ObjectResult = result;
Reason = reason;
}
}
internal enum TryInvokeMemberSuccessReason
{
FoundProperty,
FoundMethod,
FoundExtensionMethod
}
/// <summary>
/// Attempts to invoke a member based on the dynamic instance
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="thisObject">The object instance to invoke the extension method for</param>
/// <param name="binder"></param>
/// <param name="args"></param>
/// <returns></returns>
/// <remarks>
/// First tries to find a property with the binder name, if that fails it will try to find a static or instance method
/// on the object that matches the binder name
/// </remarks>
public static Attempt<TryInvokeMemberResult> TryInvokeMember<T>(T thisObject, InvokeMemberBinder binder, object[] args)
{
return TryInvokeMember<T>(thisObject, binder, args, null);
}
/// <summary>
/// Attempts to invoke a member based on the dynamic instance
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="thisObject">The object instance to invoke the extension method for</param>
/// <param name="binder"></param>
/// <param name="args"></param>
/// <param name="findExtensionMethodsOnTypes">The types to scan for extension methods </param>
/// <returns></returns>
/// <remarks>
/// First tries to find a property with the binder name, if that fails it will try to find a static or instance method
/// on the object that matches the binder name, if that fails it will then attempt to invoke an extension method
/// based on the binder name and the extension method types to scan.
/// </remarks>
public static Attempt<TryInvokeMemberResult> TryInvokeMember<T>(T thisObject,
InvokeMemberBinder binder,
object[] args,
IEnumerable<Type> findExtensionMethodsOnTypes)
{
//TODO: We MUST cache the result here, it is very expensive to keep finding extension methods!
object result;
try
{
//Property?
result = typeof(T).InvokeMember(binder.Name,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.GetProperty,
null,
thisObject,
args);
return new Attempt<TryInvokeMemberResult>(true, new TryInvokeMemberResult(result, TryInvokeMemberSuccessReason.FoundProperty));
}
catch (MissingMethodException)
{
try
{
//Static or Instance Method?
result = typeof(T).InvokeMember(binder.Name,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Static |
System.Reflection.BindingFlags.InvokeMethod,
null,
thisObject,
args);
return new Attempt<TryInvokeMemberResult>(true, new TryInvokeMemberResult(result, TryInvokeMemberSuccessReason.FoundMethod));
}
catch (MissingMethodException)
{
if (findExtensionMethodsOnTypes != null)
{
try
{
result = FindAndExecuteExtensionMethod(thisObject, args, binder.Name, findExtensionMethodsOnTypes);
return new Attempt<TryInvokeMemberResult>(true, new TryInvokeMemberResult(result, TryInvokeMemberSuccessReason.FoundExtensionMethod));
}
catch (TargetInvocationException ext)
{
//don't log here, we return this exception because the caller may need to do something specific when
//this exception occurs.
return new Attempt<TryInvokeMemberResult>(ext);
}
catch (Exception ex)
{
var sb = new StringBuilder("An error occurred finding an executing an extension method for type ");
sb.Append(typeof (T));
sb.Append("Types searched for extension methods were ");
foreach(var t in findExtensionMethodsOnTypes)
{
sb.Append(t + ",");
}
LogHelper.Error<DynamicInstanceHelper>(sb.ToString(), ex);
return new Attempt<TryInvokeMemberResult>(ex);
}
}
return Attempt<TryInvokeMemberResult>.False;
}
}
catch (Exception ex)
{
LogHelper.Error<DynamicInstanceHelper>("An unhandled exception occurred in method TryInvokeMember", ex);
return new Attempt<TryInvokeMemberResult>(ex);
}
}
/// <summary>
/// Attempts to find an extension method that matches the name and arguments based on scanning the Type's passed in
/// to the findMethodsOnTypes parameter
/// </summary>
/// <param name="thisObject">The instance object to execute the extension method for</param>
/// <param name="args"></param>
/// <param name="name"></param>
/// <param name="findMethodsOnTypes"></param>
/// <returns></returns>
internal static object FindAndExecuteExtensionMethod<T>(T thisObject,
object[] args,
string name,
IEnumerable<Type> findMethodsOnTypes)
{
object result = null;
//find known extension methods that match the first type in the list
MethodInfo toExecute = null;
foreach (var t in findMethodsOnTypes)
{
toExecute = ExtensionMethodFinder.FindExtensionMethod(t, args, name, false);
if (toExecute != null)
break;
}
if (toExecute != null)
{
var genericArgs = (new[] { (object)thisObject }).Concat(args);
result = toExecute.Invoke(null, genericArgs.ToArray());
}
else
{
throw new MissingMethodException();
}
return result;
}
}
}
+98 -26
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Dynamic;
using System.Reflection;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Collections;
@@ -10,7 +11,7 @@ using System.Web;
namespace Umbraco.Core.Dynamics
{
public class DynamicXml : DynamicObject, IEnumerable
public class DynamicXml : DynamicObject, IEnumerable<DynamicXml>, IEnumerable<XElement>
{
public XElement BaseElement { get; set; }
@@ -70,7 +71,53 @@ namespace Umbraco.Core.Dynamics
HandleIEnumerableXElement(elements, out result);
return true; //anyway
}
return base.TryInvokeMember(binder, args, out result);
//ok, now lets try to match by member, property, extensino method
var attempt = DynamicInstanceHelper.TryInvokeMember(this, binder, args, new[]
{
typeof (IEnumerable<DynamicXml>),
typeof (IEnumerable<XElement>),
typeof (DynamicXml)
});
if (attempt.Success)
{
result = attempt.Result.ObjectResult;
//need to check the return type and possibly cast if result is from an extension method found
if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod)
{
//if the result is already a DynamicXml instance, then we do not need to cast
if (attempt.Result.ObjectResult != null && !(attempt.Result.ObjectResult is DynamicXml))
{
if (attempt.Result.ObjectResult is XElement)
{
result = new DynamicXml((XElement)attempt.Result.ObjectResult);
}
else if (attempt.Result.ObjectResult is IEnumerable<XElement>)
{
result = ((IEnumerable<XElement>)attempt.Result.ObjectResult).Select(x => new DynamicXml(x));
}
else if (attempt.Result.ObjectResult is IEnumerable<DynamicXml>)
{
result = ((IEnumerable<DynamicXml>)attempt.Result.ObjectResult).Select(x => new DynamicXml(x.BaseElement));
}
}
}
return true;
}
//this is the result of an extension method execution gone wrong so we return dynamic null
if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod
&& attempt.Error != null && attempt.Error is TargetInvocationException)
{
result = new DynamicNull();
return true;
}
result = null;
return false;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
@@ -181,18 +228,39 @@ namespace Umbraco.Core.Dynamics
return new DynamicXml(this.BaseElement.XPathSelectElements(expression).FirstOrDefault());
}
public IEnumerator GetEnumerator()
IEnumerator<XElement> IEnumerable<XElement>.GetEnumerator()
{
return this.BaseElement.Elements().GetEnumerator();
}
public IEnumerator<DynamicXml> GetEnumerator()
{
return this.BaseElement.Elements().Select(e => new DynamicXml(e)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public int Count()
{
return this.BaseElement.Elements().Count();
return ((IEnumerable<XElement>)this).Count();
}
public bool Any()
{
return this.BaseElement.Elements().Any();
return ((IEnumerable<XElement>)this).Any();
}
public IEnumerable<DynamicXml> Take(int count)
{
return ((IEnumerable<DynamicXml>)this).Take(count);
}
public IEnumerable<DynamicXml> Skip(int count)
{
return ((IEnumerable<DynamicXml>)this).Skip(count);
}
public bool IsNull()
@@ -435,86 +503,88 @@ namespace Umbraco.Core.Dynamics
public HtmlString IsDescendant(DynamicXml other, string valueIfTrue)
{
var ancestors = this.Ancestors();
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
}
public HtmlString IsDescendant(DynamicXml other, string valueIfTrue, string valueIfFalse)
{
var ancestors = this.Ancestors();
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
}
public bool IsDescendantOrSelf(DynamicXml other)
{
var ancestors = this.AncestorsOrSelf();
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null);
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null);
}
public HtmlString IsDescendantOrSelf(DynamicXml other, string valueIfTrue)
{
var ancestors = this.AncestorsOrSelf();
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
}
public HtmlString IsDescendantOrSelf(DynamicXml other, string valueIfTrue, string valueIfFalse)
{
var ancestors = this.AncestorsOrSelf();
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
}
public bool IsAncestor(DynamicXml other)
{
var descendants = this.Descendants();
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null);
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null);
}
public HtmlString IsAncestor(DynamicXml other, string valueIfTrue)
{
var descendants = this.Descendants();
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
}
public HtmlString IsAncestor(DynamicXml other, string valueIfTrue, string valueIfFalse)
{
var descendants = this.Descendants();
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
}
public bool IsAncestorOrSelf(DynamicXml other)
{
var descendants = this.DescendantsOrSelf();
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null);
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null);
}
public HtmlString IsAncestorOrSelf(DynamicXml other, string valueIfTrue)
{
var descendants = this.DescendantsOrSelf();
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
}
public HtmlString IsAncestorOrSelf(DynamicXml other, string valueIfTrue, string valueIfFalse)
{
var descendants = this.DescendantsOrSelf();
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
}
public IEnumerable<DynamicXml> Descendants()
{
return Descendants(n => true);
}
public IEnumerable<DynamicXml> Descendants(Func<XElement, bool> func)
public IEnumerable<DynamicXml> Descendants(Func<XElement, bool> func)
{
var flattenedNodes = this.BaseElement.Elements().Map(func, (XElement n) => { return n.Elements(); });
//var flattenedNodes = this.BaseElement.Elements().Map(func, n => n.Elements());
var flattenedNodes = this.BaseElement.Elements().SelectMany(n => n.Elements()).Where(func);
return flattenedNodes.ToList().ConvertAll(n => new DynamicXml(n));
}
public IEnumerable<DynamicXml> DescendantsOrSelf()
public IEnumerable<DynamicXml> DescendantsOrSelf()
{
return DescendantsOrSelf(n => true);
}
public IEnumerable<DynamicXml> DescendantsOrSelf(Func<XElement, bool> func)
public IEnumerable<DynamicXml> DescendantsOrSelf(Func<XElement, bool> func)
{
var flattenedNodes = this.BaseElement.Elements().Map(func, (XElement n) => { return n.Elements(); });
//var flattenedNodes = this.BaseElement.Elements().Map(func, n => n.Elements());
var flattenedNodes = this.BaseElement.Elements().SelectMany(n => n.Elements()).Where(func);
var list = new List<DynamicXml>();
list.Add(this);
list.AddRange(flattenedNodes.ToList().ConvertAll(n => new DynamicXml(n)));
return list;
}
public IEnumerable<DynamicXml> Ancestors()
public IEnumerable<DynamicXml> Ancestors()
{
return Ancestors(item => true);
}
public IEnumerable<DynamicXml> Ancestors(Func<XElement, bool> func)
public IEnumerable<DynamicXml> Ancestors(Func<XElement, bool> func)
{
List<XElement> ancestorList = new List<XElement>();
var ancestorList = new List<XElement>();
var node = this.BaseElement;
while (node != null)
{
@@ -543,11 +613,11 @@ namespace Umbraco.Core.Dynamics
ancestorList.Reverse();
return ancestorList.ConvertAll(item => new DynamicXml(item));
}
public IEnumerable<DynamicXml> AncestorsOrSelf()
public IEnumerable<DynamicXml> AncestorsOrSelf()
{
return AncestorsOrSelf(item => true);
}
public IEnumerable<DynamicXml> AncestorsOrSelf(Func<XElement, bool> func)
public IEnumerable<DynamicXml> AncestorsOrSelf(Func<XElement, bool> func)
{
List<XElement> ancestorList = new List<XElement>();
var node = this.BaseElement;
@@ -661,5 +731,7 @@ namespace Umbraco.Core.Dynamics
}
}
}
}
}
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Dynamics
);
//add the extension methods defined in IEnumerable
candidates = candidates.Concat(typeof(IEnumerable).GetMethods(BindingFlags.Static | BindingFlags.Public));
candidates = candidates.Concat(typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public));
//filter by name
var methodsByName = candidates.Where(m => m.Name == name);
+31 -28
View File
@@ -5,36 +5,35 @@ using Umbraco.Core.Models;
namespace Umbraco.Core.Dynamics
{
[Obsolete("This class should not be used, it is just referenced by already obsoleted code and will be removed in the future")]
internal static class ExtensionMethods
{
public static IEnumerable<TSource> Map<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> selectorFunction,
Func<TSource, IEnumerable<TSource>> getChildrenFunction)
{
if (!source.Any())
{
return source;
}
// Add what we have to the stack
var flattenedList = source.Where(selectorFunction);
// Go through the input enumerable looking for children,
// and add those if we have them
foreach (TSource element in source)
{
var secondInner = getChildrenFunction(element);
if (secondInner.Any())
{
secondInner = secondInner.Map(selectorFunction, getChildrenFunction);
}
flattenedList = flattenedList.Concat(secondInner);
}
return flattenedList;
}
//public static IEnumerable<TSource> Map<TSource>(
// this IEnumerable<TSource> source,
// Func<TSource, bool> selectorFunction,
// Func<TSource, IEnumerable<TSource>> getChildrenFunction)
//{
// if (!source.Any())
// {
// return source;
// }
// // Add what we have to the stack
// var flattenedList = source.Where(selectorFunction);
// // Go through the input enumerable looking for children,
// // and add those if we have them
// foreach (TSource element in source)
// {
// var secondInner = getChildrenFunction(element);
// if (secondInner.Any())
// {
// secondInner = secondInner.Map(selectorFunction, getChildrenFunction);
// }
// flattenedList = flattenedList.Concat(secondInner);
// }
// return flattenedList;
//}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsAny(this string haystack, IEnumerable<string> needles)
{
if (haystack == null) throw new ArgumentNullException("haystack");
@@ -44,6 +43,7 @@ namespace Umbraco.Core.Dynamics
}
return false;
}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsAny(this string haystack, params string[] needles)
{
if (haystack == null) throw new ArgumentNullException("haystack");
@@ -53,6 +53,7 @@ namespace Umbraco.Core.Dynamics
}
return false;
}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsAny(this string haystack, StringComparison comparison, IEnumerable<string> needles)
{
if (haystack == null) throw new ArgumentNullException("haystack");
@@ -62,6 +63,7 @@ namespace Umbraco.Core.Dynamics
}
return false;
}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsAny(this string haystack, StringComparison comparison, params string[] needles)
{
if (haystack == null) throw new ArgumentNullException("haystack");
@@ -71,12 +73,13 @@ namespace Umbraco.Core.Dynamics
}
return false;
}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool ContainsInsensitive(this string haystack, string needle)
{
if (haystack == null) throw new ArgumentNullException("haystack");
return haystack.IndexOf(needle, StringComparison.CurrentCultureIgnoreCase) >= 0;
}
[Obsolete("This method should not be used and will be removed in the future")]
public static bool HasValue(this string s)
{
return !string.IsNullOrWhiteSpace(s);
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Umbraco.Core.Events
{
// Provides information on the macro that caused an error
public class MacroErrorEventArgs : System.EventArgs
{
/// <summary>
/// Name of the faulting macro.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Alias of the faulting macro.
/// </summary>
public string Alias { get; set; }
/// <summary>
/// Filename, file path, fully qualified class name, or other key used by the macro engine to do it's processing of the faulting macro.
/// </summary>
public string ItemKey { get; set; }
/// <summary>
/// Exception raised.
/// </summary>
public Exception Exception { get; set; }
/// <summary>
/// Gets or sets the desired behaviour when a matching macro causes an error. See
/// <see cref="MacroErrorBehaviour"/> for definitions. By setting this in your event
/// you can override the default behaviour defined in UmbracoSettings.config.
/// </summary>
/// <value>Macro error behaviour enum.</value>
public MacroErrorBehaviour Behaviour { get; set; }
}
}
+94
View File
@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace Umbraco.Core
{
/// <summary>
/// Used to create a hash code from multiple objects.
/// </summary>
/// <remarks>
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
/// which we've not included here as we just need a quick easy class for this in order to create a unique
/// hash of directories/files to see if they have changed.
/// </remarks>
internal class HashCodeCombiner
{
private long _combinedHash = 5381L;
internal void AddInt(int i)
{
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
}
internal void AddObject(object o)
{
AddInt(o.GetHashCode());
}
internal void AddDateTime(DateTime d)
{
AddInt(d.GetHashCode());
}
internal void AddCaseInsensitiveString(string s)
{
if (s != null)
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
}
internal void AddFileSystemItem(FileSystemInfo f)
{
//if it doesn't exist, don't proceed.
if (!f.Exists)
return;
AddCaseInsensitiveString(f.FullName);
AddDateTime(f.CreationTimeUtc);
AddDateTime(f.LastWriteTimeUtc);
//check if it is a file or folder
var fileInfo = f as FileInfo;
if (fileInfo != null)
{
AddInt(fileInfo.Length.GetHashCode());
}
var dirInfo = f as DirectoryInfo;
if (dirInfo != null)
{
foreach (var d in dirInfo.GetFiles())
{
AddFile(d);
}
foreach (var s in dirInfo.GetDirectories())
{
AddFolder(s);
}
}
}
internal void AddFile(FileInfo f)
{
AddFileSystemItem(f);
}
internal void AddFolder(DirectoryInfo d)
{
AddFileSystemItem(d);
}
/// <summary>
/// Returns the hex code of the combined hash code
/// </summary>
/// <returns></returns>
internal string GetCombinedHashCode()
{
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
}
}
}
+1 -2
View File
@@ -15,8 +15,7 @@ namespace Umbraco.Core.IO
///
/// This abstract class just wraps the 'real' IFileSystem object passed in to its constructor.
/// </remarks>
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
internal abstract class FileSystemWrapper : IFileSystem
public abstract class FileSystemWrapper : IFileSystem
{
private readonly IFileSystem _wrapped;
+2 -3
View File
@@ -4,9 +4,8 @@ using System.IO;
using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.IO
{
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
internal interface IFileSystem
{
public interface IFileSystem
{
IEnumerable<string> GetDirectories(string path);
+22 -3
View File
@@ -8,6 +8,7 @@ using System.IO;
using System.Configuration;
using System.Web;
using System.Text.RegularExpressions;
using System.Xml;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
@@ -220,7 +221,7 @@ namespace Umbraco.Core.IO
{
foreach (var character in Path.GetInvalidFileNameChars())
{
filePath = filePath.Replace(character, '_');
filePath = filePath.Replace(character, '-');
}
}
else
@@ -228,6 +229,20 @@ namespace Umbraco.Core.IO
filePath = String.Empty;
}
//Break up the file in name and extension before applying the UrlReplaceCharacters
var fileNamePart = filePath.Substring(0, filePath.LastIndexOf('.'));
var ext = filePath.Substring(filePath.LastIndexOf('.'));
//Because the file usually is downloadable as well we check characters against 'UmbracoSettings.UrlReplaceCharacters'
XmlNode replaceChars = UmbracoSettings.UrlReplaceCharacters;
foreach (XmlNode n in replaceChars.SelectNodes("char"))
{
if (n.Attributes.GetNamedItem("org") != null && n.Attributes.GetNamedItem("org").Value != "")
fileNamePart = fileNamePart.Replace(n.Attributes.GetNamedItem("org").Value, XmlHelper.GetNodeValue(n));
}
filePath = string.Concat(fileNamePart, ext);
// Adapted from: http://stackoverflow.com/a/4827510/5018
// Combined both Reserved Characters and Character Data
// from http://en.wikipedia.org/wiki/Percent-encoding
@@ -240,10 +255,14 @@ namespace Umbraco.Core.IO
if (reservedCharacters.IndexOf(character) == -1)
stringBuilder.Append(character);
else
stringBuilder.Append("_");
stringBuilder.Append("-");
}
return stringBuilder.ToString();
// Remove repeating dashes
// From: http://stackoverflow.com/questions/5111967/regex-to-remove-a-specific-repeated-character
var reducedString = Regex.Replace(stringBuilder.ToString(), "-+", "-");
return reducedString;
}
}
}
+1 -2
View File
@@ -11,8 +11,7 @@ namespace Umbraco.Core.IO
/// A custom file system provider for media
/// </summary>
[FileSystemProvider("media")]
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
internal class MediaFileSystem : FileSystemWrapper
public class MediaFileSystem : FileSystemWrapper
{
public MediaFileSystem(IFileSystem wrapped)
: base(wrapped)
+26 -17
View File
@@ -1,24 +1,23 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.Logging;
namespace Umbraco.Core.IO
{
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
internal class PhysicalFileSystem : IFileSystem
public class PhysicalFileSystem : IFileSystem
{
private readonly string _rootPath;
private readonly string _rootUrl;
public PhysicalFileSystem(string virtualRoot)
{
_rootPath = System.Web.Hosting.HostingEnvironment.MapPath(virtualRoot);
_rootUrl = VirtualPathUtility.ToAbsolute(virtualRoot);
_rootPath = IOHelper.MapPath(virtualRoot);
_rootUrl = IOHelper.ResolveUrl(virtualRoot);
}
public PhysicalFileSystem(string rootPath, string rootUrl)
@@ -43,9 +42,13 @@ namespace Umbraco.Core.IO
return Directory.EnumerateDirectories(path).Select(GetRelativePath);
}
catch (UnauthorizedAccessException ex)
{ }
{
LogHelper.Error<PhysicalFileSystem>("Not authorized to get directories", ex);
}
catch (DirectoryNotFoundException ex)
{ }
{
LogHelper.Error<PhysicalFileSystem>("Directory not found", ex);
}
return Enumerable.Empty<string>();
}
@@ -65,7 +68,9 @@ namespace Umbraco.Core.IO
Directory.Delete(GetFullPath(path), recursive);
}
catch (DirectoryNotFoundException ex)
{ }
{
LogHelper.Error<PhysicalFileSystem>("Directory not found", ex);
}
}
public bool DirectoryExists(string path)
@@ -80,9 +85,7 @@ namespace Umbraco.Core.IO
public void AddFile(string path, Stream stream, bool overrideIfExists)
{
if (FileExists(path) && !overrideIfExists)
throw new InvalidOperationException(string.Format("A file at path '{0}' already exists",
path));
if (FileExists(path) && !overrideIfExists) throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
EnsureDirectory(Path.GetDirectoryName(path));
@@ -108,9 +111,13 @@ namespace Umbraco.Core.IO
return Directory.EnumerateFiles(path, filter).Select(GetRelativePath);
}
catch (UnauthorizedAccessException ex)
{ }
{
LogHelper.Error<PhysicalFileSystem>("Not authorized to get directories", ex);
}
catch (DirectoryNotFoundException ex)
{ }
{
LogHelper.Error<PhysicalFileSystem>("Directory not found", ex);
}
return Enumerable.Empty<string>();
}
@@ -130,7 +137,9 @@ namespace Umbraco.Core.IO
File.Delete(GetFullPath(path));
}
catch (FileNotFoundException ex)
{ }
{
LogHelper.Error<PhysicalFileSystem>("File not found", ex);
}
}
public bool FileExists(string path)
@@ -188,7 +197,7 @@ namespace Umbraco.Core.IO
protected string EnsureTrailingSeparator(string path)
{
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal))
path = path + Path.DirectorySeparatorChar;
return path;
+24 -4
View File
@@ -12,6 +12,7 @@ namespace Umbraco.Core.IO
//all paths has a starting but no trailing /
public class SystemDirectories
{
//TODO: Why on earth is this even configurable? You cannot change the /Bin folder in ASP.Net
public static string Bin
{
get
@@ -68,6 +69,15 @@ namespace Umbraco.Core.IO
}
}
public static string AppPlugins
{
get
{
//NOTE: this is not configurable and shouldn't need to be
return "~/App_Plugins";
}
}
public static string MvcViews
{
get
@@ -173,16 +183,26 @@ namespace Umbraco.Core.IO
}
}
private static string _root;
/// <summary>
/// Gets the root path of the application
/// </summary>
public static string Root
{
get
{
string appPath = HttpRuntime.AppDomainAppVirtualPath ?? string.Empty;
if (appPath == "/")
appPath = string.Empty;
if (_root == null)
{
string appPath = HttpRuntime.AppDomainAppVirtualPath ?? string.Empty;
if (appPath == "/")
appPath = string.Empty;
return appPath;
_root = appPath;
}
return _root;
}
//Only required for unit tests
internal set { _root = value; }
}
}
@@ -64,23 +64,28 @@ namespace Umbraco.Core.Logging
{
_forceStop = true;
var windowsIdentity = WindowsIdentity.GetCurrent();
base.Append(new LoggingEvent(new LoggingEventData
{
Level = Level.Error,
Message =
"Unable to clear out the AsynchronousRollingFileAppender buffer in the allotted time, forcing a shutdown",
TimeStamp = DateTime.UtcNow,
Identity = "",
ExceptionString = "",
UserName = windowsIdentity != null ? windowsIdentity.Name : "",
Domain = AppDomain.CurrentDomain.FriendlyName,
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
LocationInfo =
new LocationInfo(this.GetType().Name, "OnClose", "AsynchronousRollingFileAppender.cs", "59"),
LoggerName = this.GetType().FullName,
Properties = new PropertiesDictionary(),
})
);
var logEvent = new LoggingEvent(new LoggingEventData
{
Level = global::log4net.Core.Level.Error,
Message =
"Unable to clear out the AsynchronousRollingFileAppender buffer in the allotted time, forcing a shutdown",
TimeStamp = DateTime.UtcNow,
Identity = "",
ExceptionString = "",
UserName = windowsIdentity != null ? windowsIdentity.Name : "",
Domain = AppDomain.CurrentDomain.FriendlyName,
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
LocationInfo =
new LocationInfo(this.GetType().Name, "OnClose", "AsynchronousRollingFileAppender.cs", "59"),
LoggerName = this.GetType().FullName,
Properties = new PropertiesDictionary(),
});
if (this.DateTimeStrategy != null)
{
base.Append(logEvent);
}
}
base.OnClose();
+55 -25
View File
@@ -60,49 +60,77 @@ namespace Umbraco.Core.Logging
#region Warn
public static void Warn(Type callingType, string message, params object[] format)
public static void Warn(Type callingType, string message, params Func<object>[] formatItems)
{
var logger = LogManager.GetLogger(callingType);
if (logger != null)
logger.WarnFormat(PrefixThreadId(message), format);
if (logger == null || !logger.IsWarnEnabled) return;
logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray());
}
public static void Warn(Type callingType, TraceContext trace, string message, params object[] format)
public static void Warn(Type callingType, string message, bool showHttpTrace, params Func<object>[] formatItems)
{
if (trace != null)
Mandate.ParameterNotNull(callingType, "callingType");
Mandate.ParameterNotNullOrEmpty(message, "message");
if (showHttpTrace && HttpContext.Current != null)
{
trace.Warn(string.Format(message, format));
HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()));
}
var logger = LogManager.GetLogger(callingType);
if (logger != null)
logger.WarnFormat(PrefixThreadId(message), format);
if (logger == null || !logger.IsWarnEnabled) return;
logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray());
}
public static void WarnWithException(Type callingType, string message, Exception e, params Func<object>[] formatItems)
{
WarnWithException(callingType, message, false, e, formatItems);
}
public static void WarnWithException(Type callingType, string message, bool showHttpTrace, Exception e, params Func<object>[] formatItems)
{
Mandate.ParameterNotNull(e, "e");
Mandate.ParameterNotNull(callingType, "callingType");
Mandate.ParameterNotNullOrEmpty(message, "message");
if (showHttpTrace && HttpContext.Current != null)
{
HttpContext.Current.Trace.Warn(
callingType.Name,
string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()),
e);
}
var logger = LogManager.GetLogger(callingType);
if (logger == null || !logger.IsWarnEnabled) return;
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
logger.WarnFormat(PrefixThreadId(message) + ". Exception: " + e, executedParams);
}
/// <summary>
/// Adds a warn log
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="message"></param>
/// <param name="items"></param>
public static void Warn<T>(string message, params object[] items)
/// <param name="formatItems"></param>
public static void Warn<T>(string message, params Func<object>[] formatItems)
{
var logger = LoggerFor<T>();
if (logger != null)
logger.WarnFormat(PrefixThreadId(message), items);
Warn(typeof(T), message, formatItems);
}
public static void Warn<T>(string message, TraceContext trace, params object[] items)
public static void Warn<T>(string message, bool showHttpTrace, params Func<object>[] formatItems)
{
if (trace != null)
{
trace.Warn(string.Format(message, items));
}
Warn(typeof(T), message, showHttpTrace, formatItems);
}
var logger = LoggerFor<T>();
if (logger != null)
logger.WarnFormat(PrefixThreadId(message), items);
public static void WarnWithException<T>(string message, Exception e, params Func<object>[] formatItems)
{
WarnWithException(typeof(T), message, e, formatItems);
}
public static void WarnWithException<T>(string message, bool showHttpTrace, Exception e, params Func<object>[] formatItems)
{
WarnWithException(typeof(T), message, showHttpTrace, e, formatItems);
}
#endregion
@@ -214,13 +242,15 @@ namespace Umbraco.Core.Logging
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="generateMessageFormat"></param>
/// <param name="trace"></param>
/// <param name="showHttpTrace"></param>
/// <param name="formatItems"></param>
public static void Debug<T>(string generateMessageFormat, TraceContext trace, params Func<object>[] formatItems)
public static void Debug<T>(string generateMessageFormat, bool showHttpTrace, params Func<object>[] formatItems)
{
if (trace != null)
if (showHttpTrace && HttpContext.Current != null)
{
trace.Write(string.Format(generateMessageFormat, formatItems.Select(x => x())));
HttpContext.Current.Trace.Write(
typeof(T).Name,
string.Format(generateMessageFormat, formatItems.Select(x => x()).ToArray()));
}
Debug(typeof(T), generateMessageFormat, formatItems);
}
+23
View File
@@ -0,0 +1,23 @@
namespace Umbraco.Core
{
public enum MacroErrorBehaviour
{
/// <summary>
/// Default umbraco behavior - show an inline error within the
/// macro but allow the page to continue rendering.
/// </summary>
Inline,
/// <summary>
/// Silently eat the error and do not display the offending macro.
/// </summary>
Silent,
/// <summary>
/// Throw an exception which can be caught by the global error handler
/// defined in Application_OnError. If no such error handler is defined
/// then you'll see the Yellow Screen Of Death (YSOD) error page.
/// </summary>
Throw
}
}
+1 -2
View File
@@ -66,8 +66,7 @@ namespace Umbraco.Core.Macros
}
}
var macroAlias = attributes["macroalias"] ?? attributes["alias"];
var macroAlias = attributes.ContainsKey("macroalias") ? attributes["macroalias"] : attributes["alias"];
//call the callback now that we have the macro parsed
macroFoundCallback(macroAlias, attributes);
@@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace Umbraco.Core.Media
{
public interface IImageUrlProvider
{
string Name { get; }
string GetImageUrlFromMedia(int mediaId, IDictionary<string, string> parameters);
string GetImageUrlFromFileName(string specifiedSrc, IDictionary<string, string> parameters);
}
}
@@ -0,0 +1,235 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
namespace Umbraco.Core.ObjectResolution
{
/// <summary>
/// A base class for lazily resolving types for a resolver
/// </summary>
/// <typeparam name="TResolver"></typeparam>
/// <typeparam name="TResolved"></typeparam>
/// <remarks>
/// This is a special case resolver for when types get lazily resolved in order to resolve the actual types. This is useful
/// for when there is some processing overhead (i.e. Type finding in assemblies) to return the Types used to instantiate the instances.
/// In some these cases we don't want to have to type find during application startup, only when we need to resolve the instances.
///
/// Important notes about this resolver: This does not support Insert or Remove and therefore does not support any ordering unless
/// the types are marked with the WeightedPluginAttribute.
/// </remarks>
internal abstract class LazyManyObjectsResolverBase<TResolver, TResolved> : ManyObjectsResolverBase<TResolver, TResolved>
where TResolved : class
where TResolver : class
{
#region Constructors
protected LazyManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: base(scope)
{
}
protected LazyManyObjectsResolverBase(HttpContextBase httpContext)
: base(httpContext)
{
}
/// <summary>
/// Constructor accepting a list of lazy types
/// </summary>
/// <param name="listOfLazyTypes"></param>
/// <param name="scope"></param>
protected LazyManyObjectsResolverBase(IEnumerable<Lazy<Type>> listOfLazyTypes, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(scope)
{
AddTypes(listOfLazyTypes);
}
/// <summary>
/// Constructor accepting a delegate to return a list of types
/// </summary>
/// <param name="typeListDelegate"></param>
/// <param name="scope"></param>
protected LazyManyObjectsResolverBase(Func<IEnumerable<Type>> typeListDelegate, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(scope)
{
_listOfTypeListDelegates.Add(typeListDelegate);
}
/// <summary>
/// Constructor accepting a list of lazy types
/// </summary>
/// <param name="httpContext"></param>
/// <param name="listOfLazyTypes"></param>
protected LazyManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Lazy<Type>> listOfLazyTypes)
: this(httpContext)
{
AddTypes(listOfLazyTypes);
}
/// <summary>
/// Constructor accepting a delegate to return a list of types
/// </summary>
/// <param name="httpContext"></param>
/// <param name="typeListDelegate"></param>
protected LazyManyObjectsResolverBase(HttpContextBase httpContext, Func<IEnumerable<Type>> typeListDelegate)
: this(httpContext)
{
_listOfTypeListDelegates.Add(typeListDelegate);
}
#endregion
private readonly List<Lazy<Type>> _lazyTypeList = new List<Lazy<Type>>();
private readonly List<Func<IEnumerable<Type>>> _listOfTypeListDelegates = new List<Func<IEnumerable<Type>>>();
private List<Type> _resolvedTypes = null;
private readonly ReaderWriterLockSlim _typeResolutionLock = new ReaderWriterLockSlim();
/// <summary>
/// Used for unit tests
/// </summary>
internal bool HasResolvedTypes
{
get { return _resolvedTypes != null; }
}
/// <summary>
/// Once this is called this will resolve all types registered in the lazy list
/// </summary>
protected override IEnumerable<Type> InstanceTypes
{
get
{
using (var lck = new UpgradeableReadLock(_typeResolutionLock))
{
var lazyTypeList = _lazyTypeList.Select(x => x.Value).ToArray();
var listofTypeListDelegates = _listOfTypeListDelegates.SelectMany(x => x()).ToArray();
//we need to validate each resolved type now since we could not do it before when inserting the lazy delegates
if (!HasResolvedTypes)
{
lck.UpgradeToWriteLock();
_resolvedTypes = new List<Type>();
//first iterate the lazy type list
foreach (var l in lazyTypeList)
{
UpdateUniqueList(_resolvedTypes, l);
}
//next iterate the list of list type delegates
foreach (var l in listofTypeListDelegates)
{
UpdateUniqueList(_resolvedTypes, l);
}
}
return _resolvedTypes;
}
}
}
private void UpdateUniqueList(List<Type> uniqueList, Type toAdd)
{
EnsureCorrectType(toAdd);
if (uniqueList.Contains(toAdd))
{
throw new InvalidOperationException("The Type " + toAdd + " already exists in the collection");
}
uniqueList.Add(toAdd);
}
/// <summary>
/// Allows adding of multiple lazy types at once
/// </summary>
/// <param name="types"></param>
protected void AddTypes(IEnumerable<Lazy<Type>> types)
{
EnsureAddSupport();
EnsureResolutionNotFrozen();
using (GetWriteLock())
{
foreach (var t in types)
{
_lazyTypeList.Add(t);
}
}
}
/// <summary>
/// Adds a type list delegate to the collection
/// </summary>
/// <param name="typeListDelegate"></param>
public void AddTypeListDelegate(Func<IEnumerable<Type>> typeListDelegate)
{
EnsureAddSupport();
EnsureResolutionNotFrozen();
using (GetWriteLock())
{
_listOfTypeListDelegates.Add(typeListDelegate);
}
}
/// <summary>
/// Adds a lazy type to the list
/// </summary>
/// <param name="value"></param>
public void AddType(Lazy<Type> value)
{
EnsureAddSupport();
EnsureResolutionNotFrozen();
using (GetWriteLock())
{
_lazyTypeList.Add(value);
}
}
/// <summary>
/// Converts the static type added to a lazy type and adds it to the internal list
/// </summary>
/// <param name="value"></param>
public override void AddType(Type value)
{
AddType(new Lazy<Type>(() => value));
}
/// <summary>
/// Clears all lazy types
/// </summary>
public override void Clear()
{
EnsureClearSupport();
EnsureResolutionNotFrozen();
using (GetWriteLock())
{
_lazyTypeList.Clear();
}
}
/// <summary>
/// Does not support removal
/// </summary>
protected override bool SupportsRemove
{
get { return false; }
}
/// <summary>
/// Does not support insert
/// </summary>
protected override bool SupportsInsert
{
get { return false; }
}
}
}
@@ -17,7 +17,7 @@ namespace Umbraco.Core.ObjectResolution
/// these old classes don't contain metadata, the objects need to be instantiated first to get their metadata, we then store this
/// for use in the GetById method.
/// </remarks>
internal abstract class LegacyTransientObjectsResolver<TResolver, TResolved> : ManyObjectsResolverBase<TResolver, TResolved>
internal abstract class LegacyTransientObjectsResolver<TResolver, TResolved> : LazyManyObjectsResolverBase<TResolver, TResolved>
where TResolved : class
where TResolver : class
{
@@ -27,16 +27,15 @@ namespace Umbraco.Core.ObjectResolution
/// <summary>
/// Constructor
/// </summary>
/// <param name="refreshers"></param>
/// <param name="types"></param>
/// <remarks>
/// We are creating Transient instances (new instances each time) because this is how the legacy code worked and
/// I don't want to muck anything up by changing them to application based instances.
/// TODO: However, it would make much more sense to do this and would speed up the application plus this would make the GetById method much easier.
/// </remarks>
protected LegacyTransientObjectsResolver(IEnumerable<Type> refreshers)
: base(ObjectLifetimeScope.Transient) // new objects every time
{
AddTypes(refreshers);
protected LegacyTransientObjectsResolver(Func<IEnumerable<Type>> types)
: base(types, ObjectLifetimeScope.Transient) // new objects every time
{
}
#endregion
@@ -55,7 +54,7 @@ namespace Umbraco.Core.ObjectResolution
protected abstract Guid GetUniqueIdentifier(TResolved obj);
/// <summary>
/// Returns a new ICacheRefresher instance by id
/// Returns a new TResolved instance by id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using Umbraco.Core.Macros;
using umbraco.interfaces;
@@ -13,14 +15,14 @@ namespace Umbraco.Core.ObjectResolution
/// Much of this classes methods are based on legacy code from umbraco.editorControls.macrocontainer.MacroControlFactory
/// this code should probably be reviewed and cleaned up if necessary.
/// </remarks>
internal sealed class MacroFieldEditorsResolver : ManyObjectsResolverBase<MacroFieldEditorsResolver, IMacroGuiRendering>
internal sealed class MacroFieldEditorsResolver : LazyManyObjectsResolverBase<MacroFieldEditorsResolver, IMacroGuiRendering>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="macroEditors"></param>
internal MacroFieldEditorsResolver(IEnumerable<Type> macroEditors)
internal MacroFieldEditorsResolver(Func<IEnumerable<Type>> macroEditors)
: base(macroEditors, ObjectLifetimeScope.Transient)
{
@@ -47,7 +49,7 @@ namespace Umbraco.Core.ObjectResolution
/// </remarks>
internal string GetValueFromMacroControl(Control macroControl)
{
return ((IMacroGuiRendering)macroControl).Value;
return HttpUtility.HtmlDecode(((IMacroGuiRendering)macroControl).Value);
}
/// <remarks>
@@ -55,7 +57,7 @@ namespace Umbraco.Core.ObjectResolution
/// </remarks>
internal List<Type> MacroControlTypes
{
get { return InstanceTypes; }
get { return InstanceTypes.ToList(); }
}
/// <summary>
@@ -74,7 +76,7 @@ namespace Umbraco.Core.ObjectResolution
{
if (!string.IsNullOrEmpty(prop.Value))
{
instance.Value = prop.Value;
instance.Value = HttpUtility.HtmlDecode(prop.Value);
}
var macroControl = instance as Control;
if (macroControl != null)
@@ -6,14 +6,14 @@ using System.Web;
namespace Umbraco.Core.ObjectResolution
{
internal abstract class ManyObjectsResolverBase<TResolver, TResolved> : ResolverBase<TResolver>
where TResolved : class
where TResolver : class
{
private List<TResolved> _applicationInstances = null;
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private readonly List<Type> _instanceTypes = new List<Type>();
#region Constructors
@@ -34,7 +34,7 @@ namespace Umbraco.Core.ObjectResolution
}
LifetimeScope = scope;
InstanceTypes = new List<Type>();
_instanceTypes = new List<Type>();
}
/// <summary>
@@ -48,7 +48,7 @@ namespace Umbraco.Core.ObjectResolution
if (httpContext == null) throw new ArgumentNullException("httpContext");
LifetimeScope = ObjectLifetimeScope.HttpRequest;
CurrentHttpContext = httpContext;
InstanceTypes = new List<Type>();
_instanceTypes = new List<Type>();
}
/// <summary>
@@ -58,8 +58,8 @@ namespace Umbraco.Core.ObjectResolution
/// <param name="scope">If set to true will resolve singleton objects which will be created once for the lifetime of the application</param>
protected ManyObjectsResolverBase(IEnumerable<Type> value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
: this(scope)
{
InstanceTypes = new List<Type>(value);
{
_instanceTypes = new List<Type>(value);
}
/// <summary>
@@ -71,7 +71,7 @@ namespace Umbraco.Core.ObjectResolution
protected ManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Type> value)
: this(httpContext)
{
InstanceTypes = new List<Type>(value);
_instanceTypes = new List<Type>(value);
}
#endregion
@@ -83,7 +83,10 @@ namespace Umbraco.Core.ObjectResolution
/// <summary>
/// Returns the list of Types registered that instances will be created from
/// </summary>
protected List<Type> InstanceTypes { get; private set; }
protected virtual IEnumerable<Type> InstanceTypes
{
get { return _instanceTypes; }
}
/// <summary>
/// Returns the Current HttpContextBase used to construct this object if one exists.
@@ -97,11 +100,7 @@ namespace Umbraco.Core.ObjectResolution
protected ObjectLifetimeScope LifetimeScope { get; private set; }
private int _defaultPluginWeight = 10;
private bool _supportsAdd = true;
private bool _supportsInsert = true;
private bool _supportsClear = true;
private bool _supportsRemove = true;
/// <summary>
/// Used in conjunction with GetSortedValues and WeightedPluginAttribute, if any of the objects
/// being resolved do not contain the WeightedPluginAttribute then this will be the default weight applied
@@ -189,15 +188,16 @@ namespace Umbraco.Core.ObjectResolution
/// Removes a type.
/// </summary>
/// <param name="value">The type to remove.</param>
public void RemoveType(Type value)
public virtual void RemoveType(Type value)
{
if (!SupportsRemove)
throw new InvalidOperationException("This resolver does not support Removing types");
EnsureRemoveSupport();
using (new WriteLock(_lock))
EnsureResolutionNotFrozen();
using (GetWriteLock())
{
EnsureCorrectType(value);
InstanceTypes.Remove(value);
_instanceTypes.Remove(value);
}
}
@@ -215,8 +215,12 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <param name="types"></param>
protected void AddTypes(IEnumerable<Type> types)
{
using (var l = new WriteLock(_lock))
{
EnsureAddSupport();
EnsureResolutionNotFrozen();
using (GetWriteLock())
{
foreach(var t in types)
{
@@ -225,7 +229,7 @@ namespace Umbraco.Core.ObjectResolution
{
throw new InvalidOperationException("The Type " + t + " already exists in the collection");
};
InstanceTypes.Add(t);
_instanceTypes.Add(t);
}
}
}
@@ -234,19 +238,20 @@ namespace Umbraco.Core.ObjectResolution
/// Adds a Type to the end of the list.
/// </summary>
/// <param name="value">The object to be added.</param>
public void AddType(Type value)
public virtual void AddType(Type value)
{
if (!SupportsAdd)
throw new InvalidOperationException("This resolver does not support Adding new types");
EnsureAddSupport();
using (var l = new WriteLock(_lock))
EnsureResolutionNotFrozen();
using (GetWriteLock())
{
EnsureCorrectType(value);
if (InstanceTypes.Contains(value))
{
throw new InvalidOperationException("The Type " + value + " already exists in the collection");
};
InstanceTypes.Add(value);
_instanceTypes.Add(value);
}
}
@@ -262,14 +267,15 @@ namespace Umbraco.Core.ObjectResolution
/// <summary>
/// Clears the list.
/// </summary>
public void Clear()
public virtual void Clear()
{
if (!SupportsClear)
throw new InvalidOperationException("This resolver does not support Clearing types");
EnsureClearSupport();
using (new WriteLock(_lock))
EnsureResolutionNotFrozen();
using (GetWriteLock())
{
InstanceTypes.Clear();
_instanceTypes.Clear();
}
}
@@ -278,12 +284,13 @@ namespace Umbraco.Core.ObjectResolution
/// </summary>
/// <param name="index">The zero-based index at which the object should be inserted.</param>
/// <param name="value">The object to insert.</param>
public void InsertType(int index, Type value)
public virtual void InsertType(int index, Type value)
{
if (!SupportsInsert)
throw new InvalidOperationException("This resolver does not support Inserting new types");
EnsureInsertSupport();
using (var l = new UpgradeableReadLock(_lock))
EnsureResolutionNotFrozen();
using (var l = GetWriteLock())
{
EnsureCorrectType(value);
if (InstanceTypes.Contains(value))
@@ -291,8 +298,7 @@ namespace Umbraco.Core.ObjectResolution
throw new InvalidOperationException("The Type " + value + " already exists in the collection");
};
l.UpgradeToWriteLock();
InstanceTypes.Insert(index, value);
_instanceTypes.Insert(index, value);
}
}
@@ -306,7 +312,65 @@ namespace Umbraco.Core.ObjectResolution
InsertType(index, typeof (T));
}
private void EnsureCorrectType(Type t)
/// <summary>
/// Returns a WriteLock to use when modifying collections
/// </summary>
/// <returns></returns>
protected WriteLock GetWriteLock()
{
return new WriteLock(_lock);
}
/// <summary>
/// Throws an exception if resolution is frozen
/// </summary>
protected void EnsureResolutionNotFrozen()
{
if (Resolution.IsFrozen)
throw new InvalidOperationException("The type list cannot be modified after resolution has been frozen");
}
/// <summary>
/// Throws an exception if this does not support Remove
/// </summary>
protected void EnsureRemoveSupport()
{
if (!SupportsRemove)
throw new InvalidOperationException("This resolver does not support Removing types");
}
/// <summary>
/// Throws an exception if this does not support Clear
/// </summary>
protected void EnsureClearSupport()
{
if (!SupportsClear)
throw new InvalidOperationException("This resolver does not support Clearing types");
}
/// <summary>
/// Throws an exception if this does not support Add
/// </summary>
protected void EnsureAddSupport()
{
if (!SupportsAdd)
throw new InvalidOperationException("This resolver does not support Adding new types");
}
/// <summary>
/// Throws an exception if this does not support insert
/// </summary>
protected void EnsureInsertSupport()
{
if (!SupportsInsert)
throw new InvalidOperationException("This resolver does not support Inserting new types");
}
/// <summary>
/// Throws an exception if the type is not of the TResolved type
/// </summary>
/// <param name="t"></param>
protected void EnsureCorrectType(Type t)
{
if (!TypeHelper.IsTypeAssignableFrom<TResolved>(t))
throw new InvalidOperationException("The resolver " + this.GetType() + " can only accept types of " + typeof(TResolved) + ". The Type passed in to this method is " + t);
@@ -314,22 +378,22 @@ namespace Umbraco.Core.ObjectResolution
protected virtual bool SupportsAdd
{
get { return _supportsAdd; }
get { return true; }
}
protected virtual bool SupportsInsert
{
get { return _supportsInsert; }
get { return true; }
}
protected virtual bool SupportsClear
{
get { return _supportsClear; }
get { return true; }
}
protected virtual bool SupportsRemove
{
get { return _supportsRemove; }
get { return true; }
}
}
}
+2 -2
View File
@@ -8,14 +8,14 @@ namespace Umbraco.Core
/// <summary>
/// A resolver to return all IPackageAction objects
/// </summary>
internal sealed class PackageActionsResolver : ManyObjectsResolverBase<PackageActionsResolver, IPackageAction>
internal sealed class PackageActionsResolver : LazyManyObjectsResolverBase<PackageActionsResolver, IPackageAction>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="packageActions"></param>
internal PackageActionsResolver(IEnumerable<Type> packageActions)
internal PackageActionsResolver(Func<IEnumerable<Type>> packageActions)
: base(packageActions)
{
File diff suppressed because it is too large Load Diff
@@ -21,16 +21,7 @@ namespace Umbraco.Core.PropertyEditors
/// <returns></returns>
public Attempt<object> ConvertPropertyValue(object value)
{
if (value == null) return new Attempt<object>(false, null);
//if its already a DateTime
if (TypeHelper.IsTypeAssignableFrom<DateTime>(value))
return new Attempt<object>(true, value);
//convert to string
var asString = Convert.ToString(value);
DateTime dt;
return DateTime.TryParse(asString, out dt)
? new Attempt<object>(true, dt)
: new Attempt<object>(false, null);
return value.TryConvertTo(typeof(DateTime));
}
}
}
@@ -7,7 +7,7 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Manages the list of IPropertyEditorValueConverter's
/// </summary>
internal class PropertyEditorValueConvertersResolver : ManyObjectsResolverBase<PropertyEditorValueConvertersResolver, IPropertyEditorValueConverter>
internal sealed class PropertyEditorValueConvertersResolver : ManyObjectsResolverBase<PropertyEditorValueConvertersResolver, IPropertyEditorValueConverter>
{
public PropertyEditorValueConvertersResolver(IEnumerable<Type> converters)
: base(converters)
@@ -16,18 +16,7 @@ namespace Umbraco.Core.PropertyEditors
/// <returns></returns>
public Attempt<object> ConvertPropertyValue(object value)
{
if (value == null) return new Attempt<object>(false, null);
//if its already a bool
if (TypeHelper.IsTypeAssignableFrom<bool>(value))
return new Attempt<object>(true, value);
//convert to string
var asString = Convert.ToString(value);
bool asBool;
return bool.TryParse(asString, out asBool)
? new Attempt<object>(true, asBool)
: bool.TryParse(asString.Replace("1", "true").Replace("0", "false"), out asBool) //convert 0 or 1 to true or false
? new Attempt<object>(true, asBool)
: new Attempt<object>(false, null);
return value.TryConvertTo(typeof(bool));
}
}
}
+56 -19
View File
@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Mime;
using System.Web;
using Umbraco.Core.Dynamics;
using Umbraco.Core.Models;
using umbraco.interfaces;
@@ -14,6 +13,7 @@ namespace Umbraco.Core
/// </summary>
public static class PublishedContentExtensions
{
#region GetProperty
@@ -41,24 +41,33 @@ namespace Umbraco.Core
#endregion
#region GetPropertyValue
public static string GetPropertyValue(this IPublishedContent doc, string alias)
public static object GetPropertyValue(this IPublishedContent doc, string alias)
{
return doc.GetPropertyValue(alias, false);
}
public static string GetPropertyValue(this IPublishedContent doc, string alias, string fallback)
public static object GetPropertyValue(this IPublishedContent doc, string alias, string fallback)
{
var prop = doc.GetPropertyValue(alias);
return !prop.IsNullOrWhiteSpace() ? prop : fallback;
return (prop != null && !Convert.ToString(prop).IsNullOrWhiteSpace()) ? prop : fallback;
}
public static string GetPropertyValue(this IPublishedContent doc, string alias, bool recursive)
public static object GetPropertyValue(this IPublishedContent doc, string alias, bool recursive)
{
var p = doc.GetProperty(alias, recursive);
return p == null ? null : Convert.ToString(p.Value);
if (p == null) return null;
//Here we need to put the value through the IPropertyEditorValueConverter's
//get the data type id for the current property
var dataType = PublishedContentHelper.GetDataType(doc.DocumentTypeAlias, alias);
//convert the string value to a known type
var converted = PublishedContentHelper.ConvertPropertyValue(p.Value, dataType, doc.DocumentTypeAlias, alias);
return converted.Success
? converted.Result
: p.Value;
}
public static string GetPropertyValue(this IPublishedContent doc, string alias, bool recursive, string fallback)
public static object GetPropertyValue(this IPublishedContent doc, string alias, bool recursive, string fallback)
{
var prop = doc.GetPropertyValue(alias, recursive);
return !prop.IsNullOrWhiteSpace() ? prop : fallback;
return (prop != null && !Convert.ToString(prop).IsNullOrWhiteSpace()) ? prop : fallback;
}
#endregion
@@ -125,23 +134,51 @@ namespace Umbraco.Core
/// then the default value of type T is returned.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="prop"></param>
/// <param name="doc"></param>
/// <param name="alias"></param>
/// <returns></returns>
public static T GetPropertyValue<T>(this IPublishedContent prop, string alias)
public static T GetPropertyValue<T>(this IPublishedContent doc, string alias)
{
return prop.GetPropertyValue<T>(alias, default(T));
return doc.GetPropertyValue<T>(alias, default(T));
}
public static T GetPropertyValue<T>(this IPublishedContent prop, string alias, bool recursive, T ifCannotConvert)
{
var p = prop.GetProperty(alias, recursive);
if (p == null)
return ifCannotConvert;
//before we try to convert it manually, lets see if the PropertyEditorValueConverter does this for us
//Here we need to put the value through the IPropertyEditorValueConverter's
//get the data type id for the current property
var dataType = PublishedContentHelper.GetDataType(prop.DocumentTypeAlias, alias);
//convert the value to a known type
var converted = PublishedContentHelper.ConvertPropertyValue(p.Value, dataType, prop.DocumentTypeAlias, alias);
if (converted.Success)
{
//if its successful, check if its the correct type and return it
if (converted.Result is T)
{
return (T)converted.Result;
}
//if that's not correct, try converting the converted type
var reConverted = converted.Result.TryConvertTo<T>();
if (reConverted.Success)
{
return reConverted.Result;
}
}
//last, if all the above has failed, we'll just try converting the raw value straight to 'T'
var manualConverted = p.Value.TryConvertTo<T>();
if (manualConverted.Success)
return manualConverted.Result;
return ifCannotConvert;
}
public static T GetPropertyValue<T>(this IPublishedContent prop, string alias, T ifCannotConvert)
{
var p = prop.GetProperty(alias);
if (p == null)
return default(T);
var converted = p.Value.TryConvertTo<T>();
if (converted.Success)
return converted.Result;
return ifCannotConvert;
return prop.GetPropertyValue<T>(alias, false, ifCannotConvert);
}
}
+103
View File
@@ -0,0 +1,103 @@
using System;
using System.Linq;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Dynamics;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Core
{
internal class PublishedContentHelper
{
/// <summary>
/// This callback is used only so we can set it dynamically because in the "Core" project currently we don't have
/// access to the business logic layer.
/// TODO: Once 6.0 is released we need to change this to use the new business logic layer that we can access from
/// this proejct. Until then this will return a Guid.Empty but the callback will need to be set in the WebBootManager
/// to work in the website. if people use this in a non-web aspect without the WebBootManager, the the IPropertyEditorValueConverters
/// will not be executed.
/// </summary>
internal static Func<string, string, Guid> GetDataTypeCallback = (docTypeAlias, propertyAlias) => Guid.Empty;
internal static Guid GetDataType(string docTypeAlias, string propertyAlias)
{
return GetDataTypeCallback(docTypeAlias, propertyAlias);
}
/// <summary>
/// Converts the currentValue to a correctly typed value based on known registered converters, then based on known standards.
/// </summary>
/// <param name="currentValue"></param>
/// <param name="dataType"></param>
/// <param name="docTypeAlias"></param>
/// <param name="propertyTypeAlias"></param>
/// <returns></returns>
internal static Attempt<object> ConvertPropertyValue(object currentValue, Guid dataType, string docTypeAlias, string propertyTypeAlias)
{
if (currentValue == null) return Attempt<object>.False;
//First lets check all registered converters for this data type.
var converters = PropertyEditorValueConvertersResolver.Current.Converters
.Where(x => x.IsConverterFor(dataType, docTypeAlias, propertyTypeAlias))
.ToArray();
//try to convert the value with any of the converters:
foreach (var converted in converters
.Select(p => p.ConvertPropertyValue(currentValue))
.Where(converted => converted.Success))
{
return new Attempt<object>(true, converted.Result);
}
//if none of the converters worked, then we'll process this from what we know
var sResult = Convert.ToString(currentValue).Trim();
//this will eat csv strings, so only do it if the decimal also includes a decimal seperator (according to the current culture)
if (sResult.Contains(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator))
{
decimal dResult;
if (decimal.TryParse(sResult, System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.CurrentCulture, out dResult))
{
return new Attempt<object>(true, dResult);
}
}
//process string booleans as booleans
if (sResult.InvariantEquals("true"))
{
return new Attempt<object>(true, true);
}
if (sResult.InvariantEquals("false"))
{
return new Attempt<object>(true, false);
}
//a really rough check to see if this may be valid xml
//TODO: This is legacy code, I'm sure there's a better and nicer way
if (sResult.StartsWith("<") && sResult.EndsWith(">") && sResult.Contains("/"))
{
try
{
var e = XElement.Parse(DynamicXml.StripDashesInElementOrAttributeNames(sResult), LoadOptions.None);
//check that the document element is not one of the disallowed elements
//allows RTE to still return as html if it's valid xhtml
var documentElement = e.Name.LocalName;
//TODO: See note against this setting, pretty sure we don't need this
if (!UmbracoSettings.NotDynamicXmlDocumentElements.Any(
tag => string.Equals(tag, documentElement, StringComparison.CurrentCultureIgnoreCase)))
{
return new Attempt<object>(true, new DynamicXml(e));
}
return Attempt<object>.False;
}
catch (Exception)
{
return Attempt<object>.False;
}
}
return Attempt<object>.False;
}
}
}
+73 -9
View File
@@ -9,6 +9,7 @@ using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
namespace Umbraco.Core
{
@@ -18,6 +19,65 @@ namespace Umbraco.Core
///</summary>
public static class StringExtensions
{
/// <summary>
/// Encrypt the string using the MachineKey in medium trust
/// </summary>
/// <param name="value">The string value to be encrypted.</param>
/// <returns></returns>
public static string EncryptWithMachineKey(this string value)
{
if (value == null)
return null;
string valueToEncrypt = value;
List<string> parts = new List<string>();
const int EncrpytBlockSize = 500;
while (valueToEncrypt.Length > EncrpytBlockSize)
{
parts.Add(valueToEncrypt.Substring(0, EncrpytBlockSize));
valueToEncrypt = valueToEncrypt.Remove(0, EncrpytBlockSize);
}
if (valueToEncrypt.Length > 0)
{
parts.Add(valueToEncrypt);
}
StringBuilder encrpytedValue = new StringBuilder();
foreach (var part in parts)
{
var encrpytedBlock = FormsAuthentication.Encrypt(new FormsAuthenticationTicket(0, string.Empty, DateTime.Now, DateTime.MaxValue, false, part));
encrpytedValue.AppendLine(encrpytedBlock);
}
return encrpytedValue.ToString().TrimEnd();
}
/// <summary>
/// Decrypt the encrypted string using the Machine key in medium trust
/// </summary>
/// <param name="value">The string value to be decrypted</param>
/// <returns></returns>
public static string DecryptWithMachineKey(this string value)
{
if (value == null)
return null;
string[] parts = value.Split('\n');
StringBuilder decryptedValue = new StringBuilder();
foreach (var part in parts)
{
decryptedValue.Append(FormsAuthentication.Decrypt(part.TrimEnd()).UserData);
}
return decryptedValue.ToString();
}
//this is from SqlMetal and just makes it a bit of fun to allow pluralisation
public static string MakePluralName(this string name)
{
@@ -119,6 +179,8 @@ namespace Umbraco.Core
public static string TrimEnd(this string value, string forRemoving)
{
if (string.IsNullOrEmpty(value)) return value;
if (string.IsNullOrEmpty(forRemoving)) return value;
while (value.EndsWith(forRemoving, StringComparison.InvariantCultureIgnoreCase))
{
value = value.Remove(value.LastIndexOf(forRemoving, StringComparison.InvariantCultureIgnoreCase));
@@ -129,6 +191,8 @@ namespace Umbraco.Core
public static string TrimStart(this string value, string forRemoving)
{
if (string.IsNullOrEmpty(value)) return value;
if (string.IsNullOrEmpty(forRemoving)) return value;
while (value.StartsWith(forRemoving, StringComparison.InvariantCultureIgnoreCase))
{
value = value.Substring(forRemoving.Length);
@@ -144,22 +208,22 @@ namespace Umbraco.Core
public static string EnsureStartsWith(this string input, char value)
{
return input.StartsWith(value.ToString()) ? input : value + input;
return input.StartsWith(value.ToString(CultureInfo.InvariantCulture)) ? input : value + input;
}
public static string EnsureEndsWith(this string input, char value)
{
return input.EndsWith(value.ToString()) ? input : input + value;
return input.EndsWith(value.ToString(CultureInfo.InvariantCulture)) ? input : input + value;
}
public static bool IsLowerCase(this char ch)
{
return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToLower();
return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
}
public static bool IsUpperCase(this char ch)
{
return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToUpper();
return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToUpperInvariant();
}
/// <summary>Is null or white space.</summary>
@@ -267,7 +331,7 @@ namespace Umbraco.Core
Enumerable.Range(97, 26));
var sb = new StringBuilder();
foreach (var c in value.Where(c => charReplacements.Values.Contains(c.ToString()) || validCodeRanges.Contains(c)))
foreach (var c in value.Where(c => charReplacements.Values.Contains(c.ToString(CultureInfo.InvariantCulture)) || validCodeRanges.Contains(c)))
{
sb.Append(c);
}
@@ -328,7 +392,7 @@ namespace Umbraco.Core
{
if (splittedPhraseChars.Length > 0)
{
splittedPhraseChars[0] = ((new String(splittedPhraseChars[0], 1)).ToUpper().ToCharArray())[0];
splittedPhraseChars[0] = ((new String(splittedPhraseChars[0], 1)).ToUpperInvariant().ToCharArray())[0];
}
sb.Append(new String(splittedPhraseChars));
}
@@ -343,15 +407,15 @@ namespace Umbraco.Core
var match = pattern.Match(result);
if (match.Success)
{
result = match.Groups[1].Value.ToLower() + match.Groups[2].Value;
result = match.Groups[1].Value.ToLowerInvariant() + match.Groups[2].Value;
return result.Substring(0, 1).ToLower() + result.Substring(1);
return result.Substring(0, 1).ToLowerInvariant() + result.Substring(1);
}
return result;
}
return result.ToLower();
return result.ToLowerInvariant();
}
return result;
+16 -1
View File
@@ -12,6 +12,8 @@
<AssemblyName>Umbraco.Core</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -54,7 +56,7 @@
<Compile Include="AssemblyExtensions.cs" />
<Compile Include="Attempt.cs" />
<Compile Include="CacheHelper.cs" />
<Compile Include="CodeAnnotations\UmbracoDeprecateAttribute.cs" />
<Compile Include="CodeAnnotations\UmbracoWillObsoleteAttribute.cs" />
<Compile Include="CodeAnnotations\UmbracoExperimentalFeatureAttribute.cs" />
<Compile Include="CodeAnnotations\UmbracoProposedPublicAttribute.cs" />
<Compile Include="Configuration\FileSystemProviderElement.cs" />
@@ -65,8 +67,14 @@
<Compile Include="DictionaryExtensions.cs" />
<Compile Include="Dictionary\CultureDictionaryFactoryResolver.cs" />
<Compile Include="Dictionary\ICultureDictionaryFactory.cs" />
<Compile Include="Dynamics\DynamicInstanceHelper.cs" />
<Compile Include="Enum.cs" />
<Compile Include="Events\MacroErrorEventArgs.cs" />
<Compile Include="HashCodeCombiner.cs" />
<Compile Include="IO\FileSystemWrapper.cs" />
<Compile Include="MacroErrorBehaviour.cs" />
<Compile Include="Media\IImageUrlProvider.cs" />
<Compile Include="ObjectResolution\LazyManyObjectsResolverbase.cs" />
<Compile Include="PublishedContentExtensions.cs" />
<Compile Include="Dictionary\ICultureDictionary.cs" />
<Compile Include="Dynamics\ClassFactory.cs" />
@@ -124,6 +132,7 @@
<Compile Include="ObjectResolution\Resolution.cs" />
<Compile Include="ObjectResolution\ResolverBase.cs" />
<Compile Include="ObjectResolution\SingleObjectResolverBase.cs" />
<Compile Include="PublishedContentHelper.cs" />
<Compile Include="RenderingEngine.cs" />
<Compile Include="TypeExtensions.cs" />
<Compile Include="ReadLock.cs" />
@@ -157,6 +166,11 @@
<Compile Include="WriteLock.cs" />
<Compile Include="XmlExtensions.cs" />
<Compile Include="XmlHelper.cs" />
<Compile Include="Xml\DynamicContext.cs" />
<Compile Include="Xml\XmlNamespaces.cs" />
<Compile Include="Xml\XmlNodeListFactory.cs" />
<Compile Include="Xml\XmlNodeExtensions.cs" />
<Compile Include="Xml\XPathVariable.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
@@ -169,6 +183,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
+312
View File
@@ -0,0 +1,312 @@
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
// source: mvpxml.codeplex.com
namespace Umbraco.Core.Xml
{
/// <summary>
/// Provides the evaluation context for fast execution and custom
/// variables resolution.
/// </summary>
/// <remarks>
/// This class is responsible for resolving variables during dynamic expression execution.
/// <para>Discussed in http://weblogs.asp.net/cazzu/archive/2003/10/07/30888.aspx</para>
/// <para>Author: Daniel Cazzulino, <a href="http://clariusconsulting.net/kzu">blog</a></para>
/// </remarks>
public class DynamicContext : XsltContext
{
#region Private vars
readonly IDictionary<string, IXsltContextVariable> _variables =
new Dictionary<string, IXsltContextVariable>();
#endregion Private
#region Constructors & Initialization
/// <summary>
/// Initializes a new instance of the <see cref="DynamicContext"/> class.
/// </summary>
public DynamicContext()
: base(new NameTable())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DynamicContext"/>
/// class with the specified <see cref="NameTable"/>.
/// </summary>
/// <param name="table">The NameTable to use.</param>
public DynamicContext(NameTable table)
: base(table)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DynamicContext"/> class.
/// </summary>
/// <param name="context">A previously filled context with the namespaces to use.</param>
public DynamicContext(XmlNamespaceManager context)
: this(context, new NameTable())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DynamicContext"/> class.
/// </summary>
/// <param name="context">A previously filled context with the namespaces to use.</param>
/// <param name="table">The NameTable to use.</param>
public DynamicContext(XmlNamespaceManager context, NameTable table)
: base(table)
{
object xml = table.Add(XmlNamespaces.Xml);
object xmlns = table.Add(XmlNamespaces.XmlNs);
if (context == null) return;
foreach (string prefix in context)
{
var uri = context.LookupNamespace(prefix);
// Use fast object reference comparison to omit forbidden namespace declarations.
if (Equals(uri, xml) || Equals(uri, xmlns))
continue;
if (uri == null)
continue;
base.AddNamespace(prefix, uri);
}
}
#endregion Constructors & Initialization
#region Common Overrides
/// <summary>
/// Implementation equal to <see cref="XsltContext"/>.
/// </summary>
public override int CompareDocument(string baseUri, string nextbaseUri)
{
return String.Compare(baseUri, nextbaseUri, false, System.Globalization.CultureInfo.InvariantCulture);
}
/// <summary>
/// Same as <see cref="XmlNamespaceManager"/>.
/// </summary>
public override string LookupNamespace(string prefix)
{
var key = NameTable.Get(prefix);
return key == null ? null : base.LookupNamespace(key);
}
/// <summary>
/// Same as <see cref="XmlNamespaceManager"/>.
/// </summary>
public override string LookupPrefix(string uri)
{
var key = NameTable.Get(uri);
return key == null ? null : base.LookupPrefix(key);
}
/// <summary>
/// Same as <see cref="XsltContext"/>.
/// </summary>
public override bool PreserveWhitespace(XPathNavigator node)
{
return true;
}
/// <summary>
/// Same as <see cref="XsltContext"/>.
/// </summary>
public override bool Whitespace
{
get { return true; }
}
#endregion Common Overrides
#region Public Members
/// <summary>
/// Shortcut method that compiles an expression using an empty navigator.
/// </summary>
/// <param name="xpath">The expression to compile</param>
/// <returns>A compiled <see cref="XPathExpression"/>.</returns>
public static XPathExpression Compile(string xpath)
{
return new XmlDocument().CreateNavigator().Compile(xpath);
}
#endregion Public Members
#region Variable Handling Code
/// <summary>
/// Adds the variable to the dynamic evaluation context.
/// </summary>
/// <param name="name">The name of the variable to add to the context.</param>
/// <param name="value">The value of the variable to add to the context.</param>
/// <remarks>
/// Value type conversion for XPath evaluation is as follows:
/// <list type="table">
/// <listheader>
/// <term>CLR Type</term>
/// <description>XPath type</description>
/// </listheader>
/// <item>
/// <term>System.String</term>
/// <description>XPathResultType.String</description>
/// </item>
/// <item>
/// <term>System.Double (or types that can be converted to)</term>
/// <description>XPathResultType.Number</description>
/// </item>
/// <item>
/// <term>System.Boolean</term>
/// <description>XPathResultType.Boolean</description>
/// </item>
/// <item>
/// <term>System.Xml.XPath.XPathNavigator</term>
/// <description>XPathResultType.Navigator</description>
/// </item>
/// <item>
/// <term>System.Xml.XPath.XPathNodeIterator</term>
/// <description>XPathResultType.NodeSet</description>
/// </item>
/// <item>
/// <term>Others</term>
/// <description>XPathResultType.Any</description>
/// </item>
/// </list>
/// <note type="note">See the topic "Compile, Select, Evaluate, and Matches with
/// XPath and XPathExpressions" in MSDN documentation for additional information.</note>
/// </remarks>
/// <exception cref="ArgumentNullException">The <paramref name="value"/> is null.</exception>
public void AddVariable(string name, object value)
{
if (value == null) throw new ArgumentNullException("value");
_variables[name] = new DynamicVariable(name, value);
}
/// <summary>
/// See <see cref="XsltContext"/>. Not used in our implementation.
/// </summary>
public override IXsltContextFunction ResolveFunction(string prefix, string name, XPathResultType[] argTypes)
{
return null;
}
/// <summary>
/// Resolves the dynamic variables added to the context. See <see cref="XsltContext"/>.
/// </summary>
public override IXsltContextVariable ResolveVariable(string prefix, string name)
{
IXsltContextVariable var;
_variables.TryGetValue(name, out var);
return var;
}
#endregion Variable Handling Code
#region Internal DynamicVariable class
/// <summary>
/// Represents a variable during dynamic expression execution.
/// </summary>
internal class DynamicVariable : IXsltContextVariable
{
readonly string _name;
readonly object _value;
#region Public Members
public string Name { get { return _name; } }
/// <summary>
/// Initializes a new instance of the class.
/// </summary>
/// <param name="name">The name of the variable.</param>
/// <param name="value">The value of the variable.</param>
public DynamicVariable(string name, object value)
{
_name = name;
_value = value;
if (value is String)
_type = XPathResultType.String;
else if (value is bool)
_type = XPathResultType.Boolean;
else if (value is XPathNavigator)
_type = XPathResultType.Navigator;
else if (value is XPathNodeIterator)
_type = XPathResultType.NodeSet;
else
{
// Try to convert to double (native XPath numeric type)
if (value is double)
{
_type = XPathResultType.Number;
}
else
{
if (value is IConvertible)
{
try
{
_value = Convert.ToDouble(value);
// We suceeded, so it's a number.
_type = XPathResultType.Number;
}
catch (FormatException)
{
_type = XPathResultType.Any;
}
catch (OverflowException)
{
_type = XPathResultType.Any;
}
}
else
{
_type = XPathResultType.Any;
}
}
}
}
#endregion Public Members
#region IXsltContextVariable Implementation
XPathResultType IXsltContextVariable.VariableType
{
get { return _type; }
}
readonly XPathResultType _type;
object IXsltContextVariable.Evaluate(XsltContext context)
{
return _value;
}
bool IXsltContextVariable.IsLocal
{
get { return false; }
}
bool IXsltContextVariable.IsParam
{
get { return false; }
}
#endregion IXsltContextVariable Implementation
}
#endregion Internal DynamicVariable class
}
}
+16
View File
@@ -0,0 +1,16 @@
// source: mvpxml.codeplex.com
namespace Umbraco.Core.Xml
{
internal class XPathVariable
{
public string Name { get; set; }
public string Value { get; set; }
public XPathVariable(string name, string value)
{
Name = name;
Value = value;
}
}
}
+41
View File
@@ -0,0 +1,41 @@
// source: mvpxml.codeplex.com
namespace Umbraco.Core.Xml
{
/// <summary>
/// Provides public constants for wellknown XML namespaces.
/// </summary>
/// <remarks>Author: Daniel Cazzulino, <a href="http://clariusconsulting.net/kzu">blog</a></remarks>
public static class XmlNamespaces
{
/// <summary>
/// The public XML 1.0 namespace.
/// </summary>
/// <remarks>See http://www.w3.org/TR/2004/REC-xml-20040204/</remarks>
public const string Xml = "http://www.w3.org/XML/1998/namespace";
/// <summary>
/// Public Xml Namespaces specification namespace.
/// </summary>
/// <remarks>See http://www.w3.org/TR/REC-xml-names/</remarks>
public const string XmlNs = "http://www.w3.org/2000/xmlns/";
/// <summary>
/// Public Xml Namespaces prefix.
/// </summary>
/// <remarks>See http://www.w3.org/TR/REC-xml-names/</remarks>
public const string XmlNsPrefix = "xmlns";
/// <summary>
/// XML Schema instance namespace.
/// </summary>
/// <remarks>See http://www.w3.org/TR/xmlschema-1/</remarks>
public const string Xsi = "http://www.w3.org/2001/XMLSchema-instance";
/// <summary>
/// XML 1.0 Schema namespace.
/// </summary>
/// <remarks>See http://www.w3.org/TR/xmlschema-1/</remarks>
public const string Xsd = "http://www.w3.org/2001/XMLSchema";
}
}
+51
View File
@@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.XPath;
// source: mvpxml.codeplex.com
namespace Umbraco.Core.Xml
{
internal static class XmlNodeExtensions
{
static XPathNodeIterator Select(string expression, XPathNavigator source, params XPathVariable[] variables)
{
var expr = source.Compile(expression);
var context = new DynamicContext();
foreach (var variable in variables)
context.AddVariable(variable.Name, variable.Value);
expr.SetContext(context);
return source.Select(expr);
}
public static XmlNodeList SelectNodes(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
{
var av = variables == null ? null : variables.ToArray();
return SelectNodes(source, expression, av);
}
public static XmlNodeList SelectNodes(this XmlNode source, string expression, params XPathVariable[] variables)
{
if (variables == null || variables.Length == 0 || variables[0] == null)
return source.SelectNodes(expression);
var iterator = Select(expression, source.CreateNavigator(), variables);
return XmlNodeListFactory.CreateNodeList(iterator);
}
public static XmlNode SelectSingleNode(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
{
var av = variables == null ? null : variables.ToArray();
return SelectSingleNode(source, expression, av);
}
public static XmlNode SelectSingleNode(this XmlNode source, string expression, params XPathVariable[] variables)
{
if (variables == null || variables.Length == 0 || variables[0] == null)
return source.SelectSingleNode(expression);
return SelectNodes(source, expression, variables).Cast<XmlNode>().FirstOrDefault();
}
}
}
+178
View File
@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.XPath;
// source: mvpxml.codeplex.com
namespace Umbraco.Core.Xml
{
class XmlNodeListFactory
{
private XmlNodeListFactory() { }
#region Public members
/// <summary>
/// Creates an instance of a <see cref="XmlNodeList"/> that allows
/// enumerating <see cref="XmlNode"/> elements in the iterator.
/// </summary>
/// <param name="iterator">The result of a previous node selection
/// through an <see cref="XPathNavigator"/> query.</param>
/// <returns>An initialized list ready to be enumerated.</returns>
/// <remarks>The underlying XML store used to issue the query must be
/// an object inheriting <see cref="XmlNode"/>, such as
/// <see cref="XmlDocument"/>.</remarks>
public static XmlNodeList CreateNodeList(XPathNodeIterator iterator)
{
return new XmlNodeListIterator(iterator);
}
#endregion Public members
#region XmlNodeListIterator
private class XmlNodeListIterator : XmlNodeList
{
readonly XPathNodeIterator _iterator;
readonly IList<XmlNode> _nodes = new List<XmlNode>();
public XmlNodeListIterator(XPathNodeIterator iterator)
{
_iterator = iterator.Clone();
}
public override System.Collections.IEnumerator GetEnumerator()
{
return new XmlNodeListEnumerator(this);
}
public override XmlNode Item(int index)
{
if (index >= _nodes.Count)
ReadTo(index);
// Compatible behavior with .NET
if (index >= _nodes.Count || index < 0)
return null;
return _nodes[index];
}
public override int Count
{
get
{
if (!_done) ReadToEnd();
return _nodes.Count;
}
}
/// <summary>
/// Reads the entire iterator.
/// </summary>
private void ReadToEnd()
{
while (_iterator.MoveNext())
{
var node = _iterator.Current as IHasXmlNode;
// Check IHasXmlNode interface.
if (node == null)
throw new ArgumentException("IHasXmlNode is missing.");
_nodes.Add(node.GetNode());
}
_done = true;
}
/// <summary>
/// Reads up to the specified index, or until the
/// iterator is consumed.
/// </summary>
private void ReadTo(int to)
{
while (_nodes.Count <= to)
{
if (_iterator.MoveNext())
{
var node = _iterator.Current as IHasXmlNode;
// Check IHasXmlNode interface.
if (node == null)
throw new ArgumentException("IHasXmlNode is missing.");
_nodes.Add(node.GetNode());
}
else
{
_done = true;
return;
}
}
}
/// <summary>
/// Flags that the iterator has been consumed.
/// </summary>
private bool Done
{
get { return _done; }
}
bool _done;
/// <summary>
/// Current count of nodes in the iterator (read so far).
/// </summary>
private int CurrentPosition
{
get { return _nodes.Count; }
}
#region XmlNodeListEnumerator
private class XmlNodeListEnumerator : System.Collections.IEnumerator
{
readonly XmlNodeListIterator _iterator;
int _position = -1;
public XmlNodeListEnumerator(XmlNodeListIterator iterator)
{
_iterator = iterator;
}
#region IEnumerator Members
void System.Collections.IEnumerator.Reset()
{
_position = -1;
}
bool System.Collections.IEnumerator.MoveNext()
{
_position++;
_iterator.ReadTo(_position);
// If we reached the end and our index is still
// bigger, there're no more items.
if (_iterator.Done && _position >= _iterator.CurrentPosition)
return false;
return true;
}
object System.Collections.IEnumerator.Current
{
get
{
return _iterator[_position];
}
}
#endregion
}
#endregion XmlNodeListEnumerator
}
#endregion XmlNodeListIterator
}
}
@@ -26,6 +26,7 @@ namespace Umbraco.Tests.BusinessLogic
CreateNew();
}
[Ignore]
[Test()]
public void Dictionary_Get_Top_Level_Items()
{
@@ -42,6 +43,7 @@ namespace Umbraco.Tests.BusinessLogic
/// Creates a new dictionary entry, adds values for all languages assigned, then deletes the
/// entry and ensure that all other data is gone too.
///</summary>
[Ignore]
[Test()]
public void Dictionary_Create_Add_Text_And_Delete()
{
@@ -64,6 +66,7 @@ namespace Umbraco.Tests.BusinessLogic
/// <summary>
///A test for IsTopMostItem
///</summary>
[Ignore]
[Test()]
public void Dictionary_IsTopMostItem()
{
@@ -85,6 +88,7 @@ namespace Umbraco.Tests.BusinessLogic
/// <summary>
/// Test the Parent and Children properties and ensures that the relationships work both ways
///</summary>
[Ignore]
[Test()]
public void Dictionary_Parent_Child_Relationship()
{
@@ -115,6 +119,7 @@ namespace Umbraco.Tests.BusinessLogic
/// <summary>
/// Deletes a parent with existing children and ensures they are all gone.
/// </summary>
[Ignore]
[Test()]
public void Dictionary_Delete_Parent_With_Children()
{
@@ -166,6 +171,7 @@ namespace Umbraco.Tests.BusinessLogic
/// <summary>
/// Guid constructor test
///</summary>
[Ignore]
[Test()]
public void Dictionary_Contructor_Guid()
{
@@ -183,6 +189,7 @@ namespace Umbraco.Tests.BusinessLogic
/// <summary>
/// key constructor test
/// </summary>
[Ignore]
[Test()]
public void Dictionary_Contructor_Key()
{
@@ -200,6 +207,7 @@ namespace Umbraco.Tests.BusinessLogic
/// <summary>
///A test for ToXml
///</summary>
[Ignore]
[Test()]
public void Dictionary_ToXml()
{
@@ -227,6 +235,7 @@ namespace Umbraco.Tests.BusinessLogic
/// <summary>
///A test to change the key of an element
///</summary>
[Ignore]
[Test()]
public void Dictionary_Change_Key()
{
@@ -17,7 +17,7 @@ namespace Umbraco.Tests
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager();
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
@@ -26,7 +26,7 @@ namespace Umbraco.Tests
};
CacheRefreshersResolver.Current = new CacheRefreshersResolver(
PluginManager.Current.ResolveCacheRefreshers());
() => PluginManager.Current.ResolveCacheRefreshers());
Resolution.Freeze();
}
@@ -2,6 +2,7 @@ using System.Linq;
using System.Xml;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Routing;
@@ -54,6 +55,8 @@ namespace Umbraco.Tests.ContentStores
</Home>
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""1045"" sortOrder=""2"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
</Home>
<Home id=""1177"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""1045"" sortOrder=""2"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub'Apostrophe"" urlName=""sub'apostrophe"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1177"" isDoc=""""><content><![CDATA[]]></content>
</Home>
</Home>
<Home id=""1172"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""1045"" sortOrder=""3"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test"" writerName=""admin"" creatorName=""admin"" path=""-1,1172"" isDoc="""" />
</root>";
@@ -63,7 +66,7 @@ namespace Umbraco.Tests.ContentStores
public void SetUp()
{
TestHelper.SetupLog4NetForTests();
Umbraco.Core.Configuration.UmbracoSettings.UseLegacyXmlSchema = false;
_httpContextFactory = new FakeHttpContextFactory("~/Home");
//ensure the StateHelper is using our custom context
StateHelper.HttpContext = _httpContextFactory.HttpContext;
@@ -103,9 +106,7 @@ namespace Umbraco.Tests.ContentStores
[TearDown]
public void TearDown()
{
//TODO: need to reset everything!
Umbraco.Core.Configuration.UmbracoSettings.UseLegacyXmlSchema = false;
UmbracoSettings.ResetSetters();
}
[Test]
@@ -155,6 +156,7 @@ namespace Umbraco.Tests.ContentStores
[TestCase("/home/sub1", 1173)]
[TestCase("/Home/sub1", 1173)]
[TestCase("/home/Sub1", 1173)] //test different cases
[TestCase("/home/Sub'Apostrophe", 1177)]
public void Get_Node_By_Route(string route, int nodeId)
{
var result = _publishedContentStore.GetDocumentByRoute(_umbracoContext, route, false);
@@ -1,18 +1,82 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using Examine;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Tests.PublishedContent;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using umbraco.BusinessLogic;
namespace Umbraco.Tests
namespace Umbraco.Tests.ContentStores
{
[TestFixture]
public class PublishMediaStoreTests
public class PublishMediaStoreTests : PublishedContentTestBase
{
public override void Initialize()
{
base.Initialize();
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
File.Copy(
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
.First()
.GetDirectories("config").First()
.GetFiles("umbracoSettings.Release.config").First().FullName,
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
true);
}
public override void TearDown()
{
base.TearDown();
}
[Test]
public void Get_Root_Docs()
{
var user = new User(0);
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
var mRoot1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot1", mType, user, -1);
var mRoot2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot2", mType, user, -1);
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot1.Id);
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot2.Id);
var ctx = GetUmbracoContext("/test", 1234);
var mediaStore = new DefaultPublishedMediaStore();
var roots = mediaStore.GetRootDocuments(ctx);
Assert.AreEqual(2, roots.Count());
Assert.IsTrue(roots.Select(x => x.Id).ContainsAll(new[] {mRoot1.Id, mRoot2.Id}));
}
[Test]
public void Get_Item_Without_Examine()
{
var user = new User(0);
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
var publishedMedia = PublishedMediaTests.GetNode(mRoot.Id, GetUmbracoContext("/test", 1234));
Assert.AreEqual(mRoot.Id, publishedMedia.Id);
Assert.AreEqual(mRoot.CreateDateTime.ToString("dd/MM/yyyy HH:mm:ss"), publishedMedia.CreateDate.ToString("dd/MM/yyyy HH:mm:ss"));
Assert.AreEqual(mRoot.User.Id, publishedMedia.CreatorId);
Assert.AreEqual(mRoot.User.Name, publishedMedia.CreatorName);
Assert.AreEqual(mRoot.ContentType.Alias, publishedMedia.DocumentTypeAlias);
Assert.AreEqual(mRoot.ContentType.Id, publishedMedia.DocumentTypeId);
Assert.AreEqual(mRoot.Level, publishedMedia.Level);
Assert.AreEqual(mRoot.Text, publishedMedia.Name);
Assert.AreEqual(mRoot.Path, publishedMedia.Path);
Assert.AreEqual(mRoot.sortOrder, publishedMedia.SortOrder);
Assert.IsNull(publishedMedia.Parent);
}
[TestCase("id")]
[TestCase("nodeId")]
[TestCase("__NodeId")]
@@ -191,10 +255,12 @@ namespace Umbraco.Tests
a => null,
//we're not going to test this so ignore
a => new List<IPublishedContent>(),
(dd, a) => dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(a))),
(dd, a) => dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(a)),
false),
//callback to get the children
d => children,
(dd, a) => dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(a)));
(dd, a) => dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(a)),
false);
return dicDoc;
}
+2 -2
View File
@@ -19,7 +19,7 @@ namespace Umbraco.Tests
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager();
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
@@ -28,7 +28,7 @@ namespace Umbraco.Tests
};
DataTypesResolver.Current = new DataTypesResolver(
PluginManager.Current.ResolveDataTypes());
() => PluginManager.Current.ResolveDataTypes());
Resolution.Freeze();
}
@@ -1,639 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Dynamics;
using Umbraco.Core.Models;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.DynamicDocument
{
[TestFixture]
public abstract class DynamicDocumentTestsBase<TDocument, TDocumentList> : BaseRoutingTest
{
public override void Initialize()
{
base.Initialize();
}
public override void TearDown()
{
base.TearDown();
}
protected override bool RequiresDbSetup
{
get { return false; }
}
protected override string GetXmlContent(int templateId)
{
return @"<?xml version=""1.0"" encoding=""utf-8""?>
<!DOCTYPE root[
<!ELEMENT Home ANY>
<!ATTLIST Home id ID #REQUIRED>
<!ELEMENT CustomDocument ANY>
<!ATTLIST CustomDocument id ID #REQUIRED>
]>
<root id=""-1"">
<Home id=""1046"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Home"" urlName=""home"" writerName=""admin"" creatorName=""admin"" path=""-1,1046"" isDoc="""">
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[this/is/my/alias, anotheralias]]></umbracoUrlAlias>
<umbracoNaviHide>1</umbracoNaviHide>
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
<content><![CDATA[<div>This is some content</div>]]></content>
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
<creatorName><![CDATA[Custom data with same property name as the member name]]></creatorName>
</Home>
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc="""">
<content><![CDATA[some content]]></content>
<blah><![CDATA[some content]]></blah>
</Home>
<CustomDocument id=""1177"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""custom sub 1"" urlName=""custom-sub-1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1177"" isDoc="""" />
<CustomDocument id=""1178"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-16T14:23:35"" nodeName=""custom sub 2"" urlName=""custom-sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1178"" isDoc="""" />
</Home>
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
</Home>
<CustomDocument id=""4444"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444"" isDoc="""">
<selectedNodes><![CDATA[1172,1176,1173]]></selectedNodes>
<CustomDocument id=""5555"" parentID=""1046"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""0"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444,5555"" isDoc="""">
</CustomDocument>
</CustomDocument>
</Home>
<CustomDocument id=""1172"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1172"" isDoc="""" />
</root>";
}
/// <summary>
/// Returns the dynamic node/document to run tests against
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
protected abstract dynamic GetDynamicNode(int id);
[Test]
public void Single()
{
var doc = GetDynamicNode(4444);
var result = doc.Children().Single();
Assert.IsNotNull(result);
Assert.AreEqual(5555, result.Id);
}
[Test]
public void Single_With_Query()
{
var doc = GetDynamicNode(1046);
var result = doc.Children().Single("id==1175");
Assert.IsNotNull(result);
Assert.AreEqual(1175, result.Id);
}
[Test]
public void First()
{
var doc = GetDynamicNode(1173);
var result = doc.Children().First();
Assert.IsNotNull(result);
Assert.AreEqual(1174, result.Id);
}
[Test]
public void First_With_Query()
{
var doc = GetDynamicNode(1173);
var result = doc.Children().First("blah==\"some content\"");
Assert.IsNotNull(result);
Assert.AreEqual(1176, result.Id);
}
[Test]
public void Where_User_Property_Value()
{
var doc = GetDynamicNode(1173);
var result = (IEnumerable<dynamic>)doc.Children().Where("blah==\"some content\"");
Assert.IsNotNull(result);
Assert.AreEqual(1, result.Count());
Assert.AreEqual(1176, result.Single().Id);
}
[Test]
public void String_ContainsValue_Extension_Method()
{
var doc = GetDynamicNode(1046);
var paramVals = new Dictionary<string, object> { { "searchId", 1173 } }; //this is an integer value
var result = doc.Children()
.Where("selectedNodes.ContainsValue(searchId)", paramVals) //call an extension method
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.AreEqual(4444, result.Id);
//don't find!
paramVals = new Dictionary<string, object> { { "searchId", 1111777 } };
result = doc.Children()
.Where("selectedNodes.ContainsValue(searchId)", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.IsTrue(result.GetType() == typeof(DynamicNull) || result.GetType() == typeof(umbraco.MacroEngines.DynamicNull));
//Assert.AreEqual(typeof(DynamicNull), result.GetType());
}
[Test]
public void String_Contains_Method()
{
var doc = GetDynamicNode(1046);
var paramVals = new Dictionary<string, object> { { "searchId", "1173" } };
var result = doc.Children()
.Where("selectedNodes.Contains(searchId)", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.AreEqual(4444, result.Id);
//don't find!
paramVals = new Dictionary<string, object> { { "searchId", "1aaa173" } };
result = doc.Children()
.Where("selectedNodes.Contains(searchId)", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.IsTrue(result.GetType() == typeof (DynamicNull) || result.GetType() == typeof (umbraco.MacroEngines.DynamicNull));
//Assert.AreEqual(typeof (DynamicNull), result.GetType());
}
[Test]
public void String_Split_Method()
{
var doc = GetDynamicNode(1046);
var paramVals = new Dictionary<string, object>
{
{ "splitTerm", new char[] { ',' } },
{ "splitOptions", StringSplitOptions.RemoveEmptyEntries }
};
var result = doc.Children()
.Where("selectedNodes.Split(splitTerm, splitOptions).Length == 3", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.AreEqual(4444, result.Id);
}
[Test]
public void Complex_Linq()
{
var doc = GetDynamicNode(1173);
var paramVals = new Dictionary<string, object> {{"splitTerm", new char[] {','}}, {"searchId", "1173"}};
var result = doc.Ancestors().OrderBy("level")
.Single()
.Descendants()
.Where("selectedNodes != null && selectedNodes != String.Empty && selectedNodes.Split(splitTerm).Contains(searchId)", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.AreEqual(4444, result.Id);
}
[Test]
public void Index()
{
var doc = GetDynamicNode(1173);
Assert.AreEqual(0, doc.Index());
doc = GetDynamicNode(1176);
Assert.AreEqual(1, doc.Index());
doc = GetDynamicNode(1177);
Assert.AreEqual(2, doc.Index());
doc = GetDynamicNode(1178);
Assert.AreEqual(3, doc.Index());
}
[Test]
public void Is_First()
{
var doc = GetDynamicNode(1046); //test root nodes
Assert.IsTrue(doc.IsFirst());
doc = GetDynamicNode(1172);
Assert.IsFalse(doc.IsFirst());
doc = GetDynamicNode(1173); //test normal nodes
Assert.IsTrue(doc.IsFirst());
doc = GetDynamicNode(1175);
Assert.IsFalse(doc.IsFirst());
}
[Test]
public void Is_Not_First()
{
var doc = GetDynamicNode(1046); //test root nodes
Assert.IsFalse(doc.IsNotFirst());
doc = GetDynamicNode(1172);
Assert.IsTrue(doc.IsNotFirst());
doc = GetDynamicNode(1173); //test normal nodes
Assert.IsFalse(doc.IsNotFirst());
doc = GetDynamicNode(1175);
Assert.IsTrue(doc.IsNotFirst());
}
[Test]
public void Is_Position()
{
var doc = GetDynamicNode(1046); //test root nodes
Assert.IsTrue(doc.IsPosition(0));
doc = GetDynamicNode(1172);
Assert.IsTrue(doc.IsPosition(1));
doc = GetDynamicNode(1173); //test normal nodes
Assert.IsTrue(doc.IsPosition(0));
doc = GetDynamicNode(1175);
Assert.IsTrue(doc.IsPosition(1));
}
[Test]
public void Children_GroupBy_DocumentTypeAlias()
{
var doc = GetDynamicNode(1046);
var found1 = doc.Children.GroupBy("DocumentTypeAlias");
var casted = (IEnumerable<IGrouping<object, dynamic>>)(found1);
Assert.AreEqual(2, casted.Count());
Assert.AreEqual(2, casted.Single(x => x.Key.ToString() == "Home").Count());
Assert.AreEqual(1, casted.Single(x => x.Key.ToString() == "CustomDocument").Count());
}
[Test]
public void Children_Where_DocumentTypeAlias()
{
var doc = GetDynamicNode(1046);
var found1 = doc.Children.Where("DocumentTypeAlias == \"CustomDocument\"");
var found2 = doc.Children.Where("DocumentTypeAlias == \"Home\"");
Assert.AreEqual(1, found1.Count());
Assert.AreEqual(2, found2.Count());
}
[Test]
public void Children_Where_NodeTypeAlias()
{
var doc = GetDynamicNode(1046);
var found1 = doc.Children.Where("NodeTypeAlias == \"CustomDocument\"");
var found2 = doc.Children.Where("NodeTypeAlias == \"Home\"");
Assert.AreEqual(1, found1.Count());
Assert.AreEqual(2, found2.Count());
}
[Test]
public void Children_Order_By_Update_Date()
{
var asDynamic = GetDynamicNode(1173);
var ordered = asDynamic.Children.OrderBy("UpdateDate");
var casted = (IEnumerable<TDocument>)ordered;
var correctOrder = new[] { 1178, 1177, 1174, 1176 };
for (var i = 0; i < correctOrder.Length ;i++)
{
Assert.AreEqual(correctOrder[i], ((dynamic)casted.ElementAt(i)).Id);
}
}
[Test]
public void Children_Order_By_Update_Date_Descending()
{
var asDynamic = GetDynamicNode(1173);
var ordered = asDynamic.Children.OrderBy("UpdateDate desc");
var casted = (IEnumerable<TDocument>)ordered;
var correctOrder = new[] { 1176, 1174, 1177, 1178 };
for (var i = 0; i < correctOrder.Length; i++)
{
Assert.AreEqual(correctOrder[i], ((dynamic)casted.ElementAt(i)).Id);
}
}
[Test]
public void HasProperty()
{
var asDynamic = GetDynamicNode(1173);
var hasProp = asDynamic.HasProperty("umbracoUrlAlias");
Assert.AreEqual(true, (bool)hasProp);
}
[Test]
public void Skip()
{
var asDynamic = GetDynamicNode(1173);
var skip = asDynamic.Children.Skip(2);
var casted = (IEnumerable<TDocument>)skip;
Assert.AreEqual(2, casted.Count());
Assert.IsTrue(casted.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[]{1177, 1178}));
}
[Test]
public void HasValue()
{
var asDynamic = GetDynamicNode(1173);
var hasValue = asDynamic.HasValue("umbracoUrlAlias");
var noValue = asDynamic.HasValue("blahblahblah");
Assert.IsTrue(hasValue);
Assert.IsFalse(noValue);
}
[Test]
public void Take()
{
var asDynamic = GetDynamicNode(1173);
var take = asDynamic.Children.Take(2);
var casted = (IEnumerable<TDocument>)take;
Assert.AreEqual(2, casted.Count());
Assert.IsTrue(casted.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1176 }));
}
[Test]
public void Ancestors_Where_Visible()
{
var asDynamic = GetDynamicNode(1174);
var whereVisible = asDynamic.Ancestors().Where("Visible");
var casted = (IEnumerable<TDocument>)whereVisible;
Assert.AreEqual(1, casted.Count());
}
[Test]
public void Visible()
{
var asDynamicHidden = GetDynamicNode(1046);
var asDynamicVisible = GetDynamicNode(1173);
Assert.IsFalse(asDynamicHidden.Visible);
Assert.IsTrue(asDynamicVisible.Visible);
}
[Test]
public void Ensure_TinyMCE_Converted_Type_User_Property()
{
var asDynamic = GetDynamicNode(1173);
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(asDynamic.Content.GetType()));
Assert.AreEqual("<div>This is some content</div>", asDynamic.Content.ToString());
}
[Test]
public void Get_Children_With_Pluralized_Alias()
{
var asDynamic = GetDynamicNode(1173);
Action<object> doAssert = d =>
{
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(d));
var casted = (IEnumerable<TDocument>)d;
Assert.AreEqual(2, casted.Count());
};
doAssert(asDynamic.Homes); //pluralized alias
doAssert(asDynamic.homes); //pluralized alias
doAssert(asDynamic.CustomDocuments); //pluralized alias
doAssert(asDynamic.customDocuments); //pluralized alias
}
[Test]
public void GetPropertyValue_Non_Reflected()
{
var asDynamic = GetDynamicNode(1174);
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.GetPropertyValue("creatorName"));
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.GetPropertyValue("CreatorName"));
}
[Test]
public void GetPropertyValue_Reflected()
{
var asDynamic = GetDynamicNode(1174);
Assert.AreEqual("admin", asDynamic.GetPropertyValue("@creatorName"));
Assert.AreEqual("admin", asDynamic.GetPropertyValue("@CreatorName"));
}
[Test]
public void Get_User_Property_With_Same_Name_As_Member_Property()
{
var asDynamic = GetDynamicNode(1174);
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.creatorName);
//because CreatorName is defined on DynamicNode, it will not return the user defined property
Assert.AreEqual("admin", asDynamic.CreatorName);
}
[Test]
public void Get_Member_Property()
{
var asDynamic = GetDynamicNode(1173);
Assert.AreEqual((int) 2, (int) asDynamic.Level);
Assert.AreEqual((int) 2, (int) asDynamic.level);
Assert.AreEqual((int) 1046, (int) asDynamic.ParentId);
Assert.AreEqual((int) 1046, (int) asDynamic.parentId);
}
[Test]
public void Get_Children()
{
var asDynamic = GetDynamicNode(1173);
var children = asDynamic.Children;
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(children));
var childrenAsList = asDynamic.ChildrenAsList; //test ChildrenAsList too
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(childrenAsList));
var castChildren = (IEnumerable<TDocument>)children;
Assert.AreEqual(4, castChildren.Count());
var castChildrenAsList = (IEnumerable<TDocument>)childrenAsList;
Assert.AreEqual(4, castChildrenAsList.Count());
}
[Test]
public void Ancestor_Or_Self()
{
var asDynamic = GetDynamicNode(1173);
var result = asDynamic.AncestorOrSelf();
Assert.IsNotNull(result);
Assert.AreEqual((int) 1046, (int) result.Id);
}
[Test]
public void Ancestors_Or_Self()
{
var asDynamic = GetDynamicNode(1174);
var result = asDynamic.AncestorsOrSelf();
Assert.IsNotNull(result);
var list = (IEnumerable<TDocument>)result;
Assert.AreEqual(3, list.Count());
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1173, 1046 }));
}
[Test]
public void Ancestors()
{
var asDynamic = GetDynamicNode(1174);
var result = asDynamic.Ancestors();
Assert.IsNotNull(result);
var list = (IEnumerable<TDocument>)result;
Assert.AreEqual(2, list.Count());
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1046 }));
}
[Test]
public void Descendants_Or_Self()
{
var asDynamic = GetDynamicNode(1046);
var result = asDynamic.DescendantsOrSelf();
Assert.IsNotNull(result);
var list = (IEnumerable<TDocument>)result;
Assert.AreEqual(9, list.Count());
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175, 4444 }));
}
[Test]
public void Descendants()
{
var asDynamic = GetDynamicNode(1046);
var result = asDynamic.Descendants();
Assert.IsNotNull(result);
var list = (IEnumerable<TDocument>)result;
Assert.AreEqual(8, list.Count());
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 }));
}
[Test]
public void Up()
{
var asDynamic = GetDynamicNode(1173);
var result = asDynamic.Up();
Assert.IsNotNull(result);
Assert.AreEqual((int) 1046, (int) result.Id);
}
[Test]
public void Down()
{
var asDynamic = GetDynamicNode(1173);
var result = asDynamic.Down();
Assert.IsNotNull(result);
Assert.AreEqual((int) 1174, (int) result.Id);
}
[Test]
public void Next()
{
var asDynamic = GetDynamicNode(1173);
var result = asDynamic.Next();
Assert.IsNotNull(result);
Assert.AreEqual((int) 1175, (int) result.Id);
}
[Test]
public void Next_Without_Sibling()
{
var asDynamic = GetDynamicNode(1178);
Assert.IsNull(asDynamic.Next());
}
[Test]
public void Previous_Without_Sibling()
{
var asDynamic = GetDynamicNode(1173);
Assert.IsNull(asDynamic.Previous());
}
[Test]
public void Previous()
{
var asDynamic = GetDynamicNode(1176);
var result = asDynamic.Previous();
Assert.IsNotNull(result);
Assert.AreEqual((int) 1174, (int) result.Id);
}
}
/// <summary>
/// Extension methods used in tests
/// </summary>
public static class TestExtensionMethods
{
public static bool ContainsValue(this string s, int val)
{
return s.Contains(val.ToString());
}
}
}
@@ -1,82 +0,0 @@
using System;
using System.IO;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Models;
using umbraco.BusinessLogic;
using umbraco.IO;
using umbraco.MacroEngines;
using umbraco.NodeFactory;
using umbraco.cms.businesslogic;
using umbraco.cms.businesslogic.template;
using System.Linq;
using umbraco.cms.businesslogic.web;
namespace Umbraco.Tests.DynamicDocument
{
[TestFixture]
public class DynamicNodeTests : DynamicDocumentTestsBase<DynamicNode, DynamicNodeList>
{
protected override bool RequiresDbSetup
{
get { return true; }
}
public override void Initialize()
{
base.Initialize();
//copy the umbraco settings file over
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
File.Copy(
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
.First()
.GetDirectories("config").First()
.GetFiles("umbracoSettings.Release.config").First().FullName,
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
true);
UmbracoSettings.SettingsFilePath = IOHelper.MapPath(SystemDirectories.Config, false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
{
typeof(DynamicNode).Assembly
};
//need to specify a custom callback for unit tests
DynamicNode.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
{
if (propertyAlias == "content")
{
//return the rte type id
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
}
return Guid.Empty;
};
}
public override void TearDown()
{
base.TearDown();
PluginManager.Current.AssembliesToScan = null;
}
protected override dynamic GetDynamicNode(int id)
{
//var template = Template.MakeNew("test", new User(0));
//var ctx = GetUmbracoContext("/test", template.Id);
var ctx = GetUmbracoContext("/test", 1234);
var contentStore = new DefaultPublishedContentStore();
var node = new DynamicNode(
new DynamicBackingItem(
new Node(ctx.GetXml().SelectSingleNode("//*[@id='" + id + "' and @isDoc]"))));
Assert.IsNotNull(node);
return (dynamic) node;
}
}
}
@@ -1,87 +0,0 @@
using System;
using System.Diagnostics;
using System.Xml;
using System.Xml.Linq;
using Microsoft.CSharp.RuntimeBinder;
using NUnit.Framework;
using Umbraco.Core.Dynamics;
namespace Umbraco.Tests.DynamicDocument
{
[TestFixture]
public class DynamicXmlTests
{
[Test]
public void Ensure_Legacy_Objects_Are_Returned()
{
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
var mediaItems = new global::umbraco.MacroEngines.DynamicXml(xml);
//Debug.WriteLine("full xml = {0}", mediaItems.ToXml());
if (mediaItems.Count() != 0)
{
foreach (dynamic item in mediaItems)
{
Type itemType = item.GetType();
Debug.WriteLine("item type = {0}", itemType);
dynamic image = item.Image;
Type imageType = image.GetType();
Debug.WriteLine("image type = {0}", imageType);
//ensure they are the same
Assert.AreEqual(itemType, imageType);
//ensure they are legacy
Assert.AreEqual(typeof(global::umbraco.MacroEngines.DynamicXml), itemType);
Assert.AreEqual(typeof(global::umbraco.MacroEngines.DynamicXml), imageType);
}
}
}
/// <summary>
/// Test the current Core class
/// </summary>
[Test]
public void Find_Test_Core_Class()
{
RunFindTest(x => new DynamicXml(x));
}
/// <summary>
/// Tests the macroEngines legacy class
/// </summary>
[Test]
public void Find_Test_Legacy_Class()
{
RunFindTest(x => new global::umbraco.MacroEngines.DynamicXml(x));
}
private void RunFindTest(Func<string, dynamic> getDynamicXml)
{
var xmlstring = @"<test>
<item id='1' name='test 1' value='found 1'/>
<item id='2' name='test 2' value='found 2'/>
<item id='3' name='test 3' value='found 3'/>
</test>";
dynamic dXml = getDynamicXml(xmlstring);
var result1 = dXml.Find("@name", "test 1");
var result2 = dXml.Find("@name", "test 2");
var result3 = dXml.Find("@name", "test 3");
var result4 = dXml.Find("@name", "dont find");
Assert.AreEqual("found 1", result1.value);
Assert.AreEqual("found 2", result2.value);
Assert.AreEqual("found 3", result3.value);
Assert.Throws<RuntimeBinderException>(() =>
{
//this will throw because result4 is not found
var temp = result4.value;
});
}
}
}
@@ -10,6 +10,77 @@ namespace Umbraco.Tests
[TestFixture]
public class EnumerableExtensionsTests
{
[Test]
public void Flatten_List()
{
var hierarchy = new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem(),
new TestItem()
}
}
}
}
}
},
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
}
}
},
new TestItem()
{
Children = new List<TestItem>()
{
new TestItem()
{
Children = new List<TestItem>()
}
}
}
}
},
}
};
var flattened = hierarchy.Children.FlattenList(x => x.Children);
Assert.AreEqual(10, flattened.Count());
}
private class TestItem
{
public TestItem()
{
Children = Enumerable.Empty<TestItem>();
}
public IEnumerable<TestItem> Children { get; set; }
}
[Test]
public void InGroupsOf_ReturnsAllElements()
{
+60 -7
View File
@@ -1,6 +1,9 @@
using System.Configuration;
using System.Web.Routing;
using NUnit.Framework;
using Umbraco.Core.IO;
using Umbraco.Tests.TestHelpers;
using System.Web.Mvc;
namespace Umbraco.Tests
{
@@ -13,21 +16,34 @@ namespace Umbraco.Tests
}
public override void Initialize()
{
{
base.Initialize();
ConfigurationManager.AppSettings.Set("umbracoReservedPaths", "~/umbraco,~/install/");
ConfigurationManager.AppSettings.Set("umbracoReservedUrls", "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd");
SettingsForTests.UmbracoPath = "~/umbraco";
}
public override void TearDown()
{
//ensure this is reset
SystemDirectories.Root = null;
SettingsForTests.UmbracoPath = "~/umbraco";
//reset the app config
base.TearDown();
//reset the app config
ConfigurationManager.AppSettings.Set("umbracoReservedPaths", "");
ConfigurationManager.AppSettings.Set("umbracoReservedUrls", "");
}
[TestCase("/umbraco/umbraco.aspx")]
[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/")]
@@ -53,5 +69,42 @@ namespace Umbraco.Tests
{
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));
}
}
}
+154
View File
@@ -0,0 +1,154 @@
using System;
using System.IO;
using System.Reflection;
using NUnit.Framework;
using Umbraco.Core;
namespace Umbraco.Tests
{
[TestFixture]
public class HashCodeCombinerTests : PartialTrust.AbstractPartialTrustFixture<HashCodeCombinerTests>
{
private DirectoryInfo PrepareFolder()
{
var assDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
var dir = Directory.CreateDirectory(Path.Combine(assDir.FullName, "HashCombiner", Guid.NewGuid().ToString("N")));
foreach (var f in dir.GetFiles())
{
f.Delete();
}
return dir;
}
[Test]
public void HashCombiner_Test_String()
{
var combiner1 = new HashCodeCombiner();
combiner1.AddCaseInsensitiveString("Hello");
var combiner2 = new HashCodeCombiner();
combiner2.AddCaseInsensitiveString("hello");
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
combiner2.AddCaseInsensitiveString("world");
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
}
[Test]
public void HashCombiner_Test_Int()
{
var combiner1 = new HashCodeCombiner();
combiner1.AddInt(1234);
var combiner2 = new HashCodeCombiner();
combiner2.AddInt(1234);
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
combiner2.AddInt(1);
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
}
[Test]
public void HashCombiner_Test_DateTime()
{
var dt = DateTime.Now;
var combiner1 = new HashCodeCombiner();
combiner1.AddDateTime(dt);
var combiner2 = new HashCodeCombiner();
combiner2.AddDateTime(dt);
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
combiner2.AddDateTime(DateTime.Now);
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
}
[Test]
public void HashCombiner_Test_File()
{
var dir = PrepareFolder();
var file1Path = Path.Combine(dir.FullName, "hastest1.txt");
File.Delete(file1Path);
using (var file1 = File.CreateText(Path.Combine(dir.FullName, "hastest1.txt")))
{
file1.WriteLine("hello");
}
var file2Path = Path.Combine(dir.FullName, "hastest2.txt");
File.Delete(file2Path);
using (var file2 = File.CreateText(Path.Combine(dir.FullName, "hastest2.txt")))
{
//even though files are the same, the dates are different
file2.WriteLine("hello");
}
var combiner1 = new HashCodeCombiner();
combiner1.AddFile(new FileInfo(file1Path));
var combiner2 = new HashCodeCombiner();
combiner2.AddFile(new FileInfo(file1Path));
var combiner3 = new HashCodeCombiner();
combiner3.AddFile(new FileInfo(file2Path));
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner3.GetCombinedHashCode());
combiner2.AddFile(new FileInfo(file2Path));
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
}
[Test]
public void HashCombiner_Test_Folder()
{
var dir = PrepareFolder();
var file1Path = Path.Combine(dir.FullName, "hastest1.txt");
File.Delete(file1Path);
using (var file1 = File.CreateText(Path.Combine(dir.FullName, "hastest1.txt")))
{
file1.WriteLine("hello");
}
//first test the whole folder
var combiner1 = new HashCodeCombiner();
combiner1.AddFolder(dir);
var combiner2 = new HashCodeCombiner();
combiner2.AddFolder(dir);
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
//now add a file to the folder
var file2Path = Path.Combine(dir.FullName, "hastest2.txt");
File.Delete(file2Path);
using (var file2 = File.CreateText(Path.Combine(dir.FullName, "hastest2.txt")))
{
//even though files are the same, the dates are different
file2.WriteLine("hello");
}
var combiner3 = new HashCodeCombiner();
combiner3.AddFolder(dir);
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner3.GetCombinedHashCode());
}
public override void TestSetup()
{
}
public override void TestTearDown()
{
}
}
}
@@ -9,7 +9,7 @@ using Umbraco.Tests.BusinessLogic;
namespace Umbraco.Tests.IO
{
[TestFixture]
[TestFixture, RequiresSTA]
internal abstract class AbstractFileSystemTests
{
protected IFileSystem _fileSystem;
@@ -104,7 +104,7 @@ namespace Umbraco.Tests.IO
_fileSystem.DeleteDirectory("test", true);
}
[Test]
public void Can_Get_File_Dates()
{
+7
View File
@@ -13,6 +13,13 @@ namespace Umbraco.Tests.IO
public class IOHelperTest
{
[Test]
public void IOHelper_ResolveUrl()
{
var result = IOHelper.ResolveUrl("~/Scripts");
Assert.AreEqual("/Scripts", result);
}
/// <summary>
///A test for MapPath verifying that HttpContext method (which includes vdirs) matches non-HttpContext method
///</summary>
@@ -9,14 +9,32 @@ using Umbraco.Tests.BusinessLogic;
namespace Umbraco.Tests.IO
{
[TestFixture]
[TestFixture, RequiresSTA]
internal class PhysicalFileSystemTests : AbstractFileSystemTests
{
public PhysicalFileSystemTests()
: base(new PhysicalFileSystem(AppDomain.CurrentDomain.BaseDirectory,
: base(new PhysicalFileSystem(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FileSysTests"),
"/Media/"))
{ }
[SetUp]
public void Setup()
{
}
[TearDown]
public void TearDown()
{
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FileSysTests");
var files = Directory.GetFiles(path);
foreach (var f in files)
{
File.Delete(f);
}
Directory.Delete(path, true);
}
protected override string ConstructUrl(string path)
{
return "/Media/" + path;
+12
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using NUnit.Framework;
@@ -26,6 +27,17 @@ namespace Umbraco.Tests
var routingContext = GetRoutingContext("/test", 1234);
UmbracoContext.Current = routingContext.UmbracoContext;
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
File.Copy(
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
.First()
.GetDirectories("config").First()
.GetFiles("umbracoSettings.Release.config").First().FullName,
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
true);
Core.Configuration.UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
}
public override void TearDown()
+1 -1
View File
@@ -18,7 +18,7 @@ namespace Umbraco.Tests
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager();
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
+1 -1
View File
@@ -18,7 +18,7 @@ namespace Umbraco.Tests
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager();
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
+31 -1
View File
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Umbraco.Core;
@@ -67,7 +68,8 @@ namespace Umbraco.Tests
{"FALSE", false},
{"False", false},
{"false", false},
{"0", false}
{"0", false},
{"", false}
};
foreach (var testCase in testCases)
@@ -79,6 +81,34 @@ namespace Umbraco.Tests
}
}
[Test]
[TestOnlyInFullTrust]
public virtual void CanConvertStringToDateTime()
{
var dateTime = new DateTime(2012, 11, 10, 13, 14, 15);
var testCases = new Dictionary<string, bool>
{
{"2012-11-10", true},
{"2012/11/10", true},
{"10/11/2012", true},
{"11/10/2012", false},
{"Sat 10, Nov 2012", true},
{"Saturday 10, Nov 2012", true},
{"Sat 10, November 2012", true},
{"Saturday 10, November 2012", true},
{"2012-11-10 13:14:15", true},
{"", false}
};
foreach (var testCase in testCases)
{
var result = testCase.Key.TryConvertTo<DateTime>();
Assert.IsTrue(result.Success);
Assert.AreEqual(DateTime.Equals(dateTime.Date, result.Result.Date), testCase.Value);
}
}
/// <summary>
/// Run once before each test in derived test fixtures.
/// </summary>
+307 -114
View File
@@ -1,37 +1,44 @@
using System;
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.Core;
using Umbraco.Core.IO;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using umbraco;
using umbraco.DataLayer;
using umbraco.MacroEngines;
using umbraco.MacroEngines.Iron;
using umbraco.businesslogic;
using umbraco.cms.businesslogic;
using umbraco.editorControls;
using umbraco.interfaces;
using umbraco.uicontrols;
using umbraco.cms;
namespace Umbraco.Tests
{
[TestFixture]
public class PluginManagerTests
{
[TestFixture]
public class PluginManagerTests
{
[SetUp]
public void Initialize()
{
TestHelper.SetupLog4NetForTests();
[SetUp]
public void Initialize()
{
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager();
//this ensures its reset
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
//TODO: Should probably update this so it only searches this assembly and add custom types to be found
PluginManager.Current.AssembliesToScan = new[]
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
//TODO: Should probably update this so it only searches this assembly and add custom types to be found
PluginManager.Current.AssembliesToScan = new[]
{
this.GetType().Assembly,
typeof(ApplicationStartupHandler).Assembly,
@@ -47,132 +54,318 @@ namespace Umbraco.Tests
typeof(System.Web.Mvc.ActionResult).Assembly,
typeof(TypeFinder).Assembly,
typeof(ISqlHelper).Assembly,
typeof(DLRScriptingEngine).Assembly,
typeof(ICultureDictionary).Assembly,
typeof(UmbracoContext).Assembly,
typeof(BaseDataType).Assembly
};
}
}
[Test]
public void Ensure_Only_One_Type_List_Created()
{
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
var foundTypes2 = PluginManager.Current.ResolveFindMeTypes();
Assert.AreEqual(1,
PluginManager.Current.GetTypeLists()
.Count(x => x.IsTypeList<IFindMe>(PluginManager.TypeResolutionKind.FindAllTypes)));
}
private DirectoryInfo PrepareFolder()
{
var assDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
var dir = Directory.CreateDirectory(Path.Combine(assDir.FullName, "PluginManager", Guid.NewGuid().ToString("N")));
foreach (var f in dir.GetFiles())
{
f.Delete();
}
return dir;
}
[Test]
public void Resolves_Types()
{
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
Assert.AreEqual(2, foundTypes1.Count());
}
//[Test]
//public void Scan_Vs_Load_Benchmark()
//{
// var pluginManager = new PluginManager(false);
// var watch = new Stopwatch();
// watch.Start();
// for (var i = 0; i < 1000; i++)
// {
// var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
// var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
// var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
// var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
// }
// watch.Stop();
// Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
// watch.Start();
// for (var i = 0; i < 1000; i++)
// {
// var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
// var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
// var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
// var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
// }
// watch.Stop();
// Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
// watch.Reset();
// watch.Start();
// for (var i = 0; i < 1000; i++)
// {
// var refreshers = pluginManager.ResolveTypes<ICacheRefresher>(false);
// }
// watch.Stop();
// Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds);
//}
[Test]
public void Resolves_Attributed_Trees()
{
var trees = PluginManager.Current.ResolveAttributedTrees();
Assert.AreEqual(27, trees.Count());
}
////NOTE: This test shows that Type.GetType is 100% faster than Assembly.Load(..).GetType(...) so we'll use that :)
//[Test]
//public void Load_Type_Benchmark()
//{
// var watch = new Stopwatch();
// watch.Start();
// for (var i = 0; i < 1000; i++)
// {
// var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
// var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
// var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
// var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
// }
// watch.Stop();
// Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
// watch.Reset();
// watch.Start();
// for (var i = 0; i < 1000; i++)
// {
// var type2 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
// .GetType("umbraco.macroCacheRefresh");
// var type3 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
// .GetType("umbraco.templateCacheRefresh");
// var type4 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
// .GetType("umbraco.presentation.cache.MediaLibraryRefreshers");
// var type5 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
// .GetType("umbraco.presentation.cache.pageRefresher");
// }
// watch.Stop();
// Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds);
// watch.Reset();
// watch.Start();
// for (var i = 0; i < 1000; i++)
// {
// var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
// var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
// var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
// var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
// }
// watch.Stop();
// Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
//}
[Test]
public void Resolves_Actions()
{
var actions = PluginManager.Current.ResolveActions();
Assert.AreEqual(37, actions.Count());
}
[Test]
public void Detect_Legacy_Plugin_File_List()
{
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
var manager = new PluginManager(false);
var filePath = Path.Combine(tempFolder, "umbraco-plugins.list");
File.WriteAllText(filePath, @"<?xml version=""1.0"" encoding=""utf-8""?>
<plugins>
<baseType type=""umbraco.interfaces.ICacheRefresher"">
<add type=""umbraco.macroCacheRefresh, umbraco, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null"" />
</baseType>
</plugins>");
[Test]
public void Resolves_Trees()
{
var trees = PluginManager.Current.ResolveTrees();
Assert.AreEqual(36, trees.Count());
}
Assert.IsTrue(manager.DetectLegacyPluginListFile());
[Test]
public void Resolves_Applications()
{
var apps = PluginManager.Current.ResolveApplications();
Assert.AreEqual(7, apps.Count());
}
File.Delete(filePath);
[Test]
public void Resolves_Action_Handlers()
{
var types = PluginManager.Current.ResolveActionHandlers();
Assert.AreEqual(1, types.Count());
}
//now create a valid one
File.WriteAllText(filePath, @"<?xml version=""1.0"" encoding=""utf-8""?>
<plugins>
<baseType type=""umbraco.interfaces.ICacheRefresher"" resolutionType=""FindAllTypes"">
<add type=""umbraco.macroCacheRefresh, umbraco, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null"" />
</baseType>
</plugins>");
[Test]
public void Resolves_DataTypes()
{
var types = PluginManager.Current.ResolveDataTypes();
Assert.AreEqual(37, types.Count());
}
Assert.IsFalse(manager.DetectLegacyPluginListFile());
}
[Test]
public void Resolves_RazorDataTypeModels()
{
var types = PluginManager.Current.ResolveRazorDataTypeModels();
Assert.AreEqual(2, types.Count());
}
[Test]
public void Create_Cached_Plugin_File()
{
var types = new[] { typeof(PluginManager), typeof(PluginManagerTests), typeof(UmbracoContext) };
[Test]
public void Resolves_RestExtensions()
{
var types = PluginManager.Current.ResolveRestExtensions();
Assert.AreEqual(2, types.Count());
}
var manager = new PluginManager(false);
//yes this is silly, none of these types inherit from string, but this is just to test the xml file format
manager.UpdateCachedPluginsFile<string>(types, PluginManager.TypeResolutionKind.FindAllTypes);
[Test]
public void Resolves_LegacyRestExtensions()
{
var types = PluginManager.Current.ResolveLegacyRestExtensions();
Assert.AreEqual(1, types.Count());
}
var plugins = manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAllTypes);
var diffType = manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAttributedTypes);
[Test]
public void Resolves_XsltExtensions()
{
var types = PluginManager.Current.ResolveXsltExtensions();
Assert.AreEqual(1, types.Count());
}
Assert.IsTrue(plugins.Success);
//this will be false since there is no cache of that type resolution kind
Assert.IsFalse(diffType.Success);
[XsltExtension("Blah.Blah")]
public class MyXsltExtension
{
Assert.AreEqual(3, plugins.Result.Count());
var shouldContain = types.Select(x => x.AssemblyQualifiedName);
//ensure they are all found
Assert.IsTrue(plugins.Result.ContainsAll(shouldContain));
}
}
[Test]
public void PluginHash_From_String()
{
var s = "hello my name is someone".GetHashCode().ToString("x", CultureInfo.InvariantCulture);
var output = PluginManager.ConvertPluginsHashFromHex(s);
Assert.AreNotEqual(0, output);
}
[umbraco.presentation.umbracobase.RestExtension("Blah")]
public class MyLegacyRestExtension
{
}
[Test]
public void Get_Plugins_Hash()
{
//Arrange
var dir = PrepareFolder();
var d1 = dir.CreateSubdirectory("1");
var d2 = dir.CreateSubdirectory("2");
var d3 = dir.CreateSubdirectory("3");
var d4 = dir.CreateSubdirectory("4");
var f1 = new FileInfo(Path.Combine(d1.FullName, "test1.dll"));
var f2 = new FileInfo(Path.Combine(d1.FullName, "test2.dll"));
var f3 = new FileInfo(Path.Combine(d2.FullName, "test1.dll"));
var f4 = new FileInfo(Path.Combine(d2.FullName, "test2.dll"));
var f5 = new FileInfo(Path.Combine(d3.FullName, "test1.dll"));
var f6 = new FileInfo(Path.Combine(d3.FullName, "test2.dll"));
var f7 = new FileInfo(Path.Combine(d4.FullName, "test1.dll"));
f1.CreateText().Close();
f2.CreateText().Close();
f3.CreateText().Close();
f4.CreateText().Close();
f5.CreateText().Close();
f6.CreateText().Close();
f7.CreateText().Close();
var list1 = new[] { f1, f2, f3, f4, f5, f6 };
var list2 = new[] { f1, f3, f5 };
var list3 = new[] { f1, f3, f5, f7 };
[Umbraco.Web.BaseRest.RestExtension("Blah")]
public class MyRestExtesion
{
}
//Act
var hash1 = PluginManager.GetAssembliesHash(list1);
var hash2 = PluginManager.GetAssembliesHash(list2);
var hash3 = PluginManager.GetAssembliesHash(list3);
public interface IFindMe
{
//Assert
Assert.AreNotEqual(hash1, hash2);
Assert.AreNotEqual(hash1, hash3);
Assert.AreNotEqual(hash2, hash3);
}
Assert.AreEqual(hash1, PluginManager.GetAssembliesHash(list1));
}
public class FindMe1 : IFindMe
{
[Test]
public void Ensure_Only_One_Type_List_Created()
{
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
var foundTypes2 = PluginManager.Current.ResolveFindMeTypes();
Assert.AreEqual(1,
PluginManager.Current.GetTypeLists()
.Count(x => x.IsTypeList<IFindMe>(PluginManager.TypeResolutionKind.FindAllTypes)));
}
}
[Test]
public void Resolves_Types()
{
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
Assert.AreEqual(2, foundTypes1.Count());
}
public class FindMe2 : IFindMe
{
[Test]
public void Resolves_Attributed_Trees()
{
var trees = PluginManager.Current.ResolveAttributedTrees();
Assert.AreEqual(27, trees.Count());
}
}
[Test]
public void Resolves_Actions()
{
var actions = PluginManager.Current.ResolveActions();
Assert.AreEqual(37, actions.Count());
}
}
[Test]
public void Resolves_Trees()
{
var trees = PluginManager.Current.ResolveTrees();
Assert.AreEqual(36, trees.Count());
}
[Test]
public void Resolves_Applications()
{
var apps = PluginManager.Current.ResolveApplications();
Assert.AreEqual(7, apps.Count());
}
[Test]
public void Resolves_Action_Handlers()
{
var types = PluginManager.Current.ResolveActionHandlers();
Assert.AreEqual(1, types.Count());
}
[Test]
public void Resolves_DataTypes()
{
var types = PluginManager.Current.ResolveDataTypes();
Assert.AreEqual(37, types.Count());
}
[Test]
public void Resolves_RazorDataTypeModels()
{
var types = PluginManager.Current.ResolveRazorDataTypeModels();
Assert.AreEqual(2, types.Count());
}
[Test]
public void Resolves_RestExtensions()
{
var types = PluginManager.Current.ResolveRestExtensions();
Assert.AreEqual(2, types.Count());
}
[Test]
public void Resolves_LegacyRestExtensions()
{
var types = PluginManager.Current.ResolveLegacyRestExtensions();
Assert.AreEqual(1, types.Count());
}
[Test]
public void Resolves_XsltExtensions()
{
var types = PluginManager.Current.ResolveXsltExtensions();
Assert.AreEqual(1, types.Count());
}
[XsltExtension("Blah.Blah")]
public class MyXsltExtension
{
}
[umbraco.presentation.umbracobase.RestExtension("Blah")]
public class MyLegacyRestExtension
{
}
[Umbraco.Web.BaseRest.RestExtension("Blah")]
public class MyRestExtesion
{
}
public interface IFindMe
{
}
public class FindMe1 : IFindMe
{
}
public class FindMe2 : IFindMe
{
}
}
}
@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.PropertyEditors
{
[TestFixture]
public class PropertyEditorValueConverterTests
{
[Test]
public void CanConvertDatePickerPropertyEditor()
{
var converter = new DatePickerPropertyEditorValueConverter();
var dateTime = new DateTime(2012, 11, 10, 13, 14, 15);
var testCases = new Dictionary<string, bool>
{
{"2012-11-10", true},
{"2012/11/10", true},
{"10/11/2012", true},
{"11/10/2012", false},
{"Sat 10, Nov 2012", true},
{"Saturday 10, Nov 2012", true},
{"Sat 10, November 2012", true},
{"Saturday 10, November 2012", true},
{"2012-11-10 13:14:15", true},
{"", false}
};
foreach (var testCase in testCases)
{
var result = converter.ConvertPropertyValue(testCase.Key);
Assert.IsTrue(result.Success);
Assert.AreEqual(DateTime.Equals(dateTime.Date, ((DateTime)result.Result).Date), testCase.Value);
}
}
[Test]
public void CanConvertYesNoPropertyEditor()
{
var converter = new YesNoPropertyEditorValueConverter();
var testCases = new Dictionary<string, bool>
{
{"TRUE", true},
{"True", true},
{"true", true},
{"1", true},
{"FALSE", false},
{"False", false},
{"false", false},
{"0", false},
{"", false}
};
foreach (var testCase in testCases)
{
var result = converter.ConvertPropertyValue(testCase.Key);
Assert.IsTrue(result.Success);
Assert.AreEqual(testCase.Value, result.Result);
}
}
}
}
@@ -0,0 +1,710 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Dynamics;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.PublishedContent
{
[TestFixture]
public abstract class DynamicDocumentTestsBase<TDocument, TDocumentList> : PublishedContentTestBase
{
public override void Initialize()
{
base.Initialize();
}
public override void TearDown()
{
base.TearDown();
}
protected override bool RequiresDbSetup
{
get { return false; }
}
protected override string GetXmlContent(int templateId)
{
return @"<?xml version=""1.0"" encoding=""utf-8""?>
<!DOCTYPE root[
<!ELEMENT Home ANY>
<!ATTLIST Home id ID #REQUIRED>
<!ELEMENT CustomDocument ANY>
<!ATTLIST CustomDocument id ID #REQUIRED>
]>
<root id=""-1"">
<Home id=""1046"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Home"" urlName=""home"" writerName=""admin"" creatorName=""admin"" path=""-1,1046"" isDoc="""">
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[this/is/my/alias, anotheralias]]></umbracoUrlAlias>
<umbracoNaviHide>1</umbracoNaviHide>
<siteTitle><![CDATA[This is my site]]></siteTitle>
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
<content><![CDATA[<div>This is some content</div>]]></content>
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
<creatorName><![CDATA[Custom data with same property name as the member name]]></creatorName>
</Home>
<CustomDocument id=""1177"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""custom sub 1"" urlName=""custom-sub-1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1177"" isDoc="""" />
<CustomDocument id=""1178"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-16T14:23:35"" nodeName=""custom sub 2"" urlName=""custom-sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1178"" isDoc="""" />
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc="""">
<content><![CDATA[some content]]></content>
<blah><![CDATA[some content]]></blah>
<umbracoNaviHide>1</umbracoNaviHide>
</Home>
</Home>
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
</Home>
<CustomDocument id=""4444"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444"" isDoc="""">
<selectedNodes><![CDATA[1172,1176,1173]]></selectedNodes>
<CustomDocument id=""5555"" parentID=""1046"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""0"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444,5555"" isDoc="""">
</CustomDocument>
</CustomDocument>
</Home>
<CustomDocument id=""1172"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1172"" isDoc="""" />
</root>";
}
/// <summary>
/// Returns the dynamic node/document to run tests against
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
protected abstract dynamic GetDynamicNode(int id);
[Test]
public void Recursive_Property()
{
var doc = GetDynamicNode(1174);
var prop = doc.GetProperty("siteTitle", true);
Assert.IsNotNull(prop);
Assert.AreEqual("This is my site", prop.Value);
prop = doc.GetProperty("_siteTitle"); //test with underscore prefix
Assert.IsNotNull(prop);
Assert.AreEqual("This is my site", prop.Value);
Assert.AreEqual("This is my site", doc._siteTitle);
}
/// <summary>
/// Tests the internal instance level caching of returning properties
/// </summary>
/// <remarks>
/// http://issues.umbraco.org/issue/U4-1824
/// http://issues.umbraco.org/issue/U4-1825
/// </remarks>
[Test]
public void Can_Return_Property_And_Value()
{
var doc = GetDynamicNode(1173);
Assert.IsTrue(doc.HasProperty("umbracoUrlAlias"));
var prop = doc.GetProperty("umbracoUrlAlias");
Assert.IsNotNull(prop);
Assert.AreEqual("page2/alias, 2ndpagealias", prop.Value);
Assert.AreEqual("page2/alias, 2ndpagealias", doc.umbracoUrlAlias);
}
/// <summary>
/// Tests the IsLast method with the result set from a Where statement
/// </summary>
[Test]
public void Is_Last_From_Where_Filter()
{
var doc = GetDynamicNode(1173);
foreach (var d in doc.Children.Where("Visible"))
{
if (d.Id != 1178)
{
Assert.IsFalse(d.IsLast());
}
else
{
Assert.IsTrue(d.IsLast());
}
}
}
[Test]
public void Single()
{
var doc = GetDynamicNode(4444);
var result = doc.Children().Single();
Assert.IsNotNull(result);
Assert.AreEqual(5555, result.Id);
}
[Test]
public void Single_With_Query()
{
var doc = GetDynamicNode(1046);
var result = doc.Children().Single("id==1175");
Assert.IsNotNull(result);
Assert.AreEqual(1175, result.Id);
}
[Test]
public void First()
{
var doc = GetDynamicNode(1173);
var result = doc.Children().First();
Assert.IsNotNull(result);
Assert.AreEqual(1174, result.Id);
}
[Test]
public void First_With_Query()
{
var doc = GetDynamicNode(1173);
var result = doc.Children().First("blah==\"some content\"");
Assert.IsNotNull(result);
Assert.AreEqual(1176, result.Id);
}
[Test]
public void Where_User_Property_Value()
{
var doc = GetDynamicNode(1173);
var result = (IEnumerable<dynamic>)doc.Children().Where("blah==\"some content\"");
Assert.IsNotNull(result);
Assert.AreEqual(1, result.Count());
Assert.AreEqual(1176, result.Single().Id);
}
[Test]
public void String_ContainsValue_Extension_Method()
{
var doc = GetDynamicNode(1046);
var paramVals = new Dictionary<string, object> { { "searchId", 1173 } }; //this is an integer value
var result = doc.Children()
.Where("selectedNodes.ContainsValue(searchId)", paramVals) //call an extension method
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.AreEqual(4444, result.Id);
//don't find!
paramVals = new Dictionary<string, object> { { "searchId", 1111777 } };
result = doc.Children()
.Where("selectedNodes.ContainsValue(searchId)", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.IsTrue(result.GetType() == typeof(DynamicNull) || result.GetType() == typeof(umbraco.MacroEngines.DynamicNull));
//Assert.AreEqual(typeof(DynamicNull), result.GetType());
}
[Test]
public void String_Contains_Method()
{
var doc = GetDynamicNode(1046);
var paramVals = new Dictionary<string, object> { { "searchId", "1173" } };
var result = doc.Children()
.Where("selectedNodes.Contains(searchId)", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.AreEqual(4444, result.Id);
//don't find!
paramVals = new Dictionary<string, object> { { "searchId", "1aaa173" } };
result = doc.Children()
.Where("selectedNodes.Contains(searchId)", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.IsTrue(result.GetType() == typeof(DynamicNull) || result.GetType() == typeof(umbraco.MacroEngines.DynamicNull));
//Assert.AreEqual(typeof (DynamicNull), result.GetType());
}
[Test]
public void String_Split_Method()
{
var doc = GetDynamicNode(1046);
var paramVals = new Dictionary<string, object>
{
{ "splitTerm", new char[] { ',' } },
{ "splitOptions", StringSplitOptions.RemoveEmptyEntries }
};
var result = doc.Children()
.Where("selectedNodes.Split(splitTerm, splitOptions).Length == 3", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.AreEqual(4444, result.Id);
}
[Ignore("We are ignoring this test because currently our ExpressionParser class cannot deal with this... it needs some serious TLC but it is very complex.")]
[Test]
public void Complex_Linq()
{
var doc = GetDynamicNode(1173);
var paramVals = new Dictionary<string, object> { { "splitTerm", new char[] { ',' } }, { "searchId", "1173" } };
var result = doc.Ancestors().OrderBy("level")
.Single()
.Descendants()
.Where("selectedNodes != null && selectedNodes != String.Empty && selectedNodes.Split(splitTerm).Contains(searchId)", paramVals)
.FirstOrDefault();
Assert.IsNotNull(result);
Assert.AreEqual(4444, result.Id);
}
[Test]
public void Index()
{
var doc = GetDynamicNode(1173);
Assert.AreEqual(0, doc.Index());
doc = GetDynamicNode(1176);
Assert.AreEqual(3, doc.Index());
doc = GetDynamicNode(1177);
Assert.AreEqual(1, doc.Index());
doc = GetDynamicNode(1178);
Assert.AreEqual(2, doc.Index());
}
[Test]
public virtual void Is_First_Root_Nodes()
{
var doc = GetDynamicNode(1046); //test root nodes
Assert.IsTrue(doc.IsFirst());
doc = GetDynamicNode(1172);
Assert.IsFalse(doc.IsFirst());
}
[Test]
public void Is_First()
{
var doc = GetDynamicNode(1173); //test normal nodes
Assert.IsTrue(doc.IsFirst());
doc = GetDynamicNode(1175);
Assert.IsFalse(doc.IsFirst());
}
[Test]
public virtual void Is_Not_First_Root_Nodes()
{
var doc = GetDynamicNode(1046); //test root nodes
Assert.IsFalse(doc.IsNotFirst());
doc = GetDynamicNode(1172);
Assert.IsTrue(doc.IsNotFirst());
}
[Test]
public void Is_Not_First()
{
var doc = GetDynamicNode(1173); //test normal nodes
Assert.IsFalse(doc.IsNotFirst());
doc = GetDynamicNode(1175);
Assert.IsTrue(doc.IsNotFirst());
}
[Test]
public virtual void Is_Position_Root_Nodes()
{
var doc = GetDynamicNode(1046); //test root nodes
Assert.IsTrue(doc.IsPosition(0));
doc = GetDynamicNode(1172);
Assert.IsTrue(doc.IsPosition(1));
}
[Test]
public void Is_Position()
{
var doc = GetDynamicNode(1173); //test normal nodes
Assert.IsTrue(doc.IsPosition(0));
doc = GetDynamicNode(1175);
Assert.IsTrue(doc.IsPosition(1));
}
[Test]
public void Children_GroupBy_DocumentTypeAlias()
{
var doc = GetDynamicNode(1046);
var found1 = doc.Children.GroupBy("DocumentTypeAlias");
var casted = (IEnumerable<IGrouping<object, dynamic>>)(found1);
Assert.AreEqual(2, casted.Count());
Assert.AreEqual(2, casted.Single(x => x.Key.ToString() == "Home").Count());
Assert.AreEqual(1, casted.Single(x => x.Key.ToString() == "CustomDocument").Count());
}
[Test]
public void Children_Where_DocumentTypeAlias()
{
var doc = GetDynamicNode(1046);
var found1 = doc.Children.Where("DocumentTypeAlias == \"CustomDocument\"");
var found2 = doc.Children.Where("DocumentTypeAlias == \"Home\"");
Assert.AreEqual(1, found1.Count());
Assert.AreEqual(2, found2.Count());
}
[Test]
public void Children_Where_NodeTypeAlias()
{
var doc = GetDynamicNode(1046);
var found1 = doc.Children.Where("NodeTypeAlias == \"CustomDocument\"");
var found2 = doc.Children.Where("NodeTypeAlias == \"Home\"");
Assert.AreEqual(1, found1.Count());
Assert.AreEqual(2, found2.Count());
}
[Test]
public void Children_Order_By_Update_Date()
{
var asDynamic = GetDynamicNode(1173);
var ordered = asDynamic.Children.OrderBy("UpdateDate");
var casted = (IEnumerable<TDocument>)ordered;
var correctOrder = new[] { 1178, 1177, 1174, 1176 };
for (var i = 0; i < correctOrder.Length; i++)
{
Assert.AreEqual(correctOrder[i], ((dynamic)casted.ElementAt(i)).Id);
}
}
[Test]
public void Children_Order_By_Update_Date_Descending()
{
var asDynamic = GetDynamicNode(1173);
var ordered = asDynamic.Children.OrderBy("UpdateDate desc");
var casted = (IEnumerable<TDocument>)ordered;
var correctOrder = new[] { 1176, 1174, 1177, 1178 };
for (var i = 0; i < correctOrder.Length; i++)
{
Assert.AreEqual(correctOrder[i], ((dynamic)casted.ElementAt(i)).Id);
}
}
[Test]
public void HasProperty()
{
var asDynamic = GetDynamicNode(1173);
var hasProp = asDynamic.HasProperty("umbracoUrlAlias");
Assert.AreEqual(true, (bool)hasProp);
}
[Test]
public void Skip()
{
var asDynamic = GetDynamicNode(1173);
var skip = asDynamic.Children.Skip(2);
var casted = (IEnumerable<TDocument>)skip;
Assert.AreEqual(2, casted.Count());
Assert.IsTrue(casted.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1178, 1176 }));
}
[Test]
public void HasValue()
{
var asDynamic = GetDynamicNode(1173);
var hasValue = asDynamic.HasValue("umbracoUrlAlias");
var noValue = asDynamic.HasValue("blahblahblah");
Assert.IsTrue(hasValue);
Assert.IsFalse(noValue);
}
[Test]
public void Take()
{
var asDynamic = GetDynamicNode(1173);
var take = asDynamic.Children.Take(2);
var casted = (IEnumerable<TDocument>)take;
Assert.AreEqual(2, casted.Count());
Assert.IsTrue(casted.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1177 }));
}
[Test]
public void Ancestors_Where_Visible()
{
var asDynamic = GetDynamicNode(1174);
var whereVisible = asDynamic.Ancestors().Where("Visible");
var casted = (IEnumerable<TDocument>)whereVisible;
Assert.AreEqual(1, casted.Count());
}
[Test]
public void Visible()
{
var asDynamicHidden = GetDynamicNode(1046);
var asDynamicVisible = GetDynamicNode(1173);
Assert.IsFalse(asDynamicHidden.Visible);
Assert.IsTrue(asDynamicVisible.Visible);
}
[Test]
public void Ensure_TinyMCE_Converted_Type_User_Property()
{
var asDynamic = GetDynamicNode(1173);
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(asDynamic.Content.GetType()));
Assert.AreEqual("<div>This is some content</div>", asDynamic.Content.ToString());
}
[Test]
public void Get_Children_With_Pluralized_Alias()
{
var asDynamic = GetDynamicNode(1173);
Action<object> doAssert = d =>
{
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(d));
var casted = (IEnumerable<TDocument>)d;
Assert.AreEqual(2, casted.Count());
};
doAssert(asDynamic.Homes); //pluralized alias
doAssert(asDynamic.homes); //pluralized alias
doAssert(asDynamic.CustomDocuments); //pluralized alias
doAssert(asDynamic.customDocuments); //pluralized alias
}
[Test]
public void GetPropertyValue_Non_Reflected()
{
var asDynamic = GetDynamicNode(1174);
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.GetPropertyValue("creatorName"));
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.GetPropertyValue("CreatorName"));
}
[Test]
public void GetPropertyValue_Reflected()
{
var asDynamic = GetDynamicNode(1174);
Assert.AreEqual("admin", asDynamic.GetPropertyValue("@creatorName"));
Assert.AreEqual("admin", asDynamic.GetPropertyValue("@CreatorName"));
}
[Test]
public void Get_User_Property_With_Same_Name_As_Member_Property()
{
var asDynamic = GetDynamicNode(1174);
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.creatorName);
//because CreatorName is defined on DynamicNode, it will not return the user defined property
Assert.AreEqual("admin", asDynamic.CreatorName);
}
[Test]
public void Get_Member_Property()
{
var asDynamic = GetDynamicNode(1173);
Assert.AreEqual((int)2, (int)asDynamic.Level);
Assert.AreEqual((int)2, (int)asDynamic.level);
Assert.AreEqual((int)1046, (int)asDynamic.ParentId);
Assert.AreEqual((int)1046, (int)asDynamic.parentId);
}
[Test]
public void Get_Children()
{
var asDynamic = GetDynamicNode(1173);
var children = asDynamic.Children;
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(children));
var childrenAsList = asDynamic.ChildrenAsList; //test ChildrenAsList too
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(childrenAsList));
var castChildren = (IEnumerable<TDocument>)children;
Assert.AreEqual(4, castChildren.Count());
var castChildrenAsList = (IEnumerable<TDocument>)childrenAsList;
Assert.AreEqual(4, castChildrenAsList.Count());
}
[Test]
public void Ancestor_Or_Self()
{
var asDynamic = GetDynamicNode(1173);
var result = asDynamic.AncestorOrSelf();
Assert.IsNotNull(result);
Assert.AreEqual((int)1046, (int)result.Id);
}
[Test]
public void Ancestors_Or_Self()
{
var asDynamic = GetDynamicNode(1174);
var result = asDynamic.AncestorsOrSelf();
Assert.IsNotNull(result);
var list = (IEnumerable<TDocument>)result;
Assert.AreEqual(3, list.Count());
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1173, 1046 }));
}
[Test]
public void Ancestors()
{
var asDynamic = GetDynamicNode(1174);
var result = asDynamic.Ancestors();
Assert.IsNotNull(result);
var list = (IEnumerable<TDocument>)result;
Assert.AreEqual(2, list.Count());
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1046 }));
}
[Test]
public void Descendants_Or_Self()
{
var asDynamic = GetDynamicNode(1046);
var result = asDynamic.DescendantsOrSelf();
Assert.IsNotNull(result);
var list = (IEnumerable<TDocument>)result;
Assert.AreEqual(9, list.Count());
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175, 4444 }));
}
[Test]
public void Descendants()
{
var asDynamic = GetDynamicNode(1046);
var result = asDynamic.Descendants();
Assert.IsNotNull(result);
var list = (IEnumerable<TDocument>)result;
Assert.AreEqual(8, list.Count());
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 }));
}
[Test]
public void Up()
{
var asDynamic = GetDynamicNode(1173);
var result = asDynamic.Up();
Assert.IsNotNull(result);
Assert.AreEqual((int)1046, (int)result.Id);
}
[Test]
public void Down()
{
var asDynamic = GetDynamicNode(1173);
var result = asDynamic.Down();
Assert.IsNotNull(result);
Assert.AreEqual((int)1174, (int)result.Id);
}
[Test]
public void Next()
{
var asDynamic = GetDynamicNode(1173);
var result = asDynamic.Next();
Assert.IsNotNull(result);
Assert.AreEqual((int)1175, (int)result.Id);
}
[Test]
public void Next_Without_Sibling()
{
var asDynamic = GetDynamicNode(1176);
Assert.IsNull(asDynamic.Next());
}
[Test]
public void Previous_Without_Sibling()
{
var asDynamic = GetDynamicNode(1173);
Assert.IsNull(asDynamic.Previous());
}
[Test]
public void Previous()
{
var asDynamic = GetDynamicNode(1176);
var result = asDynamic.Previous();
Assert.IsNotNull(result);
Assert.AreEqual((int)1178, (int)result.Id);
}
}
/// <summary>
/// Extension methods used in tests
/// </summary>
public static class TestExtensionMethods
{
public static bool ContainsValue(this string s, int val)
{
return s.Contains(val.ToString());
}
}
}
@@ -0,0 +1,98 @@
using System;
using System.IO;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using umbraco.IO;
using umbraco.MacroEngines;
using umbraco.NodeFactory;
using System.Linq;
namespace Umbraco.Tests.PublishedContent
{
[TestFixture]
public class DynamicNodeTests : DynamicDocumentTestsBase<DynamicNode, DynamicNodeList>
{
protected override bool RequiresDbSetup
{
get { return true; }
}
public override void Initialize()
{
base.Initialize();
//copy the umbraco settings file over
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
File.Copy(
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
.First()
.GetDirectories("config").First()
.GetFiles("umbracoSettings.Release.config").First().FullName,
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
true);
UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
{
typeof(DynamicNode).Assembly
};
//need to specify a custom callback for unit tests
DynamicNode.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
{
if (propertyAlias == "content")
{
//return the rte type id
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
}
return Guid.Empty;
};
}
[Test]
[Ignore("This test will never work unless DynamicNode is refactored a lot in order to get a list of root nodes since root nodes don't have a parent to look up")]
public override void Is_First_Root_Nodes()
{
base.Is_First_Root_Nodes();
}
[Test]
[Ignore("This test will never work unless DynamicNode is refactored a lot in order to get a list of root nodes since root nodes don't have a parent to look up")]
public override void Is_Not_First_Root_Nodes()
{
base.Is_Not_First_Root_Nodes();
}
[Test]
[Ignore("This test will never work unless DynamicNode is refactored a lot in order to get a list of root nodes since root nodes don't have a parent to look up")]
public override void Is_Position_Root_Nodes()
{
base.Is_Position_Root_Nodes();
}
public override void TearDown()
{
base.TearDown();
PluginManager.Current.AssembliesToScan = null;
}
protected override dynamic GetDynamicNode(int id)
{
//var template = Template.MakeNew("test", new User(0));
//var ctx = GetUmbracoContext("/test", template.Id);
var ctx = GetUmbracoContext("/test", 1234);
var contentStore = new DefaultPublishedContentStore();
var node = new DynamicNode(
new DynamicBackingItem(
new Node(ctx.GetXml().SelectSingleNode("//*[@id='" + id + "' and @isDoc]"))));
Assert.IsNotNull(node);
return (dynamic)node;
}
}
}
@@ -1,9 +1,7 @@
using System.Collections.Generic;
using Umbraco.Core.Dynamics;
using Umbraco.Core.Models;
using Umbraco.Web.Models;
namespace Umbraco.Tests.DynamicDocument
namespace Umbraco.Tests.PublishedContent
{
public static class DynamicPublishedContentCustomExtensionMethods
{
@@ -1,61 +1,22 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NUnit.Framework;
using Umbraco.Core.Dynamics;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.Routing;
using Umbraco.Web;
using Umbraco.Web.Models;
using Umbraco.Web.Routing;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic;
using umbraco.cms.businesslogic.template;
using umbraco.cms.businesslogic.web;
namespace Umbraco.Tests.DynamicDocument
namespace Umbraco.Tests.PublishedContent
{
[TestFixture]
[TestFixture]
public class DynamicPublishedContentTests : DynamicDocumentTestsBase<DynamicPublishedContent, DynamicPublishedContentList>
{
public override void Initialize()
{
base.Initialize();
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
new[]
{
typeof(DatePickerPropertyEditorValueConverter),
typeof(TinyMcePropertyEditorValueConverter),
typeof(YesNoPropertyEditorValueConverter)
});
//need to specify a custom callback for unit tests
DynamicPublishedContent.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
{
if (propertyAlias == "content")
{
//return the rte type id
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
}
return Guid.Empty;
};
var rCtx = GetRoutingContext("/test", 1234);
UmbracoContext.Current = rCtx.UmbracoContext;
PublishedContentStoreResolver.Current = new PublishedContentStoreResolver(new DefaultPublishedContentStore());
}
public override void TearDown()
{
base.TearDown();
PropertyEditorValueConvertersResolver.Reset();
PublishedContentStoreResolver.Reset();
UmbracoContext.Current = null;
}
internal DynamicPublishedContent GetNode(int id)
@@ -86,6 +47,7 @@ namespace Umbraco.Tests.DynamicDocument
Assert.AreEqual("Hello world!" + 123 + false, asDynamic.DynamicDocumentMultiParam("Hello world!", 123, false));
Assert.AreEqual("Hello world!" + 123 + false, asDynamic.Children.DynamicDocumentListMultiParam("Hello world!", 123, false));
Assert.AreEqual("Hello world!" + 123 + false, asDynamic.Children.DynamicDocumentEnumerableMultiParam("Hello world!", 123, false));
}
[Test]
@@ -0,0 +1,145 @@
using System;
using System.Diagnostics;
using Microsoft.CSharp.RuntimeBinder;
using NUnit.Framework;
using Umbraco.Core.Dynamics;
using System.Linq;
namespace Umbraco.Tests.PublishedContent
{
[TestFixture]
public class DynamicXmlTests
{
[Test]
public void Custom_Extension_Method_Legacy()
{
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
var typedXml = new global::umbraco.MacroEngines.DynamicXml(xml);
dynamic dynamicXml = typedXml;
//we haven't explicitly defined ElementAt so this will dynamically invoke this method
var element = dynamicXml.ElementAt(0);
Assert.AreEqual("1057", Enumerable.First(element.BaseElement.Elements()).Attribute("id").Value);
}
[Test]
public void Custom_Extension_Method()
{
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
var typedXml = new DynamicXml(xml);
dynamic dynamicXml = typedXml;
//we haven't explicitly defined ElementAt so this will dynamically invoke this method
var element = dynamicXml.ElementAt(0);
Assert.AreEqual("1057", Enumerable.First(element.BaseElement.Elements()).Attribute("id").Value);
}
[Test]
public void Take_Legacy()
{
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
var typedXml = new global::umbraco.MacroEngines.DynamicXml(xml);
dynamic dynamicXml = typedXml;
var typedTaken = typedXml.Take(1);
var dynamicTaken = dynamicXml.Take(1);
Assert.AreEqual(1, typedTaken.Count());
Assert.AreEqual(1, Enumerable.Count(dynamicTaken));
Assert.AreEqual("1057", typedTaken.ElementAt(0).BaseElement.Elements().First().Attribute("id").Value);
Assert.AreEqual("1057", Enumerable.First(Enumerable.ElementAt(dynamicTaken, 0).BaseElement.Elements()).Attribute("id").Value);
}
[Test]
public void Take()
{
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
var typedXml = new DynamicXml(xml);
dynamic dynamicXml = typedXml;
var typedTaken = typedXml.Take(1);
var dynamicTaken = dynamicXml.Take(1);
Assert.AreEqual(1, typedTaken.Count());
Assert.AreEqual(1, Enumerable.Count(dynamicTaken));
Assert.AreEqual("1057", typedTaken.ElementAt(0).BaseElement.Elements().First().Attribute("id").Value);
Assert.AreEqual("1057", Enumerable.First(Enumerable.ElementAt(dynamicTaken, 0).BaseElement.Elements()).Attribute("id").Value);
}
[Test]
public void Ensure_Legacy_Objects_Are_Returned()
{
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
var mediaItems = new global::umbraco.MacroEngines.DynamicXml(xml);
//Debug.WriteLine("full xml = {0}", mediaItems.ToXml());
if (mediaItems.Count() != 0)
{
foreach (dynamic item in mediaItems)
{
Type itemType = item.GetType();
Debug.WriteLine("item type = {0}", itemType);
dynamic image = item.Image;
Type imageType = image.GetType();
Debug.WriteLine("image type = {0}", imageType);
//ensure they are the same
Assert.AreEqual(itemType, imageType);
//ensure they are legacy
Assert.AreEqual(typeof(global::umbraco.MacroEngines.DynamicXml), itemType);
Assert.AreEqual(typeof(global::umbraco.MacroEngines.DynamicXml), imageType);
}
}
}
/// <summary>
/// Test the current Core class
/// </summary>
[Test]
public void Find_Test_Core_Class()
{
RunFindTest(x => new DynamicXml(x));
}
/// <summary>
/// Tests the macroEngines legacy class
/// </summary>
[Test]
public void Find_Test_Legacy_Class()
{
RunFindTest(x => new global::umbraco.MacroEngines.DynamicXml(x));
}
private void RunFindTest(Func<string, dynamic> getDynamicXml)
{
var xmlstring = @"<test>
<item id='1' name='test 1' value='found 1'/>
<item id='2' name='test 2' value='found 2'/>
<item id='3' name='test 3' value='found 3'/>
</test>";
dynamic dXml = getDynamicXml(xmlstring);
var result1 = dXml.Find("@name", "test 1");
var result2 = dXml.Find("@name", "test 2");
var result3 = dXml.Find("@name", "test 3");
var result4 = dXml.Find("@name", "dont find");
Assert.AreEqual("found 1", result1.value);
Assert.AreEqual("found 2", result2.value);
Assert.AreEqual("found 3", result3.value);
Assert.Throws<RuntimeBinderException>(() =>
{
//this will throw because result4 is not found
var temp = result4.value;
});
}
}
}
@@ -0,0 +1,82 @@
using System;
using System.IO;
using System.Linq;
using Lucene.Net.Documents;
using NUnit.Framework;
using Umbraco.Core.Configuration;
using Umbraco.Tests.TestHelpers.ExamineHelpers;
using umbraco.MacroEngines;
namespace Umbraco.Tests.PublishedContent
{
public class LegacyExamineBackedMediaTests : PublishedContentTestBase
{
public override void Initialize()
{
base.Initialize();
UmbracoSettings.ForceSafeAliases = true;
UmbracoSettings.UmbracoLibraryCacheDuration = 1800;
UmbracoSettings.ForceSafeAliases = true;
}
public override void TearDown()
{
base.TearDown();
}
[Test]
public void Ensure_Children_Are_Sorted()
{
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
var indexInit = new IndexInitializer();
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
indexer.RebuildIndex();
var searcher = indexInit.GetUmbracoSearcher(newIndexFolder);
var result = searcher.Search(searcher.CreateSearchCriteria().Id(1111).Compile());
Assert.IsNotNull(result);
Assert.AreEqual(1, result.TotalItemCount);
var searchItem = result.First();
var backedMedia = new ExamineBackedMedia(searchItem, indexer, searcher);
var children = backedMedia.ChildrenAsList.Value;
var currSort = 0;
for (var i = 0; i < children.Count(); i++)
{
Assert.GreaterOrEqual(children[i].SortOrder, currSort);
currSort = children[i].SortOrder;
}
}
[Test]
public void Ensure_Result_Has_All_Values()
{
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
var indexInit = new IndexInitializer();
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
indexer.RebuildIndex();
var searcher = indexInit.GetUmbracoSearcher(newIndexFolder);
var result = searcher.Search(searcher.CreateSearchCriteria().Id(1111).Compile());
Assert.IsNotNull(result);
Assert.AreEqual(1, result.TotalItemCount);
var searchItem = result.First();
var backedMedia = new ExamineBackedMedia(searchItem, indexer, searcher);
Assert.AreEqual(searchItem.Id, backedMedia.Id);
Assert.AreEqual(searchItem.Fields["sortOrder"], backedMedia.SortOrder.ToString());
Assert.AreEqual(searchItem.Fields["urlName"], backedMedia.UrlName);
Assert.AreEqual(DateTools.StringToDate(searchItem.Fields["createDate"]), backedMedia.CreateDate);
Assert.AreEqual(DateTools.StringToDate(searchItem.Fields["updateDate"]), backedMedia.UpdateDate);
Assert.AreEqual(Guid.Parse(searchItem.Fields["version"]), backedMedia.Version);
Assert.AreEqual(searchItem.Fields["level"], backedMedia.Level.ToString());
Assert.AreEqual(searchItem.Fields["writerID"], backedMedia.WriterID.ToString());
Assert.AreEqual(searchItem.Fields["writerID"], backedMedia.CreatorID.ToString()); //there's only writerId in the xml
Assert.AreEqual(searchItem.Fields["writerName"], backedMedia.CreatorName);
Assert.AreEqual(searchItem.Fields["writerName"], backedMedia.WriterName); //tehre's only writer name in the xml
}
}
}
@@ -9,7 +9,7 @@ using Umbraco.Core.Models;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
namespace Umbraco.Tests.DynamicDocument
namespace Umbraco.Tests.PublishedContent
{
/// <summary>
/// Unit tests for IPublishedContent and extensions
@@ -0,0 +1,57 @@
using System;
using System.IO;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
namespace Umbraco.Tests.PublishedContent
{
/// <summary>
/// Abstract base class for tests for published content and published media
/// </summary>
public abstract class PublishedContentTestBase : BaseRoutingTest
{
public override void Initialize()
{
base.Initialize();
UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
new[]
{
typeof(DatePickerPropertyEditorValueConverter),
typeof(TinyMcePropertyEditorValueConverter),
typeof(YesNoPropertyEditorValueConverter)
});
//need to specify a custom callback for unit tests
PublishedContentHelper.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
{
if (propertyAlias == "content")
{
//return the rte type id
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
}
return Guid.Empty;
};
var rCtx = GetRoutingContext("/test", 1234);
UmbracoContext.Current = rCtx.UmbracoContext;
PublishedContentStoreResolver.Current = new PublishedContentStoreResolver(new DefaultPublishedContentStore());
PublishedMediaStoreResolver.Current = new PublishedMediaStoreResolver(new DefaultPublishedMediaStore());
}
public override void TearDown()
{
base.TearDown();
PropertyEditorValueConvertersResolver.Reset();
PublishedContentStoreResolver.Reset();
PublishedMediaStoreResolver.Reset();
UmbracoContext.Current = null;
}
}
}
@@ -1,20 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Models;
namespace Umbraco.Tests.DynamicDocument
namespace Umbraco.Tests.PublishedContent
{
/// <summary>
/// Tests the typed extension methods on IPublishedContent the same way we test the dynamic ones
/// Tests the methods on IPublishedContent using the DefaultPublishedContentStore
/// </summary>
[TestFixture]
public class PublishedContentTests : BaseWebTest
public class PublishedContentTests : PublishedContentTestBase
{
protected override bool RequiresDbSetup
{
@@ -35,23 +36,24 @@ namespace Umbraco.Tests.DynamicDocument
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[this/is/my/alias, anotheralias]]></umbracoUrlAlias>
<umbracoNaviHide>1</umbracoNaviHide>
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
<content><![CDATA[<div>This is some content</div>]]></content>
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
<content><![CDATA[]]></content>
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
<creatorName><![CDATA[Custom data with same property name as the member name]]></creatorName>
</Home>
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc="""">
</Home>
<CustomDocument id=""1177"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""custom sub 1"" urlName=""custom-sub-1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1177"" isDoc="""" />
<CustomDocument id=""1178"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-16T14:23:35"" nodeName=""custom sub 2"" urlName=""custom-sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1178"" isDoc="""" />
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc="""">
<content><![CDATA[]]></content>
<umbracoNaviHide>1</umbracoNaviHide>
</Home>
<CustomDocument id=""1177"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""custom sub 1"" urlName=""custom-sub-1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1177"" isDoc="""" />
<CustomDocument id=""1178"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-16T14:23:35"" nodeName=""custom sub 2"" urlName=""custom-sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1178"" isDoc="""" />
</Home>
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
</Home>
<CustomDocument id=""4444"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444"" isDoc="""">
<CustomDocument id=""4444"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444"" isDoc="""">
<selectedNodes><![CDATA[1172,1176,1173]]></selectedNodes>
</CustomDocument>
</Home>
@@ -62,38 +64,12 @@ namespace Umbraco.Tests.DynamicDocument
public override void Initialize()
{
base.Initialize();
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
new[]
{
typeof(DatePickerPropertyEditorValueConverter),
typeof(TinyMcePropertyEditorValueConverter),
typeof(YesNoPropertyEditorValueConverter)
});
//need to specify a custom callback for unit tests
DynamicPublishedContent.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
{
if (propertyAlias == "content")
{
//return the rte type id
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
}
return Guid.Empty;
};
var umbCtx = GetUmbracoContext("/test", 1234);
UmbracoContext.Current = umbCtx;
PublishedContentStoreResolver.Current = new PublishedContentStoreResolver(new DefaultPublishedContentStore());
}
public override void TearDown()
{
base.TearDown();
PropertyEditorValueConvertersResolver.Reset();
PublishedContentStoreResolver.Reset();
UmbracoContext.Current = null;
}
internal IPublishedContent GetNode(int id)
@@ -105,6 +81,136 @@ namespace Umbraco.Tests.DynamicDocument
return doc;
}
[Test]
public void Is_Last_From_Where_Filter_Dynamic_Linq()
{
var doc = GetNode(1173);
foreach (var d in doc.Children.Where("Visible"))
{
if (d.Id != 1178)
{
Assert.IsFalse(d.IsLast());
}
else
{
Assert.IsTrue(d.IsLast());
}
}
}
[Test]
public void Is_Last_From_Where_Filter()
{
var doc = GetNode(1173);
foreach (var d in doc.Children.Where(x => x.IsVisible()))
{
if (d.Id != 1178)
{
Assert.IsFalse(d.IsLast());
}
else
{
Assert.IsTrue(d.IsLast());
}
}
}
[Test]
public void Is_Last_From_Take()
{
var doc = GetNode(1173);
foreach (var d in doc.Children.Take(3))
{
if (d.Id != 1178)
{
Assert.IsFalse(d.IsLast());
}
else
{
Assert.IsTrue(d.IsLast());
}
}
}
[Test]
public void Is_Last_From_Skip()
{
var doc = GetNode(1173);
foreach (var d in doc.Children.Skip(1))
{
if (d.Id != 1176)
{
Assert.IsFalse(d.IsLast());
}
else
{
Assert.IsTrue(d.IsLast());
}
}
}
[Test]
public void Is_Last_From_Concat()
{
var doc = GetNode(1173);
foreach (var d in doc.Children.Concat(new[] { GetNode(1175), GetNode(4444) }))
{
if (d.Id != 4444)
{
Assert.IsFalse(d.IsLast());
}
else
{
Assert.IsTrue(d.IsLast());
}
}
}
[Test]
public void Descendants_Ordered_Properly()
{
var doc = GetNode(1046);
var currentLevel = 0;
var lastSortOrder = 0;
var levelChangesAt = new[] { 1046, 1173, 1174 };
foreach (var d in doc.DescendantsOrSelf())
{
if (levelChangesAt.Contains(d.Id))
{
Assert.Greater(d.Level, currentLevel);
currentLevel = d.Level;
}
else
{
Assert.AreEqual(currentLevel, d.Level);
Assert.Greater(d.SortOrder, lastSortOrder);
}
lastSortOrder = d.SortOrder;
}
}
[Test]
public void Get_Property_Value_Uses_Converter()
{
var doc = GetNode(1173);
var propVal = doc.GetPropertyValue("content");
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(propVal.GetType()));
Assert.AreEqual("<div>This is some content</div>", propVal.ToString());
var propVal2 = doc.GetPropertyValue<IHtmlString>("content");
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(propVal2.GetType()));
Assert.AreEqual("<div>This is some content</div>", propVal2.ToString());
}
[Test]
public void Complex_Linq()
{
@@ -113,7 +219,7 @@ namespace Umbraco.Tests.DynamicDocument
var result = doc.Ancestors().OrderBy(x => x.Level)
.Single()
.Descendants()
.FirstOrDefault(x => x.GetPropertyValue("selectedNodes", "").Split(',').Contains("1173"));
.FirstOrDefault(x => x.GetPropertyValue<string>("selectedNodes", "").Split(',').Contains("1173"));
Assert.IsNotNull(result);
}
@@ -124,11 +230,11 @@ namespace Umbraco.Tests.DynamicDocument
var doc = GetNode(1173);
Assert.AreEqual(0, doc.Index());
doc = GetNode(1176);
Assert.AreEqual(1, doc.Index());
doc = GetNode(1177);
Assert.AreEqual(2, doc.Index());
doc = GetNode(1178);
Assert.AreEqual(3, doc.Index());
doc = GetNode(1177);
Assert.AreEqual(1, doc.Index());
doc = GetNode(1178);
Assert.AreEqual(2, doc.Index());
}
[Test]
@@ -255,17 +361,7 @@ namespace Umbraco.Tests.DynamicDocument
Assert.IsTrue(visible.IsVisible());
}
[Test]
public void Ensure_TinyMCE_Converted_Type_User_Property()
{
var doc = GetNode(1173);
throw new NotImplementedException("We currently don't have an extension method to return the formatted value using IPropertyValueConverter! This currently only works in the dynamic implementation");
//Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(doc.GetPropertyValue().Content.GetType()));
//Assert.AreEqual("<div>This is some content</div>", doc.Content.ToString());
}
[Test]
public void Ancestor_Or_Self()
{
@@ -326,8 +422,8 @@ namespace Umbraco.Tests.DynamicDocument
Assert.IsNotNull(result);
Assert.AreEqual(6, result.Count());
Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175 }));
Assert.AreEqual(7, result.Count());
Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 }));
}
[Test]
@@ -369,7 +465,7 @@ namespace Umbraco.Tests.DynamicDocument
[Test]
public void Next_Without_Sibling()
{
var doc = GetNode(1178);
var doc = GetNode(1176);
Assert.IsNull(doc.Next());
}
@@ -391,7 +487,7 @@ namespace Umbraco.Tests.DynamicDocument
Assert.IsNotNull(result);
Assert.AreEqual((int)1174, (int)result.Id);
Assert.AreEqual((int)1178, (int)result.Id);
}
}
}
@@ -0,0 +1,335 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using System.Xml.XPath;
using Examine;
using Examine.LuceneEngine;
using Examine.LuceneEngine.Providers;
using Lucene.Net.Analysis.Standard;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.ExamineHelpers;
using Umbraco.Web;
using UmbracoExamine;
using UmbracoExamine.DataServices;
using umbraco.BusinessLogic;
using System.Linq;
namespace Umbraco.Tests.PublishedContent
{
/// <summary>
/// Tests the typed extension methods on IPublishedContent using the DefaultPublishedMediaStore
/// </summary>
[TestFixture, RequiresSTA]
public class PublishedMediaTests : PublishedContentTestBase
{
public override void Initialize()
{
base.Initialize();
UmbracoSettings.ForceSafeAliases = true;
UmbracoSettings.UmbracoLibraryCacheDuration = 1800;
UmbracoSettings.ForceSafeAliases = true;
}
public override void TearDown()
{
base.TearDown();
}
/// <summary>
/// Shared with PublishMediaStoreTests
/// </summary>
/// <param name="id"></param>
/// <param name="umbracoContext"></param>
/// <returns></returns>
internal static IPublishedContent GetNode(int id, UmbracoContext umbracoContext)
{
var ctx = umbracoContext;
var mediaStore = new DefaultPublishedMediaStore();
var doc = mediaStore.GetDocumentById(ctx, id);
Assert.IsNotNull(doc);
return doc;
}
private IPublishedContent GetNode(int id)
{
return GetNode(id, GetUmbracoContext("/test", 1234));
}
[Test]
public void Ensure_Children_Sorted_With_Examine()
{
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
var indexInit = new IndexInitializer();
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
indexer.RebuildIndex();
var store = new DefaultPublishedMediaStore(
indexInit.GetUmbracoSearcher(newIndexFolder),
indexInit.GetUmbracoIndexer(newIndexFolder));
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 1111);
var rootChildren = publishedMedia.Children().ToArray();
var currSort = 0;
for (var i = 0; i < rootChildren.Count(); i++)
{
Assert.GreaterOrEqual(rootChildren[i].SortOrder, currSort);
currSort = rootChildren[i].SortOrder;
}
}
[Test]
public void Children_With_Examine()
{
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
var indexInit = new IndexInitializer();
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
indexer.RebuildIndex();
var store = new DefaultPublishedMediaStore(
indexInit.GetUmbracoSearcher(newIndexFolder),
indexInit.GetUmbracoIndexer(newIndexFolder));
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 1111);
var rootChildren = publishedMedia.Children();
Assert.IsTrue(rootChildren.Select(x => x.Id).ContainsAll(new[] { 2222, 1113, 1114, 1115, 1116 }));
var publishedChild1 = store.GetDocumentById(GetUmbracoContext("/test", 1234), 2222);
var subChildren = publishedChild1.Children();
Assert.IsTrue(subChildren.Select(x => x.Id).ContainsAll(new[] { 2112 }));
}
[Test]
public void Descendants_With_Examine()
{
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
var indexInit = new IndexInitializer();
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
indexer.RebuildIndex();
var store = new DefaultPublishedMediaStore(
indexInit.GetUmbracoSearcher(newIndexFolder),
indexInit.GetUmbracoIndexer(newIndexFolder));
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 1111);
var rootDescendants = publishedMedia.Descendants();
Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { 2112, 2222, 1113, 1114, 1115, 1116 }));
var publishedChild1 = store.GetDocumentById(GetUmbracoContext("/test", 1234), 2222);
var subDescendants = publishedChild1.Descendants();
Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { 2112, 3113 }));
}
[Test]
public void DescendantsOrSelf_With_Examine()
{
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
var indexInit = new IndexInitializer();
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
indexer.RebuildIndex();
var store = new DefaultPublishedMediaStore(
indexInit.GetUmbracoSearcher(newIndexFolder),
indexInit.GetUmbracoIndexer(newIndexFolder));
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 1111);
var rootDescendants = publishedMedia.DescendantsOrSelf();
Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { 1111, 2112, 2222, 1113, 1114, 1115, 1116 }));
var publishedChild1 = store.GetDocumentById(GetUmbracoContext("/test", 1234), 2222);
var subDescendants = publishedChild1.DescendantsOrSelf();
Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { 2222, 2112, 3113 }));
}
[Test]
public void Ancestors_With_Examine()
{
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
var indexInit = new IndexInitializer();
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
indexer.RebuildIndex();
var store = new DefaultPublishedMediaStore(
indexInit.GetUmbracoSearcher(newIndexFolder),
indexInit.GetUmbracoIndexer(newIndexFolder));
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 3113);
var ancestors = publishedMedia.Ancestors();
Assert.IsTrue(ancestors.Select(x => x.Id).ContainsAll(new[] { 2112, 2222, 1111 }));
}
[Test]
public void AncestorsOrSelf_With_Examine()
{
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
var indexInit = new IndexInitializer();
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
indexer.RebuildIndex();
var store = new DefaultPublishedMediaStore(
indexInit.GetUmbracoSearcher(newIndexFolder),
indexInit.GetUmbracoIndexer(newIndexFolder));
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 3113);
var ancestors = publishedMedia.AncestorsOrSelf();
Assert.IsTrue(ancestors.Select(x => x.Id).ContainsAll(new[] { 3113, 2112, 2222, 1111 }));
}
[Test]
public void Children_Without_Examine()
{
var user = new User(0);
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
var publishedMedia = GetNode(mRoot.Id);
var rootChildren = publishedMedia.Children();
Assert.IsTrue(rootChildren.Select(x => x.Id).ContainsAll(new[] {mChild1.Id, mChild2.Id, mChild3.Id}));
var publishedChild1 = GetNode(mChild1.Id);
var subChildren = publishedChild1.Children();
Assert.IsTrue(subChildren.Select(x => x.Id).ContainsAll(new[] { mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
}
[Test]
public void Descendants_Without_Examine()
{
var user = new User(0);
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
var publishedMedia = GetNode(mRoot.Id);
var rootDescendants = publishedMedia.Descendants();
Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { mChild1.Id, mChild2.Id, mChild3.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
var publishedChild1 = GetNode(mChild1.Id);
var subDescendants = publishedChild1.Descendants();
Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
}
[Test]
public void DescendantsOrSelf_Without_Examine()
{
var user = new User(0);
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
var publishedMedia = GetNode(mRoot.Id);
var rootDescendantsOrSelf = publishedMedia.DescendantsOrSelf();
Assert.IsTrue(rootDescendantsOrSelf.Select(x => x.Id).ContainsAll(
new[] { mRoot.Id, mChild1.Id, mChild2.Id, mChild3.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
var publishedChild1 = GetNode(mChild1.Id);
var subDescendantsOrSelf = publishedChild1.DescendantsOrSelf();
Assert.IsTrue(subDescendantsOrSelf.Select(x => x.Id).ContainsAll(
new[] { mChild1.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
}
[Test]
public void Parent_Without_Examine()
{
var user = new User(0);
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
var publishedRoot = GetNode(mRoot.Id);
Assert.AreEqual(null, publishedRoot.Parent);
var publishedChild1 = GetNode(mChild1.Id);
Assert.AreEqual(mRoot.Id, publishedChild1.Parent.Id);
var publishedSubChild1 = GetNode(mSubChild1.Id);
Assert.AreEqual(mChild1.Id, publishedSubChild1.Parent.Id);
}
[Test]
public void Ancestors_Without_Examine()
{
var user = new User(0);
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
var publishedSubChild1 = GetNode(mSubChild1.Id);
Assert.IsTrue(publishedSubChild1.Ancestors().Select(x => x.Id).ContainsAll(new[] {mChild1.Id, mRoot.Id}));
}
[Test]
public void AncestorsOrSelf_Without_Examine()
{
var user = new User(0);
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
var publishedSubChild1 = GetNode(mSubChild1.Id);
Assert.IsTrue(publishedSubChild1.AncestorsOrSelf().Select(x => x.Id).ContainsAll(
new[] { mSubChild1.Id, mChild1.Id, mRoot.Id }));
}
}
}
@@ -1,19 +1,30 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Models;
namespace Umbraco.Tests.DynamicDocument
namespace Umbraco.Tests.PublishedContent
{
[TestFixture]
public class StronglyTypedQueryTests : BaseWebTest
public class StronglyTypedQueryTests : PublishedContentTestBase
{
public override void Initialize()
{
base.Initialize();
}
public override void TearDown()
{
base.TearDown();
}
protected override bool RequiresDbSetup
{
get { return false; }
@@ -69,7 +80,8 @@ namespace Umbraco.Tests.DynamicDocument
Assert.IsNotNull(doc);
return doc;
}
[Test]
public void Type_Test()
{
@@ -79,6 +91,7 @@ namespace Umbraco.Tests.DynamicDocument
Assert.AreEqual("John Smith", result[1].ArticleAuthor);
}
[Test]
public void As_Test()
{
@@ -203,7 +216,7 @@ namespace Umbraco.Tests.DynamicDocument
}
}
public class PublishedContentWrapper : IPublishedContent
public class PublishedContentWrapper : IPublishedContent, IOwnerCollectionAware<IPublishedContent>
{
protected IPublishedContent WrappedContent { get; private set; }
@@ -293,6 +306,46 @@ namespace Umbraco.Tests.DynamicDocument
{
return WrappedContent.GetProperty(alias);
}
private IEnumerable<IPublishedContent> _ownersCollection;
/// <summary>
/// Need to get/set the owner collection when an item is returned from the result set of a query
/// </summary>
/// <remarks>
/// Based on this issue here: http://issues.umbraco.org/issue/U4-1797
/// </remarks>
IEnumerable<IPublishedContent> IOwnerCollectionAware<IPublishedContent>.OwnersCollection
{
get
{
var publishedContentBase = WrappedContent as IOwnerCollectionAware<IPublishedContent>;
if (publishedContentBase != null)
{
return publishedContentBase.OwnersCollection;
}
//if the owners collection is null, we'll default to it's siblings
if (_ownersCollection == null)
{
//get the root docs if parent is null
_ownersCollection = this.Siblings();
}
return _ownersCollection;
}
set
{
var publishedContentBase = WrappedContent as IOwnerCollectionAware<IPublishedContent>;
if (publishedContentBase != null)
{
publishedContentBase.OwnersCollection = value;
}
else
{
_ownersCollection = value;
}
}
}
}
public partial class HomeContentItem : ContentPageContentItem
@@ -18,7 +18,7 @@ namespace Umbraco.Tests.Resolvers
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager();
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
@@ -27,7 +27,7 @@ namespace Umbraco.Tests.Resolvers
};
ActionsResolver.Current = new ActionsResolver(
PluginManager.Current.ResolveActions());
() => PluginManager.Current.ResolveActions());
Resolution.Freeze();
}
@@ -0,0 +1,143 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Tests.Resolvers
{
[TestFixture]
public class LazyManyObjectResolverTests
{
[SetUp]
public void Initialize()
{
}
[TearDown]
public void TearDown()
{
Resolution.IsFrozen = false;
}
[Test]
public void Ensure_Lazy_Type_Resolution()
{
var resolver = new LazyResolver(new[] {new Lazy<Type>(() => typeof (TransientObject3))});
resolver.AddType<TransientObject1>();
resolver.AddType(new Lazy<Type>(() => typeof(TransientObject2)));
Resolution.Freeze();
Assert.IsFalse(resolver.HasResolvedTypes);
var instances1 = resolver.Objects;
Assert.IsTrue(resolver.HasResolvedTypes);
Assert.AreEqual(3, instances1.Count());
Assert.IsTrue(instances1.Select(x => x.GetType()).ContainsAll(new []{typeof(TransientObject1), typeof(TransientObject2), typeof(TransientObject3)}));
}
[Test]
public void Type_List_Delegates_Combination()
{
Func<IEnumerable<Type>> types = () => new[] { typeof(TransientObject3), typeof(TransientObject2) };
var resolver = new LazyResolver(types);
resolver.AddTypeListDelegate(() => new[] { typeof(TransientObject1)});
Resolution.Freeze();
var instances1 = resolver.Objects;
Assert.AreEqual(3, instances1.Count());
Assert.IsTrue(instances1.Select(x => x.GetType()).ContainsAll(new[] { typeof(TransientObject1), typeof(TransientObject2), typeof(TransientObject3) }));
}
[Test]
public void Type_List_Delegates_And_Lazy_Type_Combination()
{
Func<IEnumerable<Type>> types = () => new[] { typeof(TransientObject3) };
var resolver = new LazyResolver(types);
resolver.AddType(new Lazy<Type>(() => typeof(TransientObject2)));
resolver.AddType<TransientObject1>();
Resolution.Freeze();
var instances1 = resolver.Objects;
Assert.AreEqual(3, instances1.Count());
Assert.IsTrue(instances1.Select(x => x.GetType()).ContainsAll(new[] { typeof(TransientObject1), typeof(TransientObject2), typeof(TransientObject3) }));
}
[Test]
public void Throws_If_Duplication()
{
Func<IEnumerable<Type>> types = () => new[] { typeof(TransientObject3), typeof(TransientObject2), typeof(TransientObject1) };
var resolver = new LazyResolver(types);
//duplicate, but will not throw here
resolver.AddType<TransientObject1>();
Resolution.Freeze();
Assert.Throws<InvalidOperationException>(() =>
{
var instances = resolver.Objects;
});
}
#region Test classes
private interface ITestInterface
{
}
private class TransientObject1 : ITestInterface
{
}
private class TransientObject2 : ITestInterface
{
}
private class TransientObject3 : ITestInterface
{
}
private sealed class LazyResolver : LazyManyObjectsResolverBase<LazyResolver, ITestInterface>
{
public LazyResolver()
: base(ObjectLifetimeScope.Transient)
{
}
public LazyResolver(IEnumerable<Lazy<Type>> values)
:base (values, ObjectLifetimeScope.Transient)
{
}
public LazyResolver(Func<IEnumerable<Type>> typeList)
: base(typeList, ObjectLifetimeScope.Transient)
{
}
public IEnumerable<ITestInterface> Objects
{
get { return Values; }
}
}
#endregion
}
}
@@ -18,7 +18,7 @@ namespace Umbraco.Tests.Resolvers
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager();
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
@@ -27,7 +27,7 @@ namespace Umbraco.Tests.Resolvers
};
MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver(
PluginManager.Current.ResolveMacroRenderings());
() => PluginManager.Current.ResolveMacroRenderings());
Resolution.Freeze();
}

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