Compare commits

...

145 Commits

Author SHA1 Message Date
Sebastiaan Janssen 4935525591 Merge pull request #147 from AndyButland/u4-2958
Fix for issue U4-2958 Member can edit & Show on profile do not persist on Member Type editor
2013-10-05 10:04:08 -07:00
Andy Butland 693778fe74 Fixed issue where member type properties would not persist after first save without reloading page 2013-10-02 21:20:05 +02:00
Sebastiaan Janssen 8eee7cae2f Merge branch '6.1.6' 2013-09-30 16:10:14 +02:00
Sebastiaan Janssen 226e35d65a NuSpec update: we can only accept a specific version of MySQL 2013-09-30 14:32:06 +02:00
Sebastiaan Janssen cdda69c4cd U4-2788 Error installing Umbraco 6.1.5 with SQL CE 4 option 2013-09-30 12:39:28 +02:00
Shannon 0cff484113 fixes unit test 2013-09-30 12:12:17 +02:00
Shannon 830fde372e Fixes EditUser.aspx 2013-09-30 11:49:31 +02:00
Shannon 35f65a2c64 re-enables LoadMinimalDocument and adds this to the optimized check, even in optimized model the OnRenderNode can still execute with a minimal doc. 2013-09-30 10:55:38 +02:00
Shannon e5320f0abd Obsoletes the LoadMinimalDocument flag since it no longer serves a purpose. 2013-09-30 10:55:26 +02:00
Sebastiaan Janssen 965a7fc500 Fixes: U4-2925 Tree performance is very poor in 6.1.x when having event subscriptions 2013-09-30 10:55:13 +02:00
Sebastiaan Janssen abbf8aeb42 U4-2709 Error after upgrading from 6.1.3 to 6.1.4 2013-09-30 10:49:33 +02:00
Sebastiaan Janssen 328ada2f38 Bump version number 2013-09-30 10:46:08 +02:00
Sebastiaan Janssen 767252cdf1 Creates IDisposeOnRequestEnd and ensures UmbracoContext and UmbracoDatabase implement it, then we only dispose of these types of objects at the end of the request if they are part of the httpcontext items (U4-2738). Fixes: U4-2988 UmbracoObjectTypesExtensions is not thread safe 2013-09-30 10:31:45 +02:00
Sebastiaan Janssen 010d47c68b Fixes U4-2822 Datepicker throws "Specified cast is not valid" when saving through API 2013-09-30 10:23:43 +02:00
Shandem a353f6fb74 Merge pull request #135 from Myster/master
Fix multiple words in search U4-2509
2013-09-11 19:33:47 -07:00
Murray Roke a64efb93b3 Improved search with "and", partial match U4-2509
- added partial matching on each word.
- fixed bug so 'all' words match rather than 'any' words.
2013-09-12 14:30:42 +12:00
Murray Roke cf9f11ff45 Improved admin search splitting query U4-2509 2013-09-12 13:22:14 +12:00
Murray Roke d7481b5ca4 Fix multiple words in search U4-2509
When multiple words are entered in the search field no results are
returned.
This pull req. contains the fix suggested by Tony.
2013-09-12 10:22:59 +12:00
Niels Hartvig 2fb55cb831 Enhanced permission checking on views and snippets
Thanks to Richard Turnbull from NGS Secure Research who discovered a
minor issue that made it possible for authenticated Umbraco Users to
view files beyond their permissions
2013-09-02 14:23:27 +02:00
Sebastiaan Janssen 0e6a926a3f Merge branch '6.1.5' 2013-09-02 12:24:26 +02:00
Sebastiaan Janssen 173ac65eb5 Remove misleading comment as this has been moved out of the if statement 2013-09-02 11:41:13 +02:00
Sebastiaan Janssen 7c28e1aeba Fixed U4-2763 Content rollback generates duplicates 2013-09-02 10:56:42 +02:00
Shannon 5989d19f7f Re-fixes the issue with using IDataValueSetter.SetValue on the DefaultData implementation and ensures that when there is a null value that it reverts to an empty string since this was what the default value was in the Value getter of DefaultData when there was no value. Have added a couple unit tests to support. 2013-09-02 13:27:48 +10:00
Shannon da1c33a034 Fixes unit test 2013-09-02 12:57:56 +10:00
Sebastiaan Janssen 2111a5e31e Fix MySQL install failing on UmbracoServer table 2013-09-01 17:28:22 +02:00
Sebastiaan Janssen 5478de911b Merge pull request #115 from stocksr/6.2.0
U4-516 - Fix DatePicker with time default value
2013-09-01 17:24:03 +02:00
Sebastiaan Janssen 7765acb130 Merge pull request #124 from AndyButland/wip-u4-2759
U4-2759 - member authorise attribute was not restricting for group
2013-09-01 17:23:53 +02:00
Morten Christensen 5640daff32 Fixes U4-2752 ContentService.DeleteVersion and DeleteVersions fail
Signed-off-by: Sebastiaan Janssen <sebastiaan@umbraco.com>
2013-08-31 19:19:25 +02:00
Morten Christensen a1cae3f286 Fixes U4-2731 Document.BeforeMove + Document.AfterMove Doesn't get fired.
Using the legacy Document and Media classes for the .Move and .Copy calls as they already use the new services under the hood, so shouldn't make any noticeable difference except that the legacy events will also work.

Signed-off-by: Sebastiaan Janssen <sebastiaan@umbraco.com>
2013-08-31 19:18:47 +02:00
Shannon d22dbb4654 Fixes U4-2734 Don't set the cache references to null when disposing the UmbracoContext 2013-08-31 11:11:25 +02:00
Stephan 4d5a8298b0 U4-2549 - fix it differently 2013-08-30 12:22:58 +02:00
Stephan 9e2733ce69 U4-2549 - fix issue with last chance content finder
Conflicts:
	src/Umbraco.Web/Umbraco.Web.csproj

Conflicts:
	src/Umbraco.Web/Umbraco.Web.csproj
2013-08-30 12:22:36 +02:00
Sebastiaan Janssen fbfdd8d398 Bump version number 2013-08-30 12:00:33 +02:00
Stephan 2552dffdad U4-2691 - fix issue with alt template and internal redirects 2013-08-30 11:59:28 +02:00
Sebastiaan Janssen 52540165f1 Creating a partial view now inherits from UmbracoTemplatePage (in 6.2.0 there will be 2 snippets, one for UmbracoViewPage<dynamic>, for MVC experts and one for UmbracoTemplatePage, the default). 2013-08-30 11:47:39 +02:00
Shannon 2b408df24c Fixes: U4-2727 PluginManager's TypeList can contain duplicates - updates the locks to be upgradeable read locks, changes over all lists/collecitons to be HashSet<T> this ensures no duplicates and also improves performance. 2013-08-30 10:51:06 +02:00
Shannon d559411187 Fixes U4-2300 6.1.0: Changing a template's parent causes tree to collapse 2013-08-30 10:45:13 +02:00
Sebastiaan Janssen 3a4a6579d3 Fixes: U4-2711 DAMP throws unknown exception on image upload with image cropper 2013-08-30 10:40:29 +02:00
Sebastiaan Janssen 1e76cf67d3 Fix merge problem 2013-08-23 08:57:02 +02:00
Sebastiaan Janssen 61149f8112 Merge branch '6.1.4'
Conflicts:
	.gitignore
	src/Umbraco.Web.UI/install/steps/database.ascx
	src/Umbraco.Web/Umbraco.Web.csproj
	src/Umbraco.Web/umbraco.presentation/umbraco/controls/Images/ImageViewer.ascx.cs
	src/umbraco.editorControls/mediapicker/mediaChooser.cs
2013-08-22 14:46:11 +02:00
Sebastiaan Janssen adb059e0da Revert U4-2511 Locallink:NODEID not working as it was breaking expectations of people running site without this fix 2013-08-22 13:13:32 +02:00
Morten Christensen 4337976887 Merge branch '6.1.4' of https://github.com/umbraco/Umbraco-CMS into 6.1.4 2013-08-22 12:59:08 +02:00
Morten Christensen efe5de87a6 Updating readme for nuget packages 2013-08-22 12:58:53 +02:00
Sebastiaan Janssen 389642946e Merge pull request #85 from rolfis/patch-1
Update sv.xml
2013-08-21 09:03:37 -07:00
rolfis 53d30aa3cb Update sv.xml
Changed {0} to %0% in login screen bottomText to display correct end year of copyright notice.
2013-08-21 16:55:53 +02:00
Shannon e233cffb9d Changes the cache keys in PluginManager to reference a const to make it a bit more clear. 2013-08-21 11:19:27 +10:00
Shannon 9e58ebed24 Merge branch '6.1.4' of https://github.com/umbraco/Umbraco-CMS into 6.1.4 2013-08-21 11:14:59 +10:00
Shannon f51c4e332e Fixes: U4-2653 BeginUmbracoForm should use absolute path with query string URLs without the protocol 2013-08-21 11:14:37 +10:00
Sebastiaan Janssen 03a0a0a0e9 Fix a strange VS2012 build targets problem 2013-08-20 18:06:09 +02:00
Sebastiaan Janssen dcb381770f Fix unit test that was looking at the wrong filename 2013-08-19 12:54:20 +02:00
Sebastiaan Janssen 65db0e69a9 Fixes: U4-2642 Make SQL CE more resilient to server crashes 2013-08-19 12:26:01 +02:00
Sebastiaan Janssen 23c6a91e9c Fixes merge issue 2013-08-19 11:47:53 +02:00
Sebastiaan Janssen a03c6dcf13 Merge pull request #80 from ThomasSkyldahl/6.1.4
UmbracoViewPage.WriteLiteral(object value)  optimized memory usage and combined markup injection
2013-08-19 02:34:13 -07:00
Sebastiaan Janssen 3029d97f33 Merge pull request #78 from dprothero/6.1.4
Fixed membership provider to correctly log failed attempts.
2013-08-19 02:06:15 -07:00
Sebastiaan Janssen f41d967864 Fixes: U4-2637 Error adding a User using AD Membership Provider when no Email Address Defined 2013-08-19 10:41:49 +02:00
Thomas Skyldahl Sørensen 4a481b05d4 Optimized WriteLiteral 2013-08-16 10:09:09 +02:00
Shannon 66c6b5b524 Fixes: U4-2632 Remove the recursive permissions check on the move/copy dialog 2013-08-16 12:46:40 +10:00
Shannon e3b0f71549 Merge branch '6.1.4' of https://github.com/umbraco/Umbraco-CMS into 6.1.4 2013-08-16 12:25:55 +10:00
Shannon 973b466798 Fixes: U4-2627 Ensure that the plugins cache files are named with the machine name 2013-08-16 12:25:38 +10:00
Shandem fa0eef4333 Merge pull request #79 from sniffdk/6.1.4
Moved WriteLiteral method to UmbracoViewPage
2013-08-15 19:12:54 -07:00
Mads Krohn a343a76a26 Moved WriteLiteral method to UmbracoViewPage
When we use a custom model through a custom controller, in our view, we
inherit from UmbracoViewPage, so the WriteLiteral method, which provides
preview badge and miniprofiler code, should be placed there.
2013-08-16 00:01:31 +02:00
Morten Christensen d0a9e3236e Promise for the changed unit test was incorrect, so correcting it in this commit 2013-08-15 10:26:24 +02:00
Morten Christensen b899805ec9 Correcting issue introduced in d3b69e04e1 where the returned IProfile would contain the Username and not the Name. This will have changed the Creator and Writer name in the xml cache to be the Login instead of the Name of the user, so for those that use these fields its important to republish to update the xml cache.
Fixes U4-2628 creatorName and writerName should use username - not loginname. Also verified through file history back to v4.
2013-08-15 10:08:59 +02:00
Morten Christensen 766497e355 Refactoring QueryHelper to be a base class instead.
Fix U4-2607 Creating nodes with special characters causes YSOD
2013-08-14 17:07:21 +02:00
Morten Christensen 67a2a9cfe4 Refactoring the optimized Recycle Bin, so that the Recycle Bin's repository is more independent and easier to use with the new events added to the Content- and MediaService. 2013-08-14 16:12:13 +02:00
dprothero 766ba0c8f5 Fixed membership provider to correctly log failed attempts. 2013-08-13 13:46:32 -07:00
Morten Christensen ca71c59880 Fixes U4-2218 Document Type copy looses property tab assignment 2013-08-13 17:41:35 +02:00
Morten Christensen 6c87cf729a Fixes U4-2592 Cannot delete a node when the node has just a closing bracket in the name. 2013-08-13 11:27:39 +02:00
Shannon 5c63afa31a removed my test examine settings 2013-08-13 18:26:32 +10:00
Shannon fa88768c91 removed my test examine settings 2013-08-13 18:25:39 +10:00
Shannon bfabfd9fa5 Updated to latest Examine version (contains bug fix for U4-2180 Problem with Examine MultiIndexSearcher after upgrading from 4.11.3 to 4.11.8) and removes the partially trusted callers attribute from the PDF lib because itextsharp by default doesn't support med trust. 2013-08-13 15:41:40 +10:00
Shannon aa1c411c8c Fixes U4-2618 PDF indexer does not ensure spaces are added to textual content and fixes med trust compat relating to U4-2180 Problem with Examine MultiIndexSearcher after upgrading from 4.11.3 to 4.11.8 2013-08-13 13:47:57 +10:00
Shannon c52c452b36 Fixes issue relating to the fix for U4-2589 where we need to clear the published db flag for previous versions when creating a new published version. 2013-08-13 11:01:49 +10:00
Morten Christensen 86811fe507 Fixes U4-2397 IContent Properties added with incorrect Value when read from Cache, and adds unit test for verifying types saved and returned for 24 standard DataTypes. 2013-08-12 16:20:32 +02:00
Morten Christensen 363de53b82 Updates query to limit results in subquery for MySql according to U4-2329 Browsing Media Slow in 6.1.1 2013-08-12 12:42:21 +02:00
Shandem 958fb66f2c Merge pull request #73 from florisrobbemont/6.1.3
U4-2596: UmbracoControllerFactory method ReleaseController should be virtual
2013-08-11 18:13:06 -07:00
Morten Christensen 30e12c1367 Final piece to the puzzle for U4-2571 Need to optimize empty recycle bin. Needed to hack around the ordering of items in the recycle bin because of the self-referencing constraint - parentID to id in the umbracoNode table by updating all parentID entries, which bypasses any reference issues with the foreignkey. 2013-08-11 21:12:02 +02:00
Morten Christensen 89ff7d85e2 Correcting DELETE FROM query so it works with sql ce as well. 2013-08-09 17:44:57 +02:00
Shannon 61fbf2cfc6 reverts PersistDeletedItem transaction because i forgot that the Commit() method of the UOW already takes care of the transaction. 2013-08-09 10:52:24 +10:00
Shannon ce847e97a8 Updates the PetaPocoRepositoryBase to ensure that the deletion process is wrapped in a transaction so if any of the processes fail, it all gets rolled back. 2013-08-09 10:07:03 +10:00
Shannon 1e61563f79 Ensures the deletions are wrapped in a transaction - for performance and to mitigate db corruption if one of the deletes fails. 2013-08-09 10:01:28 +10:00
Morten Christensen b4f9985695 Last bits to implement U4-2571 Need to optimize empty recycle bin 2013-08-08 15:12:26 +02:00
Morten Christensen 82f19ede8c Merge branch '6.1.4' of https://github.com/umbraco/Umbraco-CMS into 6.1.4 2013-08-08 10:22:38 +02:00
Shannon 0fbc32a87f Fixes up logic for creating new versions (U4-2589 Save and Publish is not creating version of document) 2013-08-08 10:42:06 +10:00
Floris Robbemont dc2de4b5e7 U4-2596: UmbracoControllerFactory method ReleaseController should be virtual 2013-08-07 15:06:41 +02:00
Shannon 5fce741940 another sln update 2013-08-07 11:53:09 +10:00
Shannon 14e4a8061c removes the vs profiling files from the sln. 2013-08-07 11:49:48 +10:00
Shannon 1b9f071581 Fixes: U4-2589 Save and Publish is not creating version of document and adds a few unit tests 2013-08-07 11:39:25 +10:00
Morten Christensen 79141ef86d Initial work on U4-2571 Need to optimize empty recycle bin 2013-08-06 15:08:05 +02:00
Sebastiaan Janssen 08609a887c Merge branch '6.1.4' of github.com:umbraco/Umbraco-CMS into 6.1.4 2013-08-06 10:24:42 +02:00
Sebastiaan Janssen b11932240c Fixes U4-2587 Regression: Hide Preview Button on nodes that have no template
Now also checks if the template still exists and if it's allowed on that document to determine when to enable the preview button
2013-08-06 10:24:20 +02:00
Shannon d47b4517c1 Fixes unit tests 2013-08-06 13:06:25 +10:00
Morten Christensen 226a13c6e1 Minor adjustment related to U4-2560 Working with ContentService can give 2 versions of a document as "newest" 2013-08-05 14:30:03 +02:00
Shannon d78a03a610 Massively improves performance for the packaging service (converting docs to XML) which is used in republishing the tree. 2013-08-05 13:11:47 +10:00
Shannon b7a1123319 U4-2579 BulkPublishController causes YSOD when there are invalid child elements due to InvalidProperties having a null reference 2013-08-02 16:23:32 +10:00
Shannon 7e9cad34db Creates an SQL Server version check for bulk sql imports. 2013-08-02 16:01:54 +10:00
Shannon c4b44ea0e3 Fixes: U4-2577 Can't save umbraco user - without re-filling in the password
Fixes: U4-541 Wrong dictionary key when using in backend template names
This changes the way that the value that is stored in the auth cookie. Previously we just stored a GUID which was the user's contextid stored in the db, now we store encrypted values of a few necessary user objects. In 6.2 we'll actually set a real .Net user object on the HttpContext. For now, the http module will simply just ensure that the culture is set correctly for the currently logged in user.
2013-08-02 15:16:04 +10:00
Sebastiaan Janssen 3435a75e9e U4-2553 Double tabs when installing package that makes use of Dictionary Items to translate document types
Forgto to commit a file :)
2013-08-01 14:39:22 +02:00
Sebastiaan Janssen bdb6c5768a U4-2553 Double tabs when installing package that makes use of Dictionary Items to translate document types
Added GetRawCaptionById method for the packager so the generated XML is correct
2013-08-01 13:40:23 +02:00
Sebastiaan Janssen 87a3c53e22 Merge branch '6.1.4' of github.com:umbraco/Umbraco-CMS into 6.1.4 2013-07-31 18:31:56 +02:00
Sebastiaan Janssen 898d25f3cb Include lang files in project so they'll actually end up in the final build 2013-07-31 18:31:39 +02:00
Shannon 9bc3fdd555 Makes UmbracoContext disposable and fixes the module's DisposeHttpContextItems to actual perform the disposal of each item. 2013-07-31 17:34:42 +10:00
Shannon cbda86fe92 Fixes build error, streamlines all calls to validate a user for base controllers. 2013-07-31 17:24:36 +10:00
Shannon b48f0f52e0 updates uri extensions + tests
Conflicts:
	src/Umbraco.Core/UriExtensions.cs
2013-07-31 17:08:10 +10:00
Shannon e2eeafcbfc Fixes: U4-2232 UmbracoAuthorizeAttribute breaks Relfection methods - ensures that no singleton instances are passed into attributes since they only ever get created once, meaning we're left with a stale version in the attribute. 2013-07-31 16:45:11 +10:00
Shannon ad697db42b Fixes an issue with WebSecurity logout 2013-07-31 11:10:33 +10:00
Shannon 9bb31e9456 Merge branch '6.1.4-cmsContentXml_Optimizations' into 6.1.4 2013-07-29 17:45:48 +10:00
Shannon a195d33332 Added another benchmark for removing/re-inserting records for cmsContentXml table using one transaction which again improves performance. Now have changed the rebuild xml method in the content service to : Lookup all data that it needs to insert first, then we begin a transaction and inside of the one transaction we clear the data and re-insert it so if anything fails in this process it should be rolled back. 2013-07-29 17:45:05 +10:00
Shannon 82a87cbd92 Doh, missed file 2013-07-29 16:46:30 +10:00
Shannon 5b26436862 Removes all references to the legacy Document.RepublishAll and replaces it's logic with the correct logic. 2013-07-29 16:45:54 +10:00
Shannon eed61f9053 Adds unit test for U4-2556 to ensure that it is solved. 2013-07-29 16:42:53 +10:00
Shannon 55c68485e9 Changed the logic of the GetByPublishedVersion to only return from cache if the cache item is published. 2013-07-29 16:03:37 +10:00
Shannon b9ba350a2f Updated the RebuildXmlStructures method with performance improvements. Added cache checking to the GetByPublishedVersion method since published content should always be 'latest' this will speed things up tremendously if items are found there. Added 2 more performance tests which show very large perf improvements, namely the Get_All_Published_Content_Of_Type shows a 77% improvement. 2013-07-29 15:49:56 +10:00
Shannon 696306e7c9 Implements the bulk insert procedure for re-populating the cmsContentXml tables, removes the need to rebuild all xml structures when sorting if in LB environments 2013-07-29 13:25:02 +10:00
Sebastiaan Janssen 9bf86aff09 Merge branch '6.1.4' of github.com:umbraco/Umbraco-CMS into 6.1.4 2013-07-26 15:17:20 +02:00
Sebastiaan Janssen f50de5b049 U4-2550 Could not load file or assembly 'HtmlAgilityPack, Version=1.4.5.0 2013-07-26 15:16:55 +02:00
Sebastiaan Janssen d734ba6136 U4-2543 In the back office its possible to get Response Validation errors 2013-07-26 12:43:19 +02:00
Morten Christensen c49becea53 Cleanup of unused using statements in a few files 2013-07-26 12:35:40 +02:00
Shannon 614aea203d Merge remote-tracking branch 'origin/6.1.4' into 6.1.4-cmsContentXml_Optimizations 2013-07-26 18:14:13 +10:00
Shannon ed88bbf75f Fixed up BaseDatabaseFactoryTests so that it only loads in one db factory with the correct conn strings, now we can easily override to use a custom db. Added benchmark tests for bulk inserting records for the cmsContentXml table which shows how we can improve performance quite a bit especially for larger node sets. Added more unit tests for bulk inserting and fixed it up a bit more. 2013-07-26 18:13:56 +10:00
Sebastiaan Janssen e41d3c7e84 Increase version to 6.1.4 2013-07-25 11:59:37 +02:00
Sebastiaan Janssen b5494546c7 defaultDocumentTypeProperty is no longer case-sensitive. Added to the Release config as well so it makes it into the umbraco downloadable package. 2013-07-19 15:40:12 +02:00
Sebastiaan Janssen 7bac1ef1cd Merge branch 'wip-u4-1949' of https://github.com/AndyButland/Umbraco-CMS into AndyButland-wip-u4-1949 2013-07-19 15:22:05 +02:00
Sebastiaan Janssen da15d40b04 Merge pull request #51 from kipusoep/master
Updated the download link
2013-07-19 06:18:13 -07:00
Sebastiaan Janssen 67bd303173 Merge pull request #46 from michielvoo/u4-2417
U4-2417 Could the preview thumbnail link to the full image
2013-07-19 06:02:51 -07:00
Sebastiaan Janssen 20e6843bf0 Merge pull request #32 from AndyButland/wip-u4-1285
Fix for U4-1285: Apostrophes in member groups cause exceptions
2013-07-19 05:39:38 -07:00
Sebastiaan Janssen 85c80b07f9 Merge pull request #42 from michielvoo/u4-232
Enabled support for integrated security for SQL Server to the installer.
2013-07-19 04:26:50 -07:00
Sebastiaan Janssen 557dccd88b Merge pull request #41 from michielvoo/u4-667
U4-667
2013-07-19 04:18:29 -07:00
Sebastiaan Janssen 334f0bfd2b Merge pull request #40 from michielvoo/u4-663
U4-663
2013-07-19 03:53:15 -07:00
AndyButland 986d37afd6 Removed debugging console.log reference 2013-07-18 21:23:05 +02:00
Stefan Kip 63ea79a4d6 Updated the download link 2013-07-11 10:03:25 +02:00
Michiel van Oosterhout e4df176a37 U4-2417: show media picker image as link to the original image.
Order of the views in the markup did not match the order of the Style enum.
ImageViewer control now selects the view by matching the ViewerStyle enum to a View ID. This way the order of the views in the markup is no longer important.

Also:
Removed user control from Umbraco.Web project, moved designer code and added code behind class for user control to Umbraco.Web.UI
Refactored code to use Umbraco.Core.IO
Removed some code that was commented out
2013-07-03 17:36:28 +02:00
Michiel van Oosterhout d926180e3a Added special overload for creating a connection string with integrated security.
Actually disable checkbox is the selected database type is not Microsoft SQL Server.
Refactored saveDBConfig for readability.
2013-06-28 16:40:23 +02:00
Michiel van Oosterhout 72bb1b3583 U4-667
Added a script to make the checkbox "Render content in editor" dependent on the "Use in editor" checkbox.
Also refactored the create.aspx code-behind so it's easier to see what control is loaded in the dialog when debugging.
2013-06-28 10:44:24 +02:00
Michiel van Oosterhout 240e58e061 U4-663
Do not overwrite existing files when creating a new template.
2013-06-28 10:42:51 +02:00
Michiel van Oosterhout e980296d6d Enabled support for integrated security for SQL Server to the installer. 2013-06-28 10:39:48 +02:00
AndyButland d23482b7a6 Moved setting for DefaultDocumentTypeProperty from GlobalSettings to UmbracoSettings 2013-06-27 16:00:49 +02:00
AndyButland 212800f706 Added config setting for default document type property; used setting to set default new property type 2013-06-26 17:25:44 +02:00
AndyButland d47ff4005c Support for deleting member groups with apostrophes 2013-06-26 06:16:39 +02:00
AndyButland dfeb1c7a0b Support for displaying and editing member groups with apostrophes 2013-06-26 06:16:23 +02:00
Sebastiaan Janssen 9a3c2bbc5c Merge pull request #19 from michielvoo/master
Changed default email address in the installer
2013-06-20 07:47:50 -07:00
Michiel van Oosterhout 0b0fb92cf1 Changed default user email address to use the example domain, instead of domain.com 2013-06-20 16:01:03 +02:00
Sebastiaan Janssen 6f09da0927 Merge pull request #17 from kipusoep/patch-1
Removed space before UmbracoModule
2013-06-20 06:18:21 -07:00
Stefan Kip febe6ec241 Removed space before UmbracoModule
Removed space before UmbracoModule
2013-06-20 14:56:39 +02:00
Sebastiaan Janssen 6f85eefd85 updated ignore file with correct case sensitivity
Conflicts:
	.gitignore
2013-06-19 14:39:21 +02:00
172 changed files with 4821 additions and 1838 deletions
+5
View File
@@ -79,3 +79,8 @@ src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
build/_BuildOutput/
tools/NDepend/
src/*.vspx
src/*.psess
NDependOut/*
QueryResult.htm
*.ndproj
+1 -1
View File
@@ -1,5 +1,5 @@
@ECHO OFF
SET release=6.1.3
SET release=6.1.6
SET comment=
SET version=%release%
+12 -1
View File
@@ -228,7 +228,7 @@
</Target>
<!-- Copy the xml documentation to the bin folder -->
<Target Name="CopyXmlDocumentation" DependsOnTargets="CompileProjects">
<Target Name="CopyXmlDocumentation" DependsOnTargets="CleanupPresentation">
<ItemGroup>
<XmlDocumentationFiles Include="$(SolutionBinFolder)*.xml" />
</ItemGroup>
@@ -240,6 +240,17 @@
<Message Text="CopyXmlDocumentation" />
</Target>
<!-- Unlike 2010, the VS2012 build targets file doesn't clean up the umbraco.presentation dir, do it manually -->
<!-- Also, it places umbraco.XmlSerializers.dll in the root, even though it's also in the bin folder. Kill! -->
<Target Name="CleanupPresentation" DependsOnTargets="CompileProjects">
<ItemGroup>
<PresentationFolderToDelete Include="$(WebAppFolder)umbraco.presentation" />
<XmlSerializersDll Include="$(WebAppFolder)umbraco.XmlSerializers.dll" />
</ItemGroup>
<RemoveDir Directories="@(PresentationFolderToDelete)" />
<Delete Files="@(XmlSerializersDll)" />
</Target>
<Target Name="CompileProjects" DependsOnTargets="CompileExternalExamineProjects">
<Message Text="Compiling web project to build\$(BuildFolder)" Importance="high" />
+52 -52
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-16"?>
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>UmbracoCms.Core</id>
<version>6.1.2</version>
<version>6.2.0</version>
<title>Umbraco Cms Core Binaries</title>
<authors>Morten Christensen</authors>
<owners>Umbraco HQ</owners>
@@ -14,57 +14,57 @@
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependencies>
<dependency id="Microsoft.AspNet.Mvc" version="4.0" />
<dependency id="Microsoft.AspNet.WebApi" version="4.0" />
<dependency id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.0" />
<dependency id="MiniProfiler" version="2.1.0" />
<dependency id="HtmlAgilityPack" version="1.4.6" />
<dependency id="Lucene.Net" version="[2.9.4.1]" />
<dependency id="SharpZipLib" version="0.86.0" />
<dependency id="MySql.Data" version="[6.6.5]" />
<dependency id="xmlrpcnet" version="2.5.0" />
<dependency id="ClientDependency" version="[1.7.0,1.7.1)" />
<dependency id="ClientDependency-Mvc" version="[1.7.0,1.7.1)" />
<dependency id="Microsoft.AspNet.WebApi" version="4.0" />
<dependency id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.0" />
<dependency id="MiniProfiler" version="[2.1.0, 3.0.0)" />
<dependency id="HtmlAgilityPack" version="[1.4.6, 2.0.0)" />
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
<dependency id="MySql.Data" version="[6.6.5]" />
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
<dependency id="ClientDependency" version="[1.7.0, 2.0.0)" />
<dependency id="ClientDependency-Mvc" version="[1.7.0, 2.0.0)" />
</dependencies>
</metadata>
<files>
<file src="..\_BuildOutput\WebApp\bin\businesslogic.dll" target="lib\businesslogic.dll" />
<file src="..\_BuildOutput\WebApp\bin\businesslogic.xml" target="lib\businesslogic.xml" />
<file src="..\_BuildOutput\WebApp\bin\cms.dll" target="lib\cms.dll" />
<file src="..\_BuildOutput\WebApp\bin\cms.xml" target="lib\cms.xml" />
<file src="..\_BuildOutput\WebApp\bin\controls.dll" target="lib\controls.dll" />
<file src="..\_BuildOutput\WebApp\bin\controls.xml" target="lib\controls.xml" />
<file src="..\_BuildOutput\WebApp\bin\Examine.dll" target="lib\Examine.dll" />
<file src="..\_BuildOutput\WebApp\bin\interfaces.dll" target="lib\interfaces.dll" />
<file src="..\_BuildOutput\WebApp\bin\interfaces.xml" target="lib\interfaces.xml" />
<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\Our.Umbraco.uGoLive.47x.dll" target="lib\Our.Umbraco.uGoLive.47x.dll" />
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.Checks.dll" target="lib\Our.Umbraco.uGoLive.Checks.dll" />
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.dll" target="lib\Our.Umbraco.uGoLive.dll" />
<file src="..\_BuildOutput\WebApp\bin\SQLCE4Umbraco.dll" target="lib\SQLCE4Umbraco.dll" />
<file src="..\_BuildOutput\WebApp\bin\System.Data.SqlServerCe.dll" target="lib\System.Data.SqlServerCe.dll" />
<file src="..\_BuildOutput\WebApp\bin\System.Data.SqlServerCe.Entity.dll" target="lib\System.Data.SqlServerCe.Entity.dll" />
<file src="..\_BuildOutput\WebApp\bin\TidyNet.dll" target="lib\TidyNet.dll" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Core.dll" target="lib\Umbraco.Core.dll" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.DataLayer.dll" target="lib\umbraco.DataLayer.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.DataLayer.xml" target="lib\umbraco.DataLayer.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.dll" target="lib\umbraco.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.xml" target="lib\umbraco.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.editorControls.dll" target="lib\umbraco.editorControls.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.editorControls.xml" target="lib\umbraco.editorControls.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.MacroEngines.dll" target="lib\umbraco.MacroEngines.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.MacroEngines.xml" target="lib\umbraco.MacroEngines.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.macroRenderings.dll" target="lib\umbraco.macroRenderings.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.macroRenderings.xml" target="lib\umbraco.macroRenderings.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.providers.dll" target="lib\umbraco.providers.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.providers.xml" target="lib\umbraco.providers.xml" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Web.UI.dll" target="lib\Umbraco.Web.UI.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.XmlSerializers.dll" target="lib\umbraco.XmlSerializers.dll" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
<file src="..\_BuildOutput\WebApp\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
</files>
<files>
<file src="..\_BuildOutput\WebApp\bin\businesslogic.dll" target="lib\businesslogic.dll" />
<file src="..\_BuildOutput\WebApp\bin\businesslogic.xml" target="lib\businesslogic.xml" />
<file src="..\_BuildOutput\WebApp\bin\cms.dll" target="lib\cms.dll" />
<file src="..\_BuildOutput\WebApp\bin\cms.xml" target="lib\cms.xml" />
<file src="..\_BuildOutput\WebApp\bin\controls.dll" target="lib\controls.dll" />
<file src="..\_BuildOutput\WebApp\bin\controls.xml" target="lib\controls.xml" />
<file src="..\_BuildOutput\WebApp\bin\Examine.dll" target="lib\Examine.dll" />
<file src="..\_BuildOutput\WebApp\bin\interfaces.dll" target="lib\interfaces.dll" />
<file src="..\_BuildOutput\WebApp\bin\interfaces.xml" target="lib\interfaces.xml" />
<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\Our.Umbraco.uGoLive.47x.dll" target="lib\Our.Umbraco.uGoLive.47x.dll" />
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.Checks.dll" target="lib\Our.Umbraco.uGoLive.Checks.dll" />
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.dll" target="lib\Our.Umbraco.uGoLive.dll" />
<file src="..\_BuildOutput\WebApp\bin\SQLCE4Umbraco.dll" target="lib\SQLCE4Umbraco.dll" />
<file src="..\_BuildOutput\WebApp\bin\System.Data.SqlServerCe.dll" target="lib\System.Data.SqlServerCe.dll" />
<file src="..\_BuildOutput\WebApp\bin\System.Data.SqlServerCe.Entity.dll" target="lib\System.Data.SqlServerCe.Entity.dll" />
<file src="..\_BuildOutput\WebApp\bin\TidyNet.dll" target="lib\TidyNet.dll" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Core.dll" target="lib\Umbraco.Core.dll" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.DataLayer.dll" target="lib\umbraco.DataLayer.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.DataLayer.xml" target="lib\umbraco.DataLayer.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.dll" target="lib\umbraco.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.xml" target="lib\umbraco.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.editorControls.dll" target="lib\umbraco.editorControls.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.editorControls.xml" target="lib\umbraco.editorControls.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.MacroEngines.dll" target="lib\umbraco.MacroEngines.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.MacroEngines.xml" target="lib\umbraco.MacroEngines.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.macroRenderings.dll" target="lib\umbraco.macroRenderings.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.macroRenderings.xml" target="lib\umbraco.macroRenderings.xml" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.providers.dll" target="lib\umbraco.providers.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.providers.xml" target="lib\umbraco.providers.xml" />
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Web.UI.dll" target="lib\Umbraco.Web.UI.dll" />
<file src="..\_BuildOutput\WebApp\bin\umbraco.XmlSerializers.dll" target="lib\umbraco.XmlSerializers.dll" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
<file src="..\_BuildOutput\WebApp\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
</files>
</package>
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-16"?>
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>UmbracoCms</id>
+5 -4
View File
@@ -7,10 +7,11 @@ The config files found in the config folder will usually not be changed for patc
but the web.config will have to have its previous "umbracoConfigurationStatus"-appsetting and "umbracoDbDSN" connection string
copied over (as a minimum).
It's not possible to create a deploy package from Visual Studio, which contains everything out of the box. This is
due to a number of files and folders that are not added to the Visual Studio project. These folders include:
install, umbraco and umbraco_client.
A custom deploy script will be added in a later release.
This nuget package includes build targets that extends the creation of a deploy package, which is generated by
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
Publish this won't affect you.
These folders will now be automatically included when creating a deploy package or publishing to the file system:
umbraco and umbraco_client.
Please read the release notes on our.umbraco.org:
http://our.umbraco.org/contribute/releases
@@ -5,6 +5,7 @@ using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Caching;
using System.Web.Security;
using System.Xml;
using System.Configuration;
@@ -299,6 +300,32 @@ namespace Umbraco.Core.Configuration
}
}
internal static string AuthCookieName
{
get
{
var value = GetKey("/settings/security/authCookieName");
if (string.IsNullOrEmpty(value) == false)
{
return value;
}
return "UMB_UCONTEXT";
}
}
internal static string AuthCookieDomain
{
get
{
var value = GetKey("/settings/security/authCookieDomain");
if (string.IsNullOrEmpty(value) == false)
{
return value;
}
return FormsAuthentication.CookieDomain;
}
}
/// <summary>
/// Enables the experimental canvas (live) editing on the frontend of the website
/// </summary>
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("6.1.3");
private static readonly Version Version = new Version("6.1.6");
/// <summary>
/// Gets the current version of Umbraco.
+58 -6
View File
@@ -112,7 +112,7 @@ namespace Umbraco.Core
public void ConfigureEmbeddedDatabaseConnection()
{
const string providerName = "System.Data.SqlServerCe.4.0";
const string connectionString = @"Data Source=|DataDirectory|\Umbraco.sdf";
const string connectionString = @"Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1;";
SaveConnectionString(connectionString, providerName);
@@ -296,16 +296,15 @@ namespace Umbraco.Core
if (databaseSettings != null && string.IsNullOrWhiteSpace(databaseSettings.ConnectionString) == false && string.IsNullOrWhiteSpace(databaseSettings.ProviderName) == false)
{
var providerName = "System.Data.SqlClient";
string connString = null;
if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName))
{
providerName = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName;
_connectionString =
ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ConnectionString;
connString = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ConnectionString;
}
Initialize(providerName, connString);
Initialize(providerName);
DetermineSqlServerVersion();
}
else if (ConfigurationManager.AppSettings.ContainsKey(GlobalSettings.UmbracoConnectionName) && string.IsNullOrEmpty(ConfigurationManager.AppSettings[GlobalSettings.UmbracoConnectionName]) == false)
{
@@ -342,6 +341,8 @@ namespace Umbraco.Core
//Remove the legacy connection string, so we don't end up in a loop if something goes wrong.
GlobalSettings.RemoveSetting(GlobalSettings.UmbracoConnectionName);
DetermineSqlServerVersion();
}
else
{
@@ -369,6 +370,55 @@ namespace Umbraco.Core
}
}
internal void Initialize(string providerName, string connectionString)
{
_connectionString = connectionString;
Initialize(providerName);
}
/// <summary>
/// Set the lazy resolution of determining the SQL server version if that is the db type we're using
/// </summary>
private void DetermineSqlServerVersion()
{
var sqlServerSyntax = SqlSyntaxContext.SqlSyntaxProvider as SqlServerSyntaxProvider;
if (sqlServerSyntax != null)
{
//this will not execute now, it is lazy so will only execute when we need to actually know
// the sql server version.
sqlServerSyntax.VersionName = new Lazy<SqlServerVersionName>(() =>
{
try
{
var database = this._factory.CreateDatabase();
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
var firstPart = version.Split('.')[0];
switch (firstPart)
{
case "11":
return SqlServerVersionName.V2012;
case "10":
return SqlServerVersionName.V2008;
case "9":
return SqlServerVersionName.V2005;
case "8":
return SqlServerVersionName.V2000;
case "7":
return SqlServerVersionName.V7;
default:
return SqlServerVersionName.Other;
}
}
catch (Exception)
{
return SqlServerVersionName.Invalid;
}
});
}
}
internal DatabaseSchemaResult ValidateDatabaseSchema()
{
if (_configured == false || (string.IsNullOrEmpty(_connectionString) || string.IsNullOrEmpty(ProviderName)))
@@ -460,6 +510,8 @@ namespace Umbraco.Core
message = message + "<p>Upgrade completed!</p>";
}
//now that everything is done, we need to determine the version of SQL server that is executing
LogHelper.Info<DatabaseContext>("Database configuration status: " + message);
return new Result { Message = message, Success = true, Percentage = "100" };
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Events
{
public class RecycleBinEventArgs : CancellableEventArgs
{
public RecycleBinEventArgs(Guid nodeObjectType, IEnumerable<int> ids, List<string> files, bool emptiedSuccessfully)
: base(false)
{
NodeObjectType = nodeObjectType;
Ids = ids;
Files = files;
RecycleBinEmptiedSuccessfully = emptiedSuccessfully;
}
public RecycleBinEventArgs(Guid nodeObjectType, IEnumerable<int> ids, List<string> files)
: base(true)
{
NodeObjectType = nodeObjectType;
Ids = ids;
Files = files;
}
/// <summary>
/// Gets the Id of the node object type of the items
/// being deleted from the Recycle Bin.
/// </summary>
public Guid NodeObjectType { get; private set; }
/// <summary>
/// Gets the list of Ids for each of the items being deleted from the Recycle Bin.
/// </summary>
public IEnumerable<int> Ids { get; private set; }
/// <summary>
/// Gets the list of Files that should be deleted as part
/// of emptying the Recycle Bin.
/// </summary>
public List<string> Files { get; private set; }
/// <summary>
/// Boolean indicating whether the Recycle Bin was emptied successfully
/// </summary>
public bool RecycleBinEmptiedSuccessfully { get; private set; }
/// <summary>
/// Boolean indicating whether this event was fired for the Content's Recycle Bin.
/// </summary>
public bool IsContentRecycleBin
{
get { return NodeObjectType == new Guid(Constants.ObjectTypes.Document); }
}
/// <summary>
/// Boolean indicating whether this event was fired for the Media's Recycle Bin.
/// </summary>
public bool IsMediaRecycleBin
{
get { return NodeObjectType == new Guid(Constants.ObjectTypes.Media); }
}
}
}
+14
View File
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Umbraco.Core
{
/// <summary>
/// Any class implementing this interface that is added to the httpcontext.items keys or values will be disposed of at the end of the request.
/// </summary>
public interface IDisposeOnRequestEnd : IDisposable
{
}
}
+21 -4
View File
@@ -139,7 +139,10 @@ namespace Umbraco.Core.Models
/// <summary>
/// Boolean indicating whether this Content is Published or not
/// </summary>
/// <remarks>Setting Published to true/false should be private or internal</remarks>
/// <remarks>
/// Setting Published to true/false should be private or internal and should ONLY be used for wiring up the value
/// from the db or modifying it based on changing the published state.
/// </remarks>
[DataMember]
public bool Published
{
@@ -372,11 +375,25 @@ namespace Umbraco.Core.Models
/// <returns>True if entity is dirty, otherwise False</returns>
public override bool IsDirty()
{
bool dirtyEntity = base.IsDirty();
return IsEntityDirty() || IsAnyUserPropertyDirty();
}
bool dirtyProperties = Properties.Any(x => x.IsDirty());
/// <summary>
/// Returns true if only the entity properties are direty
/// </summary>
/// <returns></returns>
internal bool IsEntityDirty()
{
return base.IsDirty();
}
return dirtyEntity || dirtyProperties;
/// <summary>
/// Returns true if any of the properties are dirty
/// </summary>
/// <returns></returns>
internal bool IsAnyUserPropertyDirty()
{
return Properties.Any(x => x.IsDirty());
}
/// <summary>
+19 -1
View File
@@ -293,7 +293,10 @@ namespace Umbraco.Core.Models
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
public virtual TPassType GetValue<TPassType>(string propertyTypeAlias)
{
return (TPassType)Properties[propertyTypeAlias].Value;
if (Properties[propertyTypeAlias].Value is TPassType)
return (TPassType)Properties[propertyTypeAlias].Value;
return (TPassType)Convert.ChangeType(Properties[propertyTypeAlias].Value, typeof(TPassType));
}
/// <summary>
@@ -436,5 +439,20 @@ namespace Umbraco.Core.Models
}
public abstract void ChangeTrashedState(bool isTrashed, int parentId = -20);
/// <summary>
/// We will override this method to ensure that when we reset the dirty properties that we
/// also reset the dirty changes made to the content's Properties (user defined)
/// </summary>
/// <param name="rememberPreviouslyChangedProperties"></param>
internal override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
{
base.ResetDirtyProperties(rememberPreviouslyChangedProperties);
foreach (var prop in Properties)
{
prop.ResetDirtyProperties(rememberPreviouslyChangedProperties);
}
}
}
}
@@ -12,6 +12,7 @@ using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Media;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Strings;
using Umbraco.Core.Persistence;
@@ -23,6 +24,107 @@ namespace Umbraco.Core.Models
public static class ContentExtensions
{
#region IContent
/// <summary>
/// Determines if a new version should be created
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
/// <remarks>
/// A new version needs to be created when:
/// * The publish status is changed
/// * The language is changed
/// * The item is already published and is being published again and any property value is changed (to enable a rollback)
/// </remarks>
internal static bool ShouldCreateNewVersion(this IContent entity)
{
var publishedState = ((Content)entity).PublishedState;
return ShouldCreateNewVersion(entity, publishedState);
}
/// <summary>
/// Determines if a new version should be created
/// </summary>
/// <param name="entity"></param>
/// <param name="publishedState"></param>
/// <returns></returns>
/// <remarks>
/// A new version needs to be created when:
/// * The publish status is changed
/// * The language is changed
/// * The item is already published and is being published again and any property value is changed (to enable a rollback)
/// </remarks>
internal static bool ShouldCreateNewVersion(this IContent entity, PublishedState publishedState)
{
var dirtyEntity = (ICanBeDirty)entity;
//check if the published state has changed or the language
var contentChanged =
(dirtyEntity.IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished)
|| dirtyEntity.IsPropertyDirty("Language");
//return true if published or language has changed
if (contentChanged)
{
return true;
}
//check if any user prop has changed
var propertyValueChanged = ((Content) entity).IsAnyUserPropertyDirty();
//check if any content prop has changed
var contentDataChanged = ((Content) entity).IsEntityDirty();
//return true if the item is published and a property has changed or if any content property has changed
return (propertyValueChanged && publishedState == PublishedState.Published) || contentDataChanged;
}
/// <summary>
/// Determines if the published db flag should be set to true for the current entity version and all other db
/// versions should have their flag set to false.
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
/// <remarks>
/// This is determined by:
/// * If a new version is being created and the entity is published
/// * If the published state has changed and the entity is published OR the entity has been un-published.
/// </remarks>
internal static bool ShouldClearPublishedFlagForPreviousVersions(this IContent entity)
{
var publishedState = ((Content)entity).PublishedState;
return entity.ShouldClearPublishedFlagForPreviousVersions(publishedState, entity.ShouldCreateNewVersion(publishedState));
}
/// <summary>
/// Determines if the published db flag should be set to true for the current entity version and all other db
/// versions should have their flag set to false.
/// </summary>
/// <param name="entity"></param>
/// <param name="publishedState"></param>
/// <param name="isCreatingNewVersion"></param>
/// <returns></returns>
/// <remarks>
/// This is determined by:
/// * If a new version is being created and the entity is published
/// * If the published state has changed and the entity is published OR the entity has been un-published.
/// </remarks>
internal static bool ShouldClearPublishedFlagForPreviousVersions(this IContent entity, PublishedState publishedState, bool isCreatingNewVersion)
{
if (isCreatingNewVersion && entity.Published)
{
return true;
}
//If Published state has changed then previous versions should have their publish state reset.
//If state has been changed to unpublished the previous versions publish state should also be reset.
if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
{
return true;
}
return false;
}
/// <summary>
/// Returns a list of the current contents ancestors, not including the content itself.
/// </summary>
+32
View File
@@ -181,6 +181,38 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Creates a clone of the current entity
/// </summary>
/// <returns></returns>
public IContentType Clone(string alias)
{
var clone = (ContentType)this.MemberwiseClone();
clone.Alias = alias;
clone.Key = Guid.Empty;
var propertyGroups = this.PropertyGroups.Select(x => x.Clone()).ToList();
clone.PropertyGroups = new PropertyGroupCollection(propertyGroups);
clone.PropertyTypes = this.PropertyTypeCollection.Select(x => x.Clone()).ToList();
clone.ResetIdentity();
clone.ResetDirtyProperties(false);
foreach (var propertyGroup in clone.PropertyGroups)
{
propertyGroup.ResetIdentity();
foreach (var propertyType in propertyGroup.PropertyTypes)
{
propertyType.ResetIdentity();
}
}
foreach (var propertyType in clone.PropertyTypes.Where(x => x.HasIdentity))
{
propertyType.ResetIdentity();
}
return clone;
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
@@ -494,5 +494,14 @@ namespace Umbraco.Core.Models
{
_parentId = id;
}
/// <summary>
/// PropertyTypes that are not part of a PropertyGroup
/// </summary>
[IgnoreDataMember]
internal PropertyTypeCollection PropertyTypeCollection
{
get { return _propertyTypes; }
}
}
}
+17 -4
View File
@@ -22,10 +22,15 @@ namespace Umbraco.Core.Models
/// <returns>Xml of the property and its value</returns>
public static XElement ToXml(this Property property)
{
string nodeName = UmbracoSettings.UseLegacyXmlSchema ? "data" : property.Alias.ToSafeAlias();
return property.ToXml(ApplicationContext.Current.Services.DataTypeService);
}
internal static XElement ToXml(this Property property, IDataTypeService dataTypeService)
{
var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "data" : property.Alias.ToSafeAlias();
var xd = new XmlDocument();
XmlNode xmlNode = xd.CreateNode(XmlNodeType.Element, nodeName, "");
var xmlNode = xd.CreateNode(XmlNodeType.Element, nodeName, "");
//Add the property alias to the legacy schema
if (UmbracoSettings.UseLegacyXmlSchema)
@@ -37,9 +42,17 @@ namespace Umbraco.Core.Models
//This seems to fail during testing
//SD: With the new null checks below, this shouldn't fail anymore.
var dt = property.PropertyType.DataType(property.Id);
var dt = property.PropertyType.DataType(property.Id, dataTypeService);
if (dt != null && dt.Data != null)
{
{
//We've already got the value for the property so we're going to give it to the
// data type's data property so it doesn't go re-look up the value from the db again.
var defaultData = dt.Data as IDataValueSetter;
if (defaultData != null)
{
defaultData.SetValue(property.Value, property.PropertyType.DataTypeDatabaseType.ToString());
}
xmlNode.AppendChild(dt.Data.ToXMl(xd));
}
+17
View File
@@ -108,6 +108,23 @@ namespace Umbraco.Core.Models
}
}
internal PropertyGroup Clone()
{
var clone = (PropertyGroup) this.MemberwiseClone();
var collection = new PropertyTypeCollection();
foreach (var propertyType in this.PropertyTypes)
{
var property = propertyType.Clone();
property.ResetIdentity();
property.ResetDirtyProperties(false);
collection.Add(property);
}
clone.PropertyTypes = collection;
clone.ResetIdentity();
clone.ResetDirtyProperties(false);
return clone;
}
/// <summary>
/// Sets the ParentId from the lazy integer id
/// </summary>
+8
View File
@@ -378,6 +378,14 @@ namespace Umbraco.Core.Models
return true;
}
internal PropertyType Clone()
{
var clone = (PropertyType) this.MemberwiseClone();
clone.ResetIdentity();
clone.ResetDirtyProperties(false);
return clone;
}
public bool Equals(PropertyType other)
{
//Check whether the compared object is null.
@@ -1,4 +1,5 @@
using umbraco.interfaces;
using Umbraco.Core.Services;
using umbraco.interfaces;
namespace Umbraco.Core.Models
{
@@ -9,6 +10,7 @@ namespace Umbraco.Core.Models
/// </summary>
/// <param name="propertyType">PropertyType that references a DataType</param>
/// <param name="propertyId">Id of the Property which references this DataType through its PropertyType</param>
/// <param name="dataTypeService"></param>
/// <returns><see cref="IDataType"/></returns>
/// <remarks>
/// This extension method is left internal because we don't want to take
@@ -16,10 +18,10 @@ namespace Umbraco.Core.Models
/// be replaced by PropertyEditors. It is however needed to generate xml
/// for a property/propertytype when publishing.
/// </remarks>
internal static IDataType DataType(this PropertyType propertyType, int propertyId)
internal static IDataType DataType(this PropertyType propertyType, int propertyId, IDataTypeService dataTypeService)
{
Mandate.ParameterNotNull(propertyType, "propertyType");
var dataType = ApplicationContext.Current.Services.DataTypeService.GetDataTypeById(propertyType.DataTypeId);
var dataType = dataTypeService.GetDataTypeById(propertyType.DataTypeId);
if (dataType == null)
{
return null;
@@ -65,12 +65,12 @@ namespace Umbraco.Core.Models.Rdbms
return Date.Value;
}
if(!string.IsNullOrEmpty(VarChar))
if(string.IsNullOrEmpty(VarChar) == false)
{
return VarChar;
}
if(!string.IsNullOrEmpty(Text))
if(string.IsNullOrEmpty(Text) == false)
{
return Text;
}
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Umbraco.Core.CodeAnnotations;
@@ -9,7 +10,8 @@ namespace Umbraco.Core.Models
/// </summary>
public static class UmbracoObjectTypesExtensions
{
private static readonly Dictionary<UmbracoObjectTypes, Guid> UmbracoObjectTypeCache = new Dictionary<UmbracoObjectTypes,Guid>();
//MUST be concurrent to avoid thread collisions!
private static readonly ConcurrentDictionary<UmbracoObjectTypes, Guid> UmbracoObjectTypeCache = new ConcurrentDictionary<UmbracoObjectTypes, Guid>();
/// <summary>
/// Get an UmbracoObjectTypes value from it's name
@@ -48,24 +50,22 @@ namespace Umbraco.Core.Models
/// <returns>a GUID value of the UmbracoObjectTypes</returns>
public static Guid GetGuid(this UmbracoObjectTypes umbracoObjectType)
{
if (UmbracoObjectTypeCache.ContainsKey(umbracoObjectType))
return UmbracoObjectTypeCache[umbracoObjectType];
return UmbracoObjectTypeCache.GetOrAdd(umbracoObjectType, types =>
{
var type = typeof(UmbracoObjectTypes);
var memInfo = type.GetMember(umbracoObjectType.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(UmbracoObjectTypeAttribute),
false);
var type = typeof(UmbracoObjectTypes);
var memInfo = type.GetMember(umbracoObjectType.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(UmbracoObjectTypeAttribute),
false);
if (attributes.Length == 0)
return Guid.Empty;
if (attributes.Length == 0)
return Guid.Empty;
var attribute = ((UmbracoObjectTypeAttribute)attributes[0]);
if (attribute == null)
return Guid.Empty;
var attribute = ((UmbracoObjectTypeAttribute)attributes[0]);
if (attribute == null)
return Guid.Empty;
UmbracoObjectTypeCache.Add(umbracoObjectType, attribute.ObjectId);
return attribute.ObjectId;
return attribute.ObjectId;
});
}
/// <summary>
+50
View File
@@ -0,0 +1,50 @@
using System;
namespace Umbraco.Core
{
/// <summary>
/// Currently just used to get the machine name in med trust and to format a machine name for use with file names
/// </summary>
internal class NetworkHelper
{
/// <summary>
/// Returns the machine name that is safe to use in file paths.
/// </summary>
/// <remarks>
/// see: https://github.com/Shandem/ClientDependency/issues/4
/// </remarks>
public static string FileSafeMachineName
{
get { return MachineName.ReplaceNonAlphanumericChars('-'); }
}
/// <summary>
/// Returns the current machine name
/// </summary>
/// <remarks>
/// Tries to resolve the machine name, if it cannot it uses the config section.
/// </remarks>
public static string MachineName
{
get
{
try
{
return Environment.MachineName;
}
catch
{
try
{
return System.Net.Dns.GetHostName();
}
catch
{
//if we get here it means we cannot access the machine name
throw new ApplicationException("Cannot resolve the current machine name eithe by Environment.MachineName or by Dns.GetHostname()");
}
}
}
}
}
}
@@ -3,6 +3,7 @@ using System.Data;
using System.Linq;
using System.Reflection;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
{
@@ -107,6 +108,12 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
var constraintAttribute = propertyInfo.FirstAttribute<ConstraintAttribute>();
if (constraintAttribute != null)
{
//Special case for MySQL as it can't have multiple default DateTime values, which
//is what the umbracoServer table definition is trying to create
if (SqlSyntaxContext.SqlSyntaxProvider is MySqlSyntaxProvider && definition.TableName == "umbracoServer" &&
definition.TableName.ToLowerInvariant() == "lastNotifiedDate".ToLowerInvariant())
return definition;
definition.ConstraintName = constraintAttribute.Name ?? string.Empty;
definition.DefaultValue = constraintAttribute.Default ?? string.Empty;
}
@@ -14,9 +14,9 @@ namespace Umbraco.Core.Persistence
/// </remarks>
internal class DefaultDatabaseFactory : DisposableObject, IDatabaseFactory
{
private readonly string _connectionStringName;
private readonly string _connectionString;
private readonly string _providerName;
private readonly string _connectionStringName;
public string ConnectionString { get; private set; }
public string ProviderName { get; private set; }
//very important to have ThreadStatic:
// see: http://issues.umbraco.org/issue/U4-2172
@@ -52,8 +52,8 @@ namespace Umbraco.Core.Persistence
{
Mandate.ParameterNotNullOrEmpty(connectionString, "connectionString");
Mandate.ParameterNotNullOrEmpty(providerName, "providerName");
_connectionString = connectionString;
_providerName = providerName;
ConnectionString = connectionString;
ProviderName = providerName;
}
public UmbracoDatabase CreateDatabase()
@@ -68,8 +68,8 @@ namespace Umbraco.Core.Persistence
//double check
if (_nonHttpInstance == null)
{
_nonHttpInstance = string.IsNullOrEmpty(_connectionString) == false && string.IsNullOrEmpty(_providerName) == false
? new UmbracoDatabase(_connectionString, _providerName)
_nonHttpInstance = string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false
? new UmbracoDatabase(ConnectionString, ProviderName)
: new UmbracoDatabase(_connectionStringName);
}
}
@@ -81,8 +81,8 @@ namespace Umbraco.Core.Persistence
if (HttpContext.Current.Items.Contains(typeof(DefaultDatabaseFactory)) == false)
{
HttpContext.Current.Items.Add(typeof (DefaultDatabaseFactory),
string.IsNullOrEmpty(_connectionString) == false && string.IsNullOrEmpty(_providerName) == false
? new UmbracoDatabase(_connectionString, _providerName)
string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false
? new UmbracoDatabase(ConnectionString, ProviderName)
: new UmbracoDatabase(_connectionStringName));
}
return (UmbracoDatabase)HttpContext.Current.Items[typeof(DefaultDatabaseFactory)];
@@ -223,8 +223,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 4, DataTypeId = -88, ControlId = new Guid(Constants.PropertyEditors.Textbox), DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 5, DataTypeId = -89, ControlId = new Guid(Constants.PropertyEditors.TextboxMultiple), DbType = "Ntext" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 6, DataTypeId = -90, ControlId = new Guid(Constants.PropertyEditors.UploadField), DbType = "Nvarchar" });
//Dropdown list
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -91, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 7, DataTypeId = -92, ControlId = new Guid(Constants.PropertyEditors.NoEdit), DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 8, DataTypeId = -36, ControlId = new Guid(Constants.PropertyEditors.DateTime), DbType = "Date" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, ControlId = new Guid(Constants.PropertyEditors.ColorPicker), DbType = "Nvarchar" });
@@ -234,24 +232,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, ControlId = new Guid(Constants.PropertyEditors.Date), DbType = "Date" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, ControlId = new Guid(Constants.PropertyEditors.DropDownList), DbType = "Integer" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, ControlId = new Guid(Constants.PropertyEditors.CheckBoxList), DbType = "Nvarchar" });
// Fix for rich text editor backwards compatibility -> 83722133-f80c-4273-bdb6-1befaa04a612 TinyMCE DataType
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = -44, ControlId = new Guid("a3776494-0574-4d93-b7de-efdfdec6f2d1"), DbType = "Ntext" });
//Radiobutton list
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 23, DataTypeId = -128, ControlId = new Guid("a52c7c1c-c330-476e-8605-d63d3b84b6a6"), DbType = "Nvarchar" });
//Dropdown list multiple
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = -129, ControlId = new Guid("928639ed-9c73-4028-920c-1e55dbb68783"), DbType = "Nvarchar" });
//Dropdown list
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 25, DataTypeId = -130, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
//Dropdown list
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = -131, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
//Dropdown list
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = -132, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
//No edit
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = -133, ControlId = new Guid("6c738306-4c17-4d88-b9bd-6546f3771597"), DbType = "Ntext" });
//Dropdown list multiple
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = -134, ControlId = new Guid("928639ed-9c73-4028-920c-1e55dbb68783"), DbType = "Nvarchar" });
//Not found - maybe a legacy thing?
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = -50, ControlId = new Guid("aaf99bb2-dbbe-444d-a296-185076bf0484"), DbType = "Date" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 16, DataTypeId = 1034, ControlId = new Guid(Constants.PropertyEditors.ContentPicker), DbType = "Integer" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 17, DataTypeId = 1035, ControlId = new Guid(Constants.PropertyEditors.MediaPicker), DbType = "Integer" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 18, DataTypeId = 1036, ControlId = new Guid(Constants.PropertyEditors.MemberPicker), DbType = "Integer" });
@@ -6,6 +6,7 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Migrations.Initial;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence
@@ -32,76 +33,145 @@ namespace Umbraco.Core.Persistence
public static void BulkInsertRecords<T>(this Database db, IEnumerable<T> collection)
{
//don't do anything if there are no records.
if (collection.Any() == false)
return;
using (var tr = db.GetTransaction())
{
try
{
if (SqlSyntaxContext.SqlSyntaxProvider is SqlCeSyntaxProvider)
{
//SqlCe doesn't support bulk insert statements!
foreach (var poco in collection)
{
db.Insert(poco);
}
}
else
{
string sql;
using (var cmd = db.GenerateBulkInsertCommand(collection, db.Connection, out sql))
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
}
tr.Complete();
}
catch
{
tr.Dispose();
throw;
}
db.BulkInsertRecords(collection, tr);
}
}
internal static IDbCommand GenerateBulkInsertCommand<T>(this Database db, IEnumerable<T> collection, IDbConnection connection, out string sql)
public static void BulkInsertRecords<T>(this Database db, IEnumerable<T> collection, Transaction tr)
{
//don't do anything if there are no records.
if (collection.Any() == false)
return;
try
{
//if it is sql ce or it is a sql server version less than 2008, we need to do individual inserts.
var sqlServerSyntax = SqlSyntaxContext.SqlSyntaxProvider as SqlServerSyntaxProvider;
if ((sqlServerSyntax != null && (int)sqlServerSyntax.VersionName.Value < (int)SqlServerVersionName.V2008)
|| SqlSyntaxContext.SqlSyntaxProvider is SqlCeSyntaxProvider)
{
//SqlCe doesn't support bulk insert statements!
foreach (var poco in collection)
{
db.Insert(poco);
}
}
else
{
string[] sqlStatements;
var cmds = db.GenerateBulkInsertCommand(collection, db.Connection, out sqlStatements);
for (var i = 0; i < sqlStatements.Length; i++)
{
using (var cmd = cmds[i])
{
cmd.CommandText = sqlStatements[i];
cmd.ExecuteNonQuery();
}
}
}
tr.Complete();
}
catch
{
tr.Dispose();
throw;
}
}
/// <summary>
/// Creates a bulk insert command
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="db"></param>
/// <param name="collection"></param>
/// <param name="connection"></param>
/// <param name="sql"></param>
/// <returns>Sql commands with populated command parameters required to execute the sql statement</returns>
/// <remarks>
/// The limits for number of parameters are 2100 (in sql server, I think there's many more allowed in mysql). So
/// we need to detect that many params and split somehow.
/// For some reason the 2100 limit is not actually allowed even though the exception from sql server mentions 2100 as a max, perhaps it is 2099
/// that is max. I've reduced it to 2000 anyways.
/// </remarks>
internal static IDbCommand[] GenerateBulkInsertCommand<T>(
this Database db,
IEnumerable<T> collection,
IDbConnection connection,
out string[] sql)
{
//A filter used below a few times to get all columns except result cols and not the primary key if it is auto-incremental
Func<Database.PocoData, KeyValuePair<string, Database.PocoColumn>, bool> includeColumn = (data, column) =>
{
if (column.Value.ResultColumn) return false;
if (data.TableInfo.AutoIncrement && column.Key == data.TableInfo.PrimaryKey) return false;
return true;
};
var pd = Database.PocoData.ForType(typeof(T));
var tableName = db.EscapeTableName(pd.TableInfo.TableName);
//get all columns but not the primary key if it is auto-incremental
var cols = string.Join(", ", (
from c in pd.Columns
where
//don't return ResultColumns
!c.Value.ResultColumn
//if the table is auto-incremental, don't return the primary key
&& (pd.TableInfo.AutoIncrement && c.Key != pd.TableInfo.PrimaryKey)
select tableName + "." + db.EscapeSqlIdentifier(c.Key))
.ToArray());
//get all columns to include and format for sql
var cols = string.Join(", ",
pd.Columns
.Where(c => includeColumn(pd, c))
.Select(c => tableName + "." + db.EscapeSqlIdentifier(c.Key)).ToArray());
var cmd = db.CreateCommand(connection, "");
var itemArray = collection.ToArray();
var pocoValues = new List<string>();
var index = 0;
foreach (var poco in collection)
//calculate number of parameters per item
var paramsPerItem = pd.Columns.Count(i => includeColumn(pd, i));
//Example calc:
// Given: we have 4168 items in the itemArray, each item contains 8 command parameters (values to be inserterted)
// 2100 / 8 = 262.5
// Math.Floor(2100 / 8) = 262 items per trans
// 4168 / 262 = 15.908... = there will be 16 trans in total
//all items will be included if we have disabled db parameters
var itemsPerTrans = Math.Floor(2000.00 / paramsPerItem);
//there will only be one transaction if we have disabled db parameters
var numTrans = Math.Ceiling(itemArray.Length / itemsPerTrans);
var sqlQueries = new List<string>();
var commands = new List<IDbCommand>();
for (var tIndex = 0; tIndex < numTrans; tIndex++)
{
var values = new List<string>();
foreach (var i in pd.Columns)
var itemsForTrans = itemArray
.Skip(tIndex * (int)itemsPerTrans)
.Take((int)itemsPerTrans);
var cmd = db.CreateCommand(connection, "");
var pocoValues = new List<string>();
var index = 0;
foreach (var poco in itemsForTrans)
{
if (pd.TableInfo.AutoIncrement && i.Key == pd.TableInfo.PrimaryKey)
var values = new List<string>();
//get all columns except result cols and not the primary key if it is auto-incremental
foreach (var i in pd.Columns.Where(x => includeColumn(pd, x)))
{
continue;
db.AddParam(cmd, i.Value.GetValue(poco), "@");
values.Add(string.Format("{0}{1}", "@", index++));
}
values.Add(string.Format("{0}{1}", "@", index++));
db.AddParam(cmd, i.Value.GetValue(poco), "@");
pocoValues.Add("(" + string.Join(",", values.ToArray()) + ")");
}
pocoValues.Add("(" + string.Join(",", values.ToArray()) + ")");
var sqlResult = string.Format("INSERT INTO {0} ({1}) VALUES {2}", tableName, cols, string.Join(", ", pocoValues));
sqlQueries.Add(sqlResult);
commands.Add(cmd);
}
sql = string.Format("INSERT INTO {0} ({1}) VALUES {2}", tableName, cols, string.Join(", ", pocoValues));
return cmd;
sql = sqlQueries.ToArray();
return commands.ToArray();
}
public static void CreateTable(this Database db, bool overwrite, Type modelType)
@@ -0,0 +1,101 @@
using System;
using System.Globalization;
namespace Umbraco.Core.Persistence.Querying
{
/// <summary>
/// Logic that is shared with the expression helpers
/// </summary>
internal class BaseExpressionHelper
{
public virtual string GetQuotedValue(object value, Type fieldType, Func<object, string> escapeCallback = null, Func<Type, bool> shouldQuoteCallback = null)
{
if (value == null) return "NULL";
if (escapeCallback == null)
{
escapeCallback = EscapeParam;
}
if (shouldQuoteCallback == null)
{
shouldQuoteCallback = ShouldQuoteValue;
}
if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string))
{
//if (TypeSerializer.CanCreateFromString(fieldType))
//{
// return "'" + EscapeParam(TypeSerializer.SerializeToString(value)) + "'";
//}
throw new NotSupportedException(
string.Format("Property of type: {0} is not supported", fieldType.FullName));
}
if (fieldType == typeof(int))
return ((int)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(float))
return ((float)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(double))
return ((double)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(decimal))
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(DateTime))
{
return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'";
}
if (fieldType == typeof(bool))
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
return ShouldQuoteValue(fieldType)
? "'" + EscapeParam(value) + "'"
: value.ToString();
}
public virtual string EscapeParam(object paramValue)
{
return paramValue.ToString().Replace("'", "''");
}
public virtual string EscapeAtArgument(string exp)
{
if (exp.StartsWith("@"))
return string.Concat("@", exp);
return exp;
}
public virtual bool ShouldQuoteValue(Type fieldType)
{
return true;
}
protected virtual string RemoveQuote(string exp)
{
if (exp.StartsWith("'") && exp.EndsWith("'"))
{
exp = exp.Remove(0, 1);
exp = exp.Remove(exp.Length - 1, 1);
}
return exp;
}
protected virtual string RemoveQuoteFromAlias(string exp)
{
if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'"))
&&
(exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'")))
{
exp = exp.Remove(0, 1);
exp = exp.Remove(exp.Length - 1, 1);
}
return exp;
}
}
}
@@ -8,7 +8,7 @@ using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Persistence.Querying
{
internal class ModelToSqlExpressionHelper<T>
internal class ModelToSqlExpressionHelper<T> : BaseExpressionHelper
{
private string sep = " ";
private BaseMapper _mapper;
@@ -246,7 +246,7 @@ namespace Umbraco.Core.Persistence.Querying
case "ToLower":
return string.Format("lower({0})", r);
case "StartsWith":
return string.Format("upper({0}) like '{1}%'", r, RemoveQuote(args[0].ToString().ToUpper()));
return string.Format("upper({0}) like '{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString().ToUpper())));
case "EndsWith":
return string.Format("upper({0}) like '%{1}'", r, RemoveQuote(args[0].ToString()).ToUpper());
case "Contains":
@@ -435,72 +435,7 @@ namespace Umbraco.Core.Persistence.Querying
public virtual string GetQuotedValue(object value, Type fieldType)
{
if (value == null) return "NULL";
if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string))
{
throw new NotSupportedException(
string.Format("Property of type: {0} is not supported", fieldType.FullName));
}
if (fieldType == typeof(int))
return ((int)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(float))
return ((float)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(double))
return ((double)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(decimal))
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof (DateTime))
{
return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'";
}
if (fieldType == typeof(bool))
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
return ShouldQuoteValue(fieldType)
? "'" + EscapeParam(value) + "'"
: value.ToString();
}
public virtual string EscapeParam(object paramValue)
{
return paramValue.ToString().Replace("'", "''");
}
public virtual bool ShouldQuoteValue(Type fieldType)
{
return true;
}
protected string RemoveQuote(string exp)
{
if (exp.StartsWith("'") && exp.EndsWith("'"))
{
exp = exp.Remove(0, 1);
exp = exp.Remove(exp.Length - 1, 1);
}
return exp;
}
protected string RemoveQuoteFromAlias(string exp)
{
if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'"))
&&
(exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'")))
{
exp = exp.Remove(0, 1);
exp = exp.Remove(exp.Length - 1, 1);
}
return exp;
return GetQuotedValue(value, fieldType, EscapeParam, ShouldQuoteValue);
}
private string GetTrueExpression()
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
@@ -9,7 +8,7 @@ using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Querying
{
internal class PocoToSqlExpressionHelper<T>
internal class PocoToSqlExpressionHelper<T> : BaseExpressionHelper
{
private string sep = " ";
private Database.PocoData pd;
@@ -251,7 +250,7 @@ namespace Umbraco.Core.Persistence.Querying
case "ToLower":
return string.Format("lower({0})", r);
case "StartsWith":
return string.Format("upper({0}) like '{1}%'", r, RemoveQuote(args[0].ToString().ToUpper()));
return string.Format("upper({0}) like '{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString().ToUpper())));
case "EndsWith":
return string.Format("upper({0}) like '%{1}'", r, RemoveQuote(args[0].ToString()).ToUpper());
case "Contains":
@@ -440,53 +439,7 @@ namespace Umbraco.Core.Persistence.Querying
public virtual string GetQuotedValue(object value, Type fieldType)
{
if (value == null) return "NULL";
if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string))
{
//if (TypeSerializer.CanCreateFromString(fieldType))
//{
// return "'" + EscapeParam(TypeSerializer.SerializeToString(value)) + "'";
//}
throw new NotSupportedException(
string.Format("Property of type: {0} is not supported", fieldType.FullName));
}
if (fieldType == typeof(int))
return ((int)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(float))
return ((float)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(double))
return ((double)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof(decimal))
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
if (fieldType == typeof (DateTime))
{
return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'";
}
if (fieldType == typeof(bool))
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
return ShouldQuoteValue(fieldType)
? "'" + EscapeParam(value) + "'"
: value.ToString();
}
public virtual string EscapeParam(object paramValue)
{
return paramValue.ToString().Replace("'", "''");
}
public virtual bool ShouldQuoteValue(Type fieldType)
{
return true;
return GetQuotedValue(value, fieldType, EscapeParam, ShouldQuoteValue);
}
protected virtual string GetFieldName(Database.PocoData pocoData, string name)
@@ -497,30 +450,6 @@ namespace Umbraco.Core.Persistence.Querying
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(column.Value.ColumnName));
}
protected string RemoveQuote(string exp)
{
if (exp.StartsWith("'") && exp.EndsWith("'"))
{
exp = exp.Remove(0, 1);
exp = exp.Remove(exp.Length - 1, 1);
}
return exp;
}
protected string RemoveQuoteFromAlias(string exp)
{
if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'"))
&&
(exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'")))
{
exp = exp.Remove(0, 1);
exp = exp.Remove(exp.Length - 1, 1);
}
return exp;
}
private string GetTrueExpression()
{
object o = GetQuotedTrueValue();
@@ -170,11 +170,31 @@ namespace Umbraco.Core.Persistence.Repositories
return content;
}
public override void DeleteVersion(Guid versionId)
{
var sql = new Sql()
.Select("*")
.From<DocumentDto>()
.InnerJoin<ContentVersionDto>().On<ContentVersionDto, DocumentDto>(left => left.VersionId, right => right.VersionId)
.Where<ContentVersionDto>(x => x.VersionId == versionId)
.Where<DocumentDto>(x => x.Newest == true);
var dto = Database.Fetch<DocumentDto, ContentVersionDto>(sql).FirstOrDefault();
if(dto == null) return;
using (var transaction = Database.GetTransaction())
{
PerformDeleteVersion(dto.NodeId, versionId);
transaction.Complete();
}
}
protected override void PerformDeleteVersion(int id, Guid versionId)
{
Database.Delete<PreviewXmlDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<PropertyDataDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<ContentVersionDto>("WHERE nodeId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<PropertyDataDto>("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<ContentVersionDto>("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<DocumentDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
}
@@ -275,8 +295,9 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PersistUpdatedItem(IContent entity)
{
var publishedState = ((Content) entity).PublishedState;
//A new version should only be created if published state (or language) has changed
bool shouldCreateNewVersion = (((ICanBeDirty)entity).IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished) || ((ICanBeDirty)entity).IsPropertyDirty("Language");
//check if we need to create a new version
bool shouldCreateNewVersion = entity.ShouldCreateNewVersion(publishedState);
if (shouldCreateNewVersion)
{
//Updates Modified date and Version Guid
@@ -327,7 +348,8 @@ namespace Umbraco.Core.Persistence.Repositories
//If Published state has changed then previous versions should have their publish state reset.
//If state has been changed to unpublished the previous versions publish state should also be reset.
if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
//if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
if (entity.ShouldClearPublishedFlagForPreviousVersions(publishedState, shouldCreateNewVersion))
{
var publishedDocs = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND published = @IsPublished", new { Id = entity.Id, IsPublished = true });
foreach (var doc in publishedDocs)
@@ -338,19 +360,18 @@ namespace Umbraco.Core.Persistence.Repositories
}
}
//Look up (newest) entries by id in cmsDocument table to set newest = false
var documentDtos = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND newest = @IsNewest", new { Id = entity.Id, IsNewest = true });
foreach (var documentDto in documentDtos)
{
var docDto = documentDto;
docDto.Newest = false;
Database.Update(docDto);
}
var contentVersionDto = dto.ContentVersionDto;
if (shouldCreateNewVersion)
{
//Look up (newest) entries by id in cmsDocument table to set newest = false
//NOTE: This is only relevant when a new version is created, which is why its done inside this if-statement.
var documentDtos = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND newest = @IsNewest", new { Id = entity.Id, IsNewest = true });
foreach (var documentDto in documentDtos)
{
var docDto = documentDto;
docDto.Newest = false;
Database.Update(docDto);
}
//Create a new version - cmsContentVersion
//Assumes a new Version guid and Version date (modified date) has been set
Database.Insert(contentVersionDto);
@@ -449,7 +470,19 @@ namespace Umbraco.Core.Persistence.Repositories
foreach (var dto in dtos)
{
yield return CreateContentFromDto(dto, dto.VersionId);
//Check in the cache first. If it exists there AND it is published
// then we can use that entity. Otherwise if it is not published (which can be the case
// because we only store the 'latest' entries in the cache which might not be the published
// version)
var fromCache = TryGetFromCache(dto.NodeId);
if (fromCache.Success && fromCache.Result.Published)
{
yield return fromCache.Result;
}
else
{
yield return CreateContentFromDto(dto, dto.VersionId);
}
}
}
@@ -469,7 +502,7 @@ namespace Umbraco.Core.Persistence.Repositories
}
#endregion
/// <summary>
/// Private method to create a content object from a DocumentDto, which is used by Get and GetByVersion.
/// </summary>
@@ -84,7 +84,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
var sql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId).Append(GetGroupBy(isContent, isMedia));
var sql = GetBaseWhere(GetBase, isContent, isMedia, string.Empty, objectTypeId).Append(GetGroupBy(isContent, isMedia));
var dtos = isMedia
? _work.Database.Fetch<UmbracoEntityDto, UmbracoPropertyDto, UmbracoEntityDto>(
new UmbracoEntityRelator().Map, sql)
@@ -101,7 +101,8 @@ namespace Umbraco.Core.Persistence.Repositories
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query)
{
var sqlClause = GetBase(false, false);
var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query<IUmbracoEntity>) query).WhereClauses()));
var sqlClause = GetBase(false, false, wheres);
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
var sql = translator.Translate().Append(GetGroupBy(false, false));
@@ -117,7 +118,9 @@ namespace Umbraco.Core.Persistence.Repositories
{
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId);
var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query<IUmbracoEntity>)query).WhereClauses()));
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, wheres, objectTypeId);
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
var sql = translator.Translate().Append(GetGroupBy(isContent, isMedia));
@@ -136,7 +139,7 @@ namespace Umbraco.Core.Persistence.Repositories
#region Sql Statements
protected virtual Sql GetBase(bool isContent, bool isMedia)
protected virtual Sql GetBase(bool isContent, bool isMedia, string additionWhereStatement = "")
{
var columns = new List<object>
{
@@ -187,42 +190,38 @@ namespace Umbraco.Core.Persistence.Repositories
.On("umbracoNode.id = latest.nodeId");
}
/*if (isContent)
{
sql.LeftJoin(
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid" +
" INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId) as property")
.On("umbracoNode.id = property.contentNodeId AND latest.versionId = property.versionId");
}*/
if (isMedia)
{
sql.LeftJoin(
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid" +
" INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId) as property")
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData " +
"INNER JOIN umbracoNode ON cmsPropertyData.contentNodeId = umbracoNode.id " +
"INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid " +
"INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId "+
"WHERE umbracoNode.nodeObjectType = '" + Constants.ObjectTypes.Media + "'" + additionWhereStatement + ") as property")
.On("umbracoNode.id = property.contentNodeId");
}
return sql;
}
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, Guid id)
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, string additionWhereStatement, Guid id)
{
var sql = baseQuery(isContent, isMedia)
var sql = baseQuery(isContent, isMedia, additionWhereStatement)
.Where("umbracoNode.nodeObjectType = @NodeObjectType", new { NodeObjectType = id });
return sql;
}
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, int id)
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, int id)
{
var sql = baseQuery(isContent, isMedia)
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'")
.Where("umbracoNode.id = @Id", new { Id = id })
.Append(GetGroupBy(isContent, isMedia));
return sql;
}
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, Guid objectId, int id)
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, Guid objectId, int id)
{
var sql = baseQuery(isContent, isMedia)
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'")
.Where("umbracoNode.id = @Id AND umbracoNode.nodeObjectType = @NodeObjectType",
new {Id = id, NodeObjectType = objectId});
return sql;
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Querying;
@@ -15,7 +16,7 @@ namespace Umbraco.Core.Persistence.Repositories
IContent GetByLanguage(int id, string language);
/// <summary>
/// Gets all published Content byh the specified query
/// Gets all published Content by the specified query
/// </summary>
/// <param name="query">Query to execute against published versions</param>
/// <returns>An enumerable list of <see cref="IContent"/></returns>
@@ -4,6 +4,5 @@ namespace Umbraco.Core.Persistence.Repositories
{
public interface IMediaRepository : IRepositoryVersionable<int, IMedia>
{
}
}
@@ -176,8 +176,8 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PerformDeleteVersion(int id, Guid versionId)
{
Database.Delete<PreviewXmlDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<PropertyDataDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<ContentVersionDto>("WHERE nodeId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<PropertyDataDto>("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete<ContentVersionDto>("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
}
#endregion
@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
{
/// <summary>
/// Represents a repository specific to the Recycle Bins
/// available for Content and Media.
/// </summary>
internal class RecycleBinRepository : DisposableObject
{
private readonly IDatabaseUnitOfWork _unitOfWork;
public RecycleBinRepository(IDatabaseUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
/// <summary>
/// Gets a list of files, which are referenced on items in the Recycle Bin.
/// The list is generated by the convention that a file is referenced by
/// the Upload data type or a property type with the alias 'umbracoFile'.
/// </summary>
/// <param name="nodeObjectType"></param>
/// <returns></returns>
public List<string> GetFilesInRecycleBin(Guid nodeObjectType)
{
var db = _unitOfWork.Database;
//Issue query to get all trashed content or media that has the Upload field as a property
//The value for each field is stored in a list: FilesToDelete<string>()
//Alias: Constants.Conventions.Media.File and ControlId: Constants.PropertyEditors.UploadField
var sql = new Sql();
sql.Select("DISTINCT(dataNvarchar)")
.From<PropertyDataDto>()
.InnerJoin<NodeDto>().On<PropertyDataDto, NodeDto>(left => left.NodeId, right => right.NodeId)
.InnerJoin<PropertyTypeDto>().On<PropertyDataDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.InnerJoin<DataTypeDto>().On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
.Where("umbracoNode.trashed = '1' AND umbracoNode.nodeObjectType = @NodeObjectType AND dataNvarchar IS NOT NULL AND (cmsPropertyType.Alias = @FileAlias OR cmsDataType.controlId = @ControlId)",
new { FileAlias = Constants.Conventions.Media.File, NodeObjectType = nodeObjectType, ControlId = Constants.PropertyEditors.UploadField });
var files = db.Fetch<string>(sql);
return files;
}
/// <summary>
/// Gets a list of Ids for each of the items in the Recycle Bin.
/// </summary>
/// <param name="nodeObjectType"></param>
/// <returns></returns>
public List<int> GetIdsOfItemsInRecycleBin(Guid nodeObjectType)
{
var db = _unitOfWork.Database;
var idsSql = new Sql();
idsSql.Select("DISTINCT(id)")
.From<NodeDto>()
.Where<NodeDto>(x => x.Trashed && x.NodeObjectType == nodeObjectType);
var ids = db.Fetch<int>(idsSql);
return ids;
}
/// <summary>
/// Empties the Recycle Bin by running single bulk-Delete queries
/// against the Content- or Media's Recycle Bin.
/// </summary>
/// <param name="nodeObjectType"></param>
/// <returns></returns>
public bool EmptyRecycleBin(Guid nodeObjectType)
{
var db = _unitOfWork.Database;
//Construct and execute delete statements for all trashed items by 'nodeObjectType'
var deletes = new List<string>
{
FormatDeleteStatement("umbracoUser2NodeNotify", "nodeId"),
FormatDeleteStatement("umbracoUser2NodePermission", "nodeId"),
FormatDeleteStatement("umbracoRelation", "parentId"),
FormatDeleteStatement("umbracoRelation", "childId"),
FormatDeleteStatement("cmsTagRelationship", "nodeId"),
FormatDeleteStatement("umbracoDomains", "domainRootStructureID"),
FormatDeleteStatement("cmsDocument", "NodeId"),
FormatDeleteStatement("cmsPropertyData", "contentNodeId"),
FormatDeleteStatement("cmsPreviewXml", "nodeId"),
FormatDeleteStatement("cmsContentVersion", "ContentId"),
FormatDeleteStatement("cmsContentXml", "nodeID"),
FormatDeleteStatement("cmsContent", "NodeId"),
"UPDATE umbracoNode SET parentID = '-20' WHERE trashed = '1' AND nodeObjectType = @NodeObjectType",
"DELETE FROM umbracoNode WHERE trashed = '1' AND nodeObjectType = @NodeObjectType"
};
//Wraps in transaction - this improves performance and also ensures
// that if any of the deletions fails that the whole thing is rolled back.
using (var trans = db.GetTransaction())
{
try
{
foreach (var delete in deletes)
{
db.Execute(delete, new { NodeObjectType = nodeObjectType });
}
trans.Complete();
return true;
}
catch (Exception ex)
{
trans.Dispose();
LogHelper.Error<RecycleBinRepository>("An error occurred while emptying the Recycle Bin: " + ex.Message, ex);
return false;
}
}
}
/// <summary>
/// Deletes all files passed in.
/// </summary>
/// <param name="files"></param>
/// <returns></returns>
public bool DeleteFiles(IEnumerable<string> files)
{
try
{
var fs = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
Parallel.ForEach(files, file =>
{
if (UmbracoSettings.UploadAllowDirectories)
{
var relativeFilePath = fs.GetRelativePath(file);
var parentDirectory = System.IO.Path.GetDirectoryName(relativeFilePath);
fs.DeleteDirectory(parentDirectory, true);
}
else
{
fs.DeleteFile(file, true);
}
});
return true;
}
catch (Exception ex)
{
LogHelper.Error<RecycleBinRepository>("An error occurred while deleting files attached to deleted nodes: " + ex.Message, ex);
return false;
}
}
private string FormatDeleteStatement(string tableName, string keyName)
{
//This query works with sql ce and sql server:
//DELETE FROM umbracoUser2NodeNotify WHERE umbracoUser2NodeNotify.nodeId IN
//(SELECT nodeId FROM umbracoUser2NodeNotify as TB1 INNER JOIN umbracoNode as TB2 ON TB1.nodeId = TB2.id WHERE TB2.trashed = '1' AND TB2.nodeObjectType = 'C66BA18E-EAF3-4CFF-8A22-41B16D66A972')
return
string.Format(
"DELETE FROM {0} WHERE {0}.{1} IN (SELECT TB1.{1} FROM {0} as TB1 INNER JOIN umbracoNode as TB2 ON TB1.{1} = TB2.id WHERE TB2.trashed = '1' AND TB2.nodeObjectType = @NodeObjectType)",
tableName, keyName);
}
/// <summary>
/// Dispose disposable properties
/// </summary>
/// <remarks>
/// Ensure the unit of work is disposed
/// </remarks>
protected override void DisposeResources()
{
_unitOfWork.DisposeIfDisposable();
}
}
}
@@ -85,11 +85,10 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns></returns>
public TEntity Get(TId id)
{
Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString());
var rEntity = _cache.GetById(typeof(TEntity), key);
if (rEntity != null)
var fromCache = TryGetFromCache(id);
if (fromCache.Success)
{
return (TEntity)rEntity;
return fromCache.Result;
}
var entity = PerformGet(id);
@@ -112,6 +111,17 @@ namespace Umbraco.Core.Persistence.Repositories
return entity;
}
protected Attempt<TEntity> TryGetFromCache(TId id)
{
Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString());
var rEntity = _cache.GetById(typeof(TEntity), key);
if (rEntity != null)
{
return new Attempt<TEntity>(true, (TEntity) rEntity);
}
return Attempt<TEntity>.False;
}
protected abstract IEnumerable<TEntity> PerformGetAll(params TId[] ids);
/// <summary>
/// Gets all entities of type TEntity or a list according to the passed in Ids
@@ -173,14 +183,12 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns></returns>
public bool Exists(TId id)
{
Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString());
var rEntity = _cache.GetById(typeof(TEntity), key);
if (rEntity != null)
var fromCache = TryGetFromCache(id);
if (fromCache.Success)
{
return true;
}
return PerformExists(id);
return PerformExists(id);
}
protected abstract int PerformCount(IQuery<TEntity> query);
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
public int Compare(string x, string y)
{
if (x.LastIndexOf(')') == x.Length - 1 && y.LastIndexOf(')') == y.Length - 1)
if (x.LastIndexOf('(') != -1 && x.LastIndexOf(')') == x.Length - 1 && y.LastIndexOf(')') == y.Length - 1)
{
if (x.ToLower().Substring(0, x.LastIndexOf('(')) == y.ToLower().Substring(0, y.LastIndexOf('(')))
{
@@ -43,8 +43,8 @@ namespace Umbraco.Core.Persistence.Repositories
public virtual void DeleteVersion(Guid versionId)
{
var dto = Database.FirstOrDefault<ContentVersionDto>("WHERE versionId = @VersionId AND newest = @Newest", new { VersionId = versionId, Newest = false });
Mandate.That<Exception>(dto != null);
var dto = Database.FirstOrDefault<ContentVersionDto>("WHERE versionId = @VersionId", new { VersionId = versionId });
if(dto == null) return;
using (var transaction = Database.GetTransaction())
{
@@ -56,8 +56,8 @@ namespace Umbraco.Core.Persistence.Repositories
public virtual void DeleteVersions(int id, DateTime versionDate)
{
var list = Database.Fetch<ContentVersionDto>("WHERE nodeId = @Id AND VersionDate < @VersionDate", new { Id = id, VersionDate = versionDate });
Mandate.That<Exception>(list.Any());
var list = Database.Fetch<ContentVersionDto>("WHERE ContentId = @Id AND VersionDate < @VersionDate", new { Id = id, VersionDate = versionDate });
if (list.Any() == false) return;
using (var transaction = Database.GetTransaction())
{
@@ -9,34 +9,6 @@ namespace Umbraco.Core.Persistence
/// </summary>
public class RepositoryFactory
{
internal virtual ServerRegistrationRepository CreateServerRegistrationRepository(IDatabaseUnitOfWork uow)
{
return new ServerRegistrationRepository(
uow,
NullCacheProvider.Current);
}
internal virtual IUserTypeRepository CreateUserTypeRepository(IDatabaseUnitOfWork uow)
{
return new UserTypeRepository(
uow,
NullCacheProvider.Current);
}
internal virtual IUserRepository CreateUserRepository(IDatabaseUnitOfWork uow)
{
return new UserRepository(
uow,
NullCacheProvider.Current,
CreateUserTypeRepository(uow));
}
internal virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow)
{
return new EntityRepository(uow);
}
public virtual IContentRepository CreateContentRepository(IDatabaseUnitOfWork uow)
{
return new ContentRepository(
@@ -120,5 +92,37 @@ namespace Umbraco.Core.Persistence
{
return new TemplateRepository(uow, RuntimeCacheProvider.Current);
}
internal virtual ServerRegistrationRepository CreateServerRegistrationRepository(IDatabaseUnitOfWork uow)
{
return new ServerRegistrationRepository(
uow,
NullCacheProvider.Current);
}
internal virtual IUserTypeRepository CreateUserTypeRepository(IDatabaseUnitOfWork uow)
{
return new UserTypeRepository(
uow,
NullCacheProvider.Current);
}
internal virtual IUserRepository CreateUserRepository(IDatabaseUnitOfWork uow)
{
return new UserRepository(
uow,
NullCacheProvider.Current,
CreateUserTypeRepository(uow));
}
internal virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow)
{
return new EntityRepository(uow);
}
internal virtual RecycleBinRepository CreateRecycleBinRepository(IDatabaseUnitOfWork uow)
{
return new RecycleBinRepository(uow);
}
}
}
@@ -13,6 +13,20 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public static ISqlSyntaxProvider Provider { get { return new SqlServerSyntaxProvider(); } }
}
/// <summary>
/// Represents the version name of SQL server (i.e. the year 2008, 2005, etc...)
/// </summary>
internal enum SqlServerVersionName
{
Invalid = -1,
V7 = 0,
V2000 = 1,
V2005 = 2,
V2008 = 3,
V2012 = 4,
Other = 5
}
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Server
/// </summary>
@@ -36,6 +50,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
InitColumnTypeMap();
}
/// <summary>
/// Gets/sets the version of the current SQL server instance
/// </summary>
internal Lazy<SqlServerVersionName> VersionName { get; set; }
public override string GetQuotedTableName(string tableName)
{
return string.Format("[{0}]", tableName);
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Persistence
/// can then override any additional execution (such as additional loggging, functionality, etc...) that we need to without breaking compatibility since we'll always be exposing
/// this object instead of the base PetaPoco database object.
/// </remarks>
public class UmbracoDatabase : Database
public class UmbracoDatabase : Database, IDisposeOnRequestEnd
{
private readonly Guid _instanceId = Guid.NewGuid();
/// <summary>
+6 -6
View File
@@ -20,7 +20,6 @@ using File = System.IO.File;
namespace Umbraco.Core
{
/// <summary>
/// Used to resolve all plugin types and cache them and is also used to instantiate plugin types
/// </summary>
@@ -37,6 +36,7 @@ namespace Umbraco.Core
internal class PluginManager
{
private readonly ApplicationContext _appContext;
private const string CacheKey = "umbraco-plugins.list";
/// <summary>
/// Creates a new PluginManager with an ApplicationContext instance which ensures that the plugin xml
@@ -251,7 +251,7 @@ namespace Umbraco.Core
XDocument xml;
if (_appContext != null)
{
xml = _appContext.ApplicationCache.GetCacheItem("umbraco-plugins.list",
xml = _appContext.ApplicationCache.GetCacheItem(CacheKey,
new TimeSpan(0, 0, 5, 0),
() => XDocument.Load(filePath));
}
@@ -304,18 +304,18 @@ namespace Umbraco.Core
if (_appContext != null)
{
_appContext.ApplicationCache.ClearCacheItem("umbraco-plugins.list");
_appContext.ApplicationCache.ClearCacheItem(CacheKey);
}
}
private string GetPluginListFilePath()
{
return Path.Combine(_tempFolder, "umbraco-plugins.list");
return Path.Combine(_tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName));
}
private string GetPluginHashFilePath()
{
return Path.Combine(_tempFolder, "umbraco-plugins.hash");
return Path.Combine(_tempFolder, string.Format("umbraco-plugins.{0}.hash", NetworkHelper.FileSafeMachineName));
}
/// <summary>
+13 -7
View File
@@ -8,15 +8,14 @@ namespace Umbraco.Core.Publishing
/// </summary>
internal class PublishStatus
{
public IContent ContentItem { get; private set; }
public PublishStatusType StatusType { get; internal set; }
/// <summary>
/// Gets sets the invalid properties if the status failed due to validation.
/// </summary>
public IEnumerable<Property> InvalidProperties { get; set; }
public PublishStatus()
{
//initialize
InvalidProperties = new List<Property>();
}
public PublishStatus(IContent content, PublishStatusType statusType)
: this()
{
ContentItem = content;
StatusType = statusType;
@@ -29,6 +28,13 @@ namespace Umbraco.Core.Publishing
: this(content, PublishStatusType.Success)
{
}
public IContent ContentItem { get; private set; }
public PublishStatusType StatusType { get; internal set; }
/// <summary>
/// Gets sets the invalid properties if the status failed due to validation.
/// </summary>
public IEnumerable<Property> InvalidProperties { get; set; }
}
}
@@ -0,0 +1,199 @@
using System;
using System.Web;
using System.Web.Security;
using Newtonsoft.Json;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Security
{
internal static class FormsAuthenticationTicketExtensions
{
public static UmbracoBackOfficeIdentity CreateUmbracoIdentity(this FormsAuthenticationTicket ticket)
{
try
{
//create the Umbraco user identity
return new UmbracoBackOfficeIdentity(ticket);
}
catch (Exception ex)
{
//This might occur if we cannot decrypt the value in which case we'll just ignore it, it will
// be handled by the base pages
LogHelper.Error(typeof(FormsAuthenticationTicketExtensions), "An error occurred decrypting the user's ticket", ex);
return null;
}
}
}
/// <summary>
/// Extensions to create and renew and remove authentication tickets for the Umbraco back office
/// </summary>
internal static class AuthenticationExtensions
{
//public static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContextBase http)
//{
// return http.User.Identity as UmbracoBackOfficeIdentity;
//}
//internal static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContext http)
//{
// return new HttpContextWrapper(http).GetCurrentIdentity();
//}
/// <summary>
/// This clears the authentication cookie
/// </summary>
public static void UmbracoLogout(this HttpContextBase http)
{
Logout(http, UmbracoSettings.AuthCookieName);
}
internal static void UmbracoLogout(this HttpContext http)
{
new HttpContextWrapper(http).UmbracoLogout();
}
/// <summary>
/// Creates the umbraco authentication ticket
/// </summary>
/// <param name="http"></param>
/// <param name="userdata"></param>
public static void CreateUmbracoAuthTicket(this HttpContextBase http, UserData userdata)
{
CreateAuthTicket(
http,
userdata,
//This is one full day... this is how Umbraco has always created this cookie, it is setup to always
//expire one day from issue and it never gets updated.
1440,
"/",
UmbracoSettings.AuthCookieName,
UmbracoSettings.AuthCookieDomain);
}
internal static void CreateUmbracoAuthTicket(this HttpContext http, UserData userdata)
{
new HttpContextWrapper(http).CreateUmbracoAuthTicket(userdata);
}
/// <summary>
/// Gets the umbraco auth ticket
/// </summary>
/// <param name="http"></param>
/// <returns></returns>
public static FormsAuthenticationTicket GetUmbracoAuthTicket(this HttpContextBase http)
{
return GetAuthTicket(http, UmbracoSettings.AuthCookieName);
}
internal static FormsAuthenticationTicket GetUmbracoAuthTicket(this HttpContext http)
{
return new HttpContextWrapper(http).GetUmbracoAuthTicket();
}
/// <summary>
/// This clears the authentication cookie
/// </summary>
/// <param name="http"></param>
/// <param name="cookieName"></param>
private static void Logout(this HttpContextBase http, string cookieName)
{
//remove from the request
http.Request.Cookies.Remove(cookieName);
//expire from the response
var formsCookie = http.Response.Cookies[cookieName];
if (formsCookie != null)
{
//this will expire immediately and be removed from the browser
formsCookie.Expires = DateTime.Now.AddYears(-1);
}
else
{
//ensure there's def an expired cookie
http.Response.Cookies.Add(new HttpCookie(cookieName) { Expires = DateTime.Now.AddYears(-1) });
}
}
/// <summary>
/// In v6 this is a custom cookie, in v7 this is a real formsauth cookie.
/// </summary>
/// <param name="http"></param>
/// <param name="cookieName"></param>
/// <returns></returns>
private static FormsAuthenticationTicket GetAuthTicket(this HttpContextBase http, string cookieName)
{
var formsCookie = http.Request.Cookies[cookieName];
if (formsCookie == null)
{
return null;
}
try
{
//get the cookie value
var cookieVal = formsCookie.Value.DecryptWithMachineKey();
//here we need to see if the cookie val can be serialized into UserData, if not it means it's probably an old cookie
var deserialized = JsonConvert.DeserializeObject<UserData>(cookieVal);
//in v6, we're not using real FormsAuth but our own custom cookie and then we just return a custom FormsAuth ticket
// for this request.
return new FormsAuthenticationTicket(
4,
deserialized.RealName,
DateTime.Now,
DateTime.Now.AddMinutes(GlobalSettings.TimeOutInMinutes),
false,
cookieVal,
"/");
}
catch (Exception)
{
//occurs when decryption fails
http.Logout(cookieName);
return null;
}
}
/// <summary>
/// Creates a custom umbraco auth cookie with the data specified
/// </summary>
/// <param name="http">The HTTP.</param>
/// <param name="userData">The user data.</param>
/// <param name="minutesPersisted">The minutes persisted.</param>
/// <param name="cookiePath">The cookie path.</param>
/// <param name="cookieName">Name of the cookie.</param>
/// <param name="cookieDomain">The cookie domain.</param>
private static void CreateAuthTicket(this HttpContextBase http,
UserData userData,
int minutesPersisted,
string cookiePath,
string cookieName,
string cookieDomain)
{
var cookie = new HttpCookie(cookieName);
if (GlobalSettings.UseSSL)
cookie.Secure = true;
//ensure http only, this should only be able to be accessed via the server
cookie.HttpOnly = true;
cookie.Path = cookiePath;
cookie.Domain = cookieDomain;
cookie.Expires = DateTime.Now.AddMinutes(minutesPersisted);
//serialize the user data
var json = JsonConvert.SerializeObject(userData);
//encrypt it
var encTicket = json.EncryptWithMachineKey();
//set the cookie value
cookie.Value = encTicket;
http.Response.Cookies.Set(cookie);
}
}
}
@@ -0,0 +1,110 @@
using System;
using System.Web;
using System.Web.Security;
using Newtonsoft.Json;
namespace Umbraco.Core.Security
{
/// <summary>
/// A custom user identity for the Umbraco backoffice
/// </summary>
/// <remarks>
/// All values are lazy loaded for performance reasons as the constructor is called for every single request
/// </remarks>
internal class UmbracoBackOfficeIdentity : FormsIdentity
{
public UmbracoBackOfficeIdentity(FormsAuthenticationTicket ticket)
: base(ticket)
{
UserData = ticket.UserData;
EnsureDeserialized();
}
protected readonly string UserData;
internal UserData DeserializedData;
public string UserContextId
{
get { return DeserializedData.UserContextId; }
}
public int StartContentNode
{
get { return DeserializedData.StartContentNode; }
}
public int StartMediaNode
{
get { return DeserializedData.StartMediaNode; }
}
public string[] AllowedApplications
{
get { return DeserializedData.AllowedApplications; }
}
public object Id
{
get { return DeserializedData.Id; }
}
public string RealName
{
get { return DeserializedData.RealName; }
}
public string Culture
{
get { return DeserializedData.Culture; }
}
//public int SessionTimeout
//{
// get
// {
// EnsureDeserialized();
// return DeserializedData.SessionTimeout;
// }
//}
public string[] Roles
{
get { return DeserializedData.Roles; }
}
/// <summary>
/// This will ensure we only deserialize once
/// </summary>
/// <remarks>
/// For performance reasons, we'll also check if there's an http context available,
/// if so, we'll chuck our instance in there so that we only deserialize once per request.
/// </remarks>
protected void EnsureDeserialized()
{
if (DeserializedData != null)
return;
if (HttpContext.Current != null)
{
//check if we've already done this in this request
var data = HttpContext.Current.Items[typeof(UmbracoBackOfficeIdentity)] as UserData;
if (data != null)
{
DeserializedData = data;
return;
}
}
if (string.IsNullOrEmpty(UserData))
{
throw new NullReferenceException("The " + typeof(UserData) + " found in the ticket cannot be empty");
}
DeserializedData = JsonConvert.DeserializeObject<UserData>(UserData);
if (HttpContext.Current != null)
{
HttpContext.Current.Items[typeof (UmbracoBackOfficeIdentity)] = DeserializedData;
}
}
}
}
+51
View File
@@ -0,0 +1,51 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Security
{
/// <summary>
/// Data structure used to store information in the authentication cookie
/// </summary>
[DataContract(Name = "userData", Namespace = "")]
internal class UserData
{
public UserData()
{
AllowedApplications = new string[] {};
Roles = new string[] {};
}
///// <summary>
///// When their session is going to expire (in ticks)
///// </summary>
//[DataMember(Name = "timeout")]
//public long Timeout { get; set; }
[DataMember(Name = "userContextId")]
public string UserContextId { get; set; }
[DataMember(Name = "id")]
public object Id { get; set; }
[DataMember(Name = "roles")]
public string[] Roles { get; set; }
[DataMember(Name = "username")]
public string Username { get; set; }
[DataMember(Name = "name")]
public string RealName { get; set; }
[DataMember(Name = "startContent")]
public int StartContentNode { get; set; }
[DataMember(Name = "startMedia")]
public int StartMediaNode { get; set; }
[DataMember(Name = "allowedApps")]
public string[] AllowedApplications { get; set; }
[DataMember(Name = "culture")]
public string Culture { get; set; }
}
}
+92 -51
View File
@@ -13,6 +13,7 @@ using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
@@ -250,6 +251,17 @@ namespace Umbraco.Core.Services
}
}
internal IEnumerable<IContent> GetPublishedContentOfContentType(int id)
{
using (var repository = _repositoryFactory.CreateContentRepository(_uowProvider.GetUnitOfWork()))
{
var query = Query<IContent>.Builder.Where(x => x.ContentTypeId == id);
var contents = repository.GetByPublishedVersion(query);
return contents;
}
}
/// <summary>
/// Gets a collection of <see cref="IContent"/> objects by Level
/// </summary>
@@ -431,6 +443,19 @@ namespace Umbraco.Core.Services
}
}
/// <summary>
/// Gets all published content items
/// </summary>
/// <returns></returns>
internal IEnumerable<IContent> GetAllPublished()
{
using (var repository = _repositoryFactory.CreateContentRepository(_uowProvider.GetUnitOfWork()))
{
var query = Query<IContent>.Builder.Where(x => x.Trashed == false);
return repository.GetByPublishedVersion(query);
}
}
/// <summary>
/// Gets a collection of <see cref="IContent"/> objects, which has an expiration date less than or equal to today.
/// </summary>
@@ -986,27 +1011,29 @@ namespace Umbraco.Core.Services
/// </summary>
public void EmptyRecycleBin()
{
//TODO: Why don't we have a base class to share between MediaService/ContentService as some of this is exacty the same?
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentRepository(uow))
using (new WriteLock(Locker))
{
var query = Query<IContent>.Builder.Where(x => x.Trashed == true);
var contents = repository.GetByQuery(query).OrderByDescending(x => x.Level);
List<int> ids;
List<string> files;
bool success;
var nodeObjectType = new Guid(Constants.ObjectTypes.Document);
foreach (var content in contents)
using (var repository = _repositoryFactory.CreateRecycleBinRepository(_uowProvider.GetUnitOfWork()))
{
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IContent>(content), this))
continue;
ids = repository.GetIdsOfItemsInRecycleBin(nodeObjectType);
files = repository.GetFilesInRecycleBin(nodeObjectType);
repository.Delete(content);
if (EmptyingRecycleBin.IsRaisedEventCancelled(new RecycleBinEventArgs(nodeObjectType, ids, files), this))
return;
Deleted.RaiseEvent(new DeleteEventArgs<IContent>(content, false), this);
success = repository.EmptyRecycleBin(nodeObjectType);
if (success)
repository.DeleteFiles(files);
}
uow.Commit();
}
Audit.Add(AuditTypes.Delete, "Empty Recycle Bin performed by user", 0, -20);
EmptiedRecycleBin.RaiseEvent(new RecycleBinEventArgs(nodeObjectType, ids, files, success), this);
}
Audit.Add(AuditTypes.Delete, "Empty Content Recycle Bin performed by user", 0, -20);
}
/// <summary>
@@ -1353,46 +1380,45 @@ namespace Umbraco.Core.Services
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentRepository(uow))
{
if (contentTypeIds.Any() == false)
{
//Remove all Document records from the cmsContentXml table (DO NOT REMOVE Media/Members!)
uow.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
INNER JOIN cmsDocument ON cmsContentXml.nodeId = cmsDocument.nodeId)");
//get all content items that are published
// Consider creating a Path query instead of recursive method:
// var query = Query<IContent>.Builder.Where(x => x.Path.StartsWith("-1"));
var rootContent = GetRootContent();
foreach (var content in rootContent.Where(content => content.Published))
{
list.Add(content);
list.AddRange(GetPublishedDescendants(content));
}
}
else
{
foreach (var id in contentTypeIds)
{
//first we'll clear out the data from the cmsContentXml table for this type
uow.Database.Execute(@"delete from cmsContentXml where nodeId in
(select cmsDocument.nodeId from cmsDocument
inner join cmsContent on cmsDocument.nodeId = cmsContent.nodeId
where published = 1 and contentType = @contentTypeId)", new {contentTypeId = id});
//First we're going to get the data that needs to be inserted before clearing anything, this
//ensures that we don't accidentally leave the content xml table empty if something happens
//during the lookup process.
//now get all published content objects of this type and add to the list
list.AddRange(GetContentOfContentType(id).Where(content => content.Published));
}
}
list.AddRange(contentTypeIds.Any() == false
? GetAllPublished()
: contentTypeIds.SelectMany(GetPublishedContentOfContentType));
var xmlItems = new List<ContentXmlDto>();
foreach (var c in list)
{
//generate the xml
var xml = c.ToXml();
//create the dto to insert
var poco = new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) };
//insert it into the database
uow.Database.Insert(poco);
xmlItems.Add(new ContentXmlDto {NodeId = c.Id, Xml = xml.ToString(SaveOptions.None)});
}
//Ok, now we need to remove the data and re-insert it, we'll do this all in one transaction too.
using (var tr = uow.Database.GetTransaction())
{
if (contentTypeIds.Any() == false)
{
//Remove all Document records from the cmsContentXml table (DO NOT REMOVE Media/Members!)
uow.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
INNER JOIN cmsDocument ON cmsContentXml.nodeId = cmsDocument.nodeId)");
}
else
{
foreach (var id in contentTypeIds)
{
//first we'll clear out the data from the cmsContentXml table for this type
uow.Database.Execute(@"delete from cmsContentXml where nodeId in
(select cmsDocument.nodeId from cmsDocument
inner join cmsContent on cmsDocument.nodeId = cmsContent.nodeId
where published = 1 and contentType = @contentTypeId)", new { contentTypeId = id });
}
}
//bulk insert it into the database
uow.Database.BulkInsertRecords(xmlItems, tr);
}
}
Audit.Add(AuditTypes.Publish, "RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
@@ -1436,7 +1462,12 @@ namespace Umbraco.Core.Services
LogHelper.Info<ContentService>(
string.Format("Content '{0}' with Id '{1}' could not be published because of invalid properties.",
content.Name, content.Id));
result.Add(new Attempt<PublishStatus>(false, new PublishStatus(content, PublishStatusType.FailedContentInvalid)));
result.Add(
new Attempt<PublishStatus>(false,
new PublishStatus(content, PublishStatusType.FailedContentInvalid)
{
InvalidProperties = ((ContentBase) content).LastInvalidProperties
}));
return result;
}
@@ -1854,7 +1885,7 @@ namespace Umbraco.Core.Services
/// Occurs after Create
/// </summary>
/// <remarks>
/// Please note that the Content object has been created, but not saved
/// Please note that the Content object has been created, but might not have been saved
/// so it does not have an identity yet (meaning no Id has been set).
/// </remarks>
public static event TypedEventHandler<IContentService, NewEventArgs<IContent>> Created;
@@ -1908,6 +1939,16 @@ namespace Umbraco.Core.Services
/// Occurs after Send to Publish
/// </summary>
public static event TypedEventHandler<IContentService, SendToPublishEventArgs<IContent>> SentToPublish;
/// <summary>
/// Occurs before the Recycle Bin is emptied
/// </summary>
public static event TypedEventHandler<IContentService, RecycleBinEventArgs> EmptyingRecycleBin;
/// <summary>
/// Occurs after the Recycle Bin has been Emptied
/// </summary>
public static event TypedEventHandler<IContentService, RecycleBinEventArgs> EmptiedRecycleBin;
#endregion
}
}
+35 -21
View File
@@ -11,10 +11,11 @@ using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
namespace Umbraco.Core.Services
{
/// <summary>
/// <summary>
/// Represents the Media Service, which is an easy access to operations involving <see cref="IMedia"/>
/// </summary>
public class MediaService : IMediaService
@@ -536,27 +537,29 @@ namespace Umbraco.Core.Services
/// </summary>
public void EmptyRecycleBin()
{
//TODO: Why don't we have a base class to share between MediaService/ContentService as some of this is exacty the same?
using (new WriteLock(Locker))
{
List<int> ids;
List<string> files;
bool success;
var nodeObjectType = new Guid(Constants.ObjectTypes.Media);
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
{
var query = Query<IMedia>.Builder.Where(x => x.Trashed == true);
var contents = repository.GetByQuery(query).OrderByDescending(x => x.Level);
using (var repository = _repositoryFactory.CreateRecycleBinRepository(_uowProvider.GetUnitOfWork()))
{
ids = repository.GetIdsOfItemsInRecycleBin(nodeObjectType);
files = repository.GetFilesInRecycleBin(nodeObjectType);
foreach (var content in contents)
{
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMedia>(content), this))
continue;
if (EmptyingRecycleBin.IsRaisedEventCancelled(new RecycleBinEventArgs(nodeObjectType, ids, files), this))
return;
repository.Delete(content);
success = repository.EmptyRecycleBin(nodeObjectType);
if (success)
repository.DeleteFiles(files);
}
Deleted.RaiseEvent(new DeleteEventArgs<IMedia>(content, false), this);
}
uow.Commit();
}
Audit.Add(AuditTypes.Delete, "Empty Recycle Bin performed by user", 0, -20);
EmptiedRecycleBin.RaiseEvent(new RecycleBinEventArgs(nodeObjectType, ids, files, success), this);
}
Audit.Add(AuditTypes.Delete, "Empty Media Recycle Bin performed by user", 0, -21);
}
/// <summary>
@@ -875,15 +878,16 @@ namespace Umbraco.Core.Services
}
}
var xmlItems = new List<ContentXmlDto>();
foreach (var c in list)
{
//generate the xml
var xml = c.ToXml();
//create the dto to insert
var poco = new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) };
//insert it into the database
uow.Database.Insert(poco);
xmlItems.Add(new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) });
}
//bulk insert it into the database
uow.Database.BulkInsertRecords(xmlItems);
}
Audit.Add(AuditTypes.Publish, "RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
}
@@ -1009,6 +1013,16 @@ namespace Umbraco.Core.Services
/// Occurs after Move
/// </summary>
public static event TypedEventHandler<IMediaService, MoveEventArgs<IMedia>> Moved;
/// <summary>
/// Occurs before the Recycle Bin is emptied
/// </summary>
public static event TypedEventHandler<IMediaService, RecycleBinEventArgs> EmptyingRecycleBin;
/// <summary>
/// Occurs after the Recycle Bin has been Emptied
/// </summary>
public static event TypedEventHandler<IMediaService, RecycleBinEventArgs> EmptiedRecycleBin;
#endregion
}
}
+2 -2
View File
@@ -43,13 +43,13 @@ namespace Umbraco.Core.Services
public IProfile GetProfileById(int id)
{
var user = GetUserById(id);
return new Profile(user.Id, user.Username);
return new Profile(user.Id, user.Name);
}
public IProfile GetProfileByUserName(string username)
{
var user = GetUserByUserName(username);
return new Profile(user.Id, user.Username);
return new Profile(user.Id, user.Name);
}
public IUser GetUserByUserName(string username)
+21
View File
@@ -28,6 +28,27 @@ namespace Umbraco.Core
[UmbracoWillObsolete("Do not use this constants. See IShortStringHelper.CleanStringForSafeAliasJavaScriptCode.")]
public const string UmbracoInvalidFirstCharacters = "01234567890";
internal static string ReplaceNonAlphanumericChars(this string input, char replacement)
{
//any character that is not alphanumeric, convert to a hyphen
var mName = input;
foreach (var c in mName.ToCharArray().Where(c => !char.IsLetterOrDigit(c)))
{
mName = mName.Replace(c, replacement);
}
return mName;
}
public static string ExceptChars(this string str, HashSet<char> toExclude)
{
var sb = new StringBuilder(str.Length);
foreach (var c in str.Where(c => toExclude.Contains(c) == false))
{
sb.Append(c);
}
return sb.ToString();
}
/// <summary>
/// Encrypt the string using the MachineKey in medium trust
/// </summary>
+367 -342
View File
@@ -19,54 +19,56 @@ using Umbraco.Core.IO;
namespace Umbraco.Core
{
/// <summary>
/// A utility class to find all classes of a certain type by reflection in the current bin folder
/// of the web application.
/// </summary>
public static class TypeFinder
{
private static readonly ConcurrentBag<Assembly> LocalFilteredAssemblyCache = new ConcurrentBag<Assembly>();
private static readonly ReaderWriterLockSlim LocalFilteredAssemblyCacheLocker = new ReaderWriterLockSlim();
private static ReadOnlyCollection<Assembly> _allAssemblies = null;
private static ReadOnlyCollection<Assembly> _binFolderAssemblies = null;
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
/// <summary>
/// A utility class to find all classes of a certain type by reflection in the current bin folder
/// of the web application.
/// </summary>
public static class TypeFinder
{
private static readonly HashSet<Assembly> LocalFilteredAssemblyCache = new HashSet<Assembly>();
private static readonly ReaderWriterLockSlim LocalFilteredAssemblyCacheLocker = new ReaderWriterLockSlim();
private static HashSet<Assembly> _allAssemblies = null;
private static HashSet<Assembly> _binFolderAssemblies = null;
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
/// <summary>
/// lazily load a reference to all assemblies and only local assemblies.
/// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
/// </summary>
/// <remarks>
/// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
/// loaded in the CLR, not all assemblies.
/// See these threads:
/// http://issues.umbraco.org/issue/U5-198
/// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app
/// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl
/// </remarks>
internal static IEnumerable<Assembly> GetAllAssemblies()
{
if (_allAssemblies == null)
{
using (new WriteLock(Locker))
{
List<Assembly> assemblies = null;
try
{
var isHosted = HttpContext.Current != null;
/// <summary>
/// lazily load a reference to all assemblies and only local assemblies.
/// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
/// </summary>
/// <remarks>
/// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
/// loaded in the CLR, not all assemblies.
/// See these threads:
/// http://issues.umbraco.org/issue/U5-198
/// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app
/// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl
/// </remarks>
internal static HashSet<Assembly> GetAllAssemblies()
{
using (var lck = new UpgradeableReadLock(Locker))
{
if (_allAssemblies == null)
{
try
{
if (isHosted)
{
assemblies = new List<Assembly>(BuildManager.GetReferencedAssemblies().Cast<Assembly>());
}
}
catch (InvalidOperationException e)
{
if (!(e.InnerException is SecurityException))
throw;
}
lck.UpgradeToWriteLock();
HashSet<Assembly> assemblies = null;
try
{
var isHosted = HttpContext.Current != null;
try
{
if (isHosted)
{
assemblies = new HashSet<Assembly>(BuildManager.GetReferencedAssemblies().Cast<Assembly>());
}
}
catch (InvalidOperationException e)
{
if (!(e.InnerException is SecurityException))
throw;
}
if (assemblies == null)
@@ -77,7 +79,7 @@ namespace Umbraco.Core
var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
//var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
//var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
assemblies = new List<Assembly>();
assemblies = new HashSet<Assembly>();
foreach (var a in binAssemblyFiles)
{
try
@@ -99,151 +101,161 @@ namespace Umbraco.Core
}
}
}
//if for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies.
if (!assemblies.Any())
{
assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().ToList());
}
if (!assemblies.Any())
{
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
assemblies.Add(a);
}
}
//here we are trying to get the App_Code assembly
var fileExtensions = new[] {".cs", ".vb"}; //only vb and cs files are supported
var appCodeFolder = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code")));
//check if the folder exists and if there are any files in it with the supported file extensions
if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any())))
{
var appCodeAssembly = Assembly.Load("App_Code");
if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already
assemblies.Add(appCodeAssembly);
}
//here we are trying to get the App_Code assembly
var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported
var appCodeFolder = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code")));
//check if the folder exists and if there are any files in it with the supported file extensions
if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any())))
{
var appCodeAssembly = Assembly.Load("App_Code");
if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already
assemblies.Add(appCodeAssembly);
}
//now set the _allAssemblies
_allAssemblies = new ReadOnlyCollection<Assembly>(assemblies);
//now set the _allAssemblies
_allAssemblies = new HashSet<Assembly>(assemblies);
}
catch (InvalidOperationException e)
{
if (!(e.InnerException is SecurityException))
throw;
}
catch (InvalidOperationException e)
{
if (!(e.InnerException is SecurityException))
throw;
_binFolderAssemblies = _allAssemblies;
}
}
}
_binFolderAssemblies = _allAssemblies;
}
}
return _allAssemblies;
}
/// <summary>
/// Returns only assemblies found in the bin folder that have been loaded into the app domain.
/// </summary>
/// <returns></returns>
/// <remarks>
/// This will be used if we implement App_Plugins from Umbraco v5 but currently it is not used.
/// </remarks>
internal static IEnumerable<Assembly> GetBinAssemblies()
{
return _allAssemblies;
}
}
if (_binFolderAssemblies == null)
{
using (new WriteLock(Locker))
{
var assemblies = GetAssembliesWithKnownExclusions().ToArray();
var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
var domainAssemblyNames = binAssemblyFiles.Select(AssemblyName.GetAssemblyName);
var safeDomainAssemblies = new List<Assembly>();
var binFolderAssemblies = new List<Assembly>();
/// <summary>
/// Returns only assemblies found in the bin folder that have been loaded into the app domain.
/// </summary>
/// <returns></returns>
/// <remarks>
/// This will be used if we implement App_Plugins from Umbraco v5 but currently it is not used.
/// </remarks>
internal static HashSet<Assembly> GetBinAssemblies()
{
foreach (var a in assemblies)
{
try
{
//do a test to see if its queryable in med trust
var assemblyFile = a.GetAssemblyFile();
safeDomainAssemblies.Add(a);
}
catch (SecurityException)
{
//we will just ignore this because this will fail
//in medium trust for system assemblies, we get an exception but we just want to continue until we get to
//an assembly that is ok.
}
}
if (_binFolderAssemblies == null)
{
using (new WriteLock(Locker))
{
var assemblies = GetAssembliesWithKnownExclusions().ToArray();
var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
var domainAssemblyNames = binAssemblyFiles.Select(AssemblyName.GetAssemblyName);
var safeDomainAssemblies = new HashSet<Assembly>();
var binFolderAssemblies = new HashSet<Assembly>();
foreach (var assemblyName in domainAssemblyNames)
{
try
{
var foundAssembly =
safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile());
if (foundAssembly != null)
{
binFolderAssemblies.Add(foundAssembly);
}
}
catch (SecurityException)
{
//we will just ignore this because if we are trying to do a call to:
// AssemblyName.ReferenceMatchesDefinition(a.GetName(), assemblyName)))
//in medium trust for system assemblies, we get an exception but we just want to continue until we get to
//an assembly that is ok.
}
}
foreach (var a in assemblies)
{
try
{
//do a test to see if its queryable in med trust
var assemblyFile = a.GetAssemblyFile();
safeDomainAssemblies.Add(a);
}
catch (SecurityException)
{
//we will just ignore this because this will fail
//in medium trust for system assemblies, we get an exception but we just want to continue until we get to
//an assembly that is ok.
}
}
_binFolderAssemblies = new ReadOnlyCollection<Assembly>(binFolderAssemblies);
}
}
return _binFolderAssemblies;
}
foreach (var assemblyName in domainAssemblyNames)
{
try
{
var foundAssembly =
safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile());
if (foundAssembly != null)
{
binFolderAssemblies.Add(foundAssembly);
}
}
catch (SecurityException)
{
//we will just ignore this because if we are trying to do a call to:
// AssemblyName.ReferenceMatchesDefinition(a.GetName(), assemblyName)))
//in medium trust for system assemblies, we get an exception but we just want to continue until we get to
//an assembly that is ok.
}
}
/// <summary>
/// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
/// and exluding the ones passed in and excluding the exclusion list filter, the results of this are
/// cached for perforance reasons.
/// </summary>
/// <param name="excludeFromResults"></param>
/// <returns></returns>
internal static IEnumerable<Assembly> GetAssembliesWithKnownExclusions(
IEnumerable<Assembly> excludeFromResults = null)
{
if (LocalFilteredAssemblyCache.Any()) return LocalFilteredAssemblyCache;
using (new WriteLock(LocalFilteredAssemblyCacheLocker))
{
var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
assemblies.ForEach(LocalFilteredAssemblyCache.Add);
}
return LocalFilteredAssemblyCache;
}
_binFolderAssemblies = new HashSet<Assembly>(binFolderAssemblies);
}
}
return _binFolderAssemblies;
}
/// <summary>
/// Return a list of found local Assemblies and exluding the ones passed in and excluding the exclusion list filter
/// </summary>
/// <param name="excludeFromResults"></param>
/// <param name="exclusionFilter"></param>
/// <returns></returns>
private static IEnumerable<Assembly> GetFilteredAssemblies(
IEnumerable<Assembly> excludeFromResults = null,
string[] exclusionFilter = null)
{
if (excludeFromResults == null)
excludeFromResults = new List<Assembly>();
if (exclusionFilter == null)
exclusionFilter = new string[] { };
/// <summary>
/// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
/// and exluding the ones passed in and excluding the exclusion list filter, the results of this are
/// cached for perforance reasons.
/// </summary>
/// <param name="excludeFromResults"></param>
/// <returns></returns>
internal static HashSet<Assembly> GetAssembliesWithKnownExclusions(
IEnumerable<Assembly> excludeFromResults = null)
{
using (var lck = new UpgradeableReadLock(LocalFilteredAssemblyCacheLocker))
{
if (LocalFilteredAssemblyCache.Any()) return LocalFilteredAssemblyCache;
return GetAllAssemblies()
.Where(x => !excludeFromResults.Contains(x)
&& !x.GlobalAssemblyCache
&& !exclusionFilter.Any(f => x.FullName.StartsWith(f)));
}
lck.UpgradeToWriteLock();
/// <summary>
/// this is our assembly filter to filter out known types that def dont contain types we'd like to find or plugins
/// </summary>
/// <remarks>
/// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match
/// </remarks>
internal static readonly string[] KnownAssemblyExclusionFilter = new[]
var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
foreach (var a in assemblies)
{
LocalFilteredAssemblyCache.Add(a);
}
return LocalFilteredAssemblyCache;
}
}
/// <summary>
/// Return a distinct list of found local Assemblies and exluding the ones passed in and excluding the exclusion list filter
/// </summary>
/// <param name="excludeFromResults"></param>
/// <param name="exclusionFilter"></param>
/// <returns></returns>
private static IEnumerable<Assembly> GetFilteredAssemblies(
IEnumerable<Assembly> excludeFromResults = null,
string[] exclusionFilter = null)
{
if (excludeFromResults == null)
excludeFromResults = new HashSet<Assembly>();
if (exclusionFilter == null)
exclusionFilter = new string[] { };
return GetAllAssemblies()
.Where(x => !excludeFromResults.Contains(x)
&& !x.GlobalAssemblyCache
&& !exclusionFilter.Any(f => x.FullName.StartsWith(f)));
}
/// <summary>
/// this is our assembly filter to filter out known types that def dont contain types we'd like to find or plugins
/// </summary>
/// <remarks>
/// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match
/// </remarks>
internal static readonly string[] KnownAssemblyExclusionFilter = new[]
{
"mscorlib,",
"System.",
@@ -287,11 +299,11 @@ namespace Umbraco.Core
/// <typeparam name="T"></typeparam>
/// <typeparam name="TAttribute"></typeparam>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfTypeWithAttribute<T, TAttribute>()
where TAttribute : Attribute
{
return FindClassesOfTypeWithAttribute<T, TAttribute>(GetAssembliesWithKnownExclusions(), true);
}
public static IEnumerable<Type> FindClassesOfTypeWithAttribute<T, TAttribute>()
where TAttribute : Attribute
{
return FindClassesOfTypeWithAttribute<T, TAttribute>(GetAssembliesWithKnownExclusions(), true);
}
/// <summary>
/// Finds any classes derived from the type T that contain the attribute TAttribute
@@ -300,11 +312,11 @@ namespace Umbraco.Core
/// <typeparam name="TAttribute"></typeparam>
/// <param name="assemblies"></param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfTypeWithAttribute<T, TAttribute>(IEnumerable<Assembly> assemblies)
where TAttribute : Attribute
{
return FindClassesOfTypeWithAttribute<T, TAttribute>(assemblies, true);
}
public static IEnumerable<Type> FindClassesOfTypeWithAttribute<T, TAttribute>(IEnumerable<Assembly> assemblies)
where TAttribute : Attribute
{
return FindClassesOfTypeWithAttribute<T, TAttribute>(assemblies, true);
}
/// <summary>
/// Finds any classes derived from the type T that contain the attribute TAttribute
@@ -314,13 +326,13 @@ namespace Umbraco.Core
/// <param name="assemblies"></param>
/// <param name="onlyConcreteClasses"></param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfTypeWithAttribute<T, TAttribute>(
IEnumerable<Assembly> assemblies,
bool onlyConcreteClasses)
where TAttribute : Attribute
{
return FindClassesOfTypeWithAttribute<TAttribute>(typeof (T), assemblies, onlyConcreteClasses);
}
public static IEnumerable<Type> FindClassesOfTypeWithAttribute<T, TAttribute>(
IEnumerable<Assembly> assemblies,
bool onlyConcreteClasses)
where TAttribute : Attribute
{
return FindClassesOfTypeWithAttribute<TAttribute>(typeof(T), assemblies, onlyConcreteClasses);
}
/// <summary>
/// Finds any classes derived from the assignTypeFrom Type that contain the attribute TAttribute
@@ -330,85 +342,85 @@ namespace Umbraco.Core
/// <param name="assemblies"></param>
/// <param name="onlyConcreteClasses"></param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfTypeWithAttribute<TAttribute>(
Type assignTypeFrom,
IEnumerable<Assembly> assemblies,
public static IEnumerable<Type> FindClassesOfTypeWithAttribute<TAttribute>(
Type assignTypeFrom,
IEnumerable<Assembly> assemblies,
bool onlyConcreteClasses)
where TAttribute : Attribute
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
return GetClasses(assignTypeFrom, assemblies, onlyConcreteClasses,
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
return GetClasses(assignTypeFrom, assemblies, onlyConcreteClasses,
//the additional filter will ensure that any found types also have the attribute applied.
t => t.GetCustomAttributes<TAttribute>(false).Any());
}
t => t.GetCustomAttributes<TAttribute>(false).Any());
}
/// <summary>
/// Searches all filtered local assemblies specified for classes of the type passed in.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfType<T>()
{
return FindClassesOfType<T>(GetAssembliesWithKnownExclusions(), true);
}
/// <summary>
/// Searches all filtered local assemblies specified for classes of the type passed in.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfType<T>()
{
return FindClassesOfType<T>(GetAssembliesWithKnownExclusions(), true);
}
/// <summary>
/// Returns all types found of in the assemblies specified of type T
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblies"></param>
/// <param name="onlyConcreteClasses"></param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfType<T>(IEnumerable<Assembly> assemblies, bool onlyConcreteClasses)
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
/// <summary>
/// Returns all types found of in the assemblies specified of type T
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblies"></param>
/// <param name="onlyConcreteClasses"></param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfType<T>(IEnumerable<Assembly> assemblies, bool onlyConcreteClasses)
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
return GetClasses(typeof(T), assemblies, onlyConcreteClasses);
}
}
/// <summary>
/// Returns all types found of in the assemblies specified of type T
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblies"></param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfType<T>(IEnumerable<Assembly> assemblies)
{
return FindClassesOfType<T>(assemblies, true);
}
/// <summary>
/// Returns all types found of in the assemblies specified of type T
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblies"></param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesOfType<T>(IEnumerable<Assembly> assemblies)
{
return FindClassesOfType<T>(assemblies, true);
}
/// <summary>
/// Finds the classes with attribute.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblies">The assemblies.</param>
/// <param name="onlyConcreteClasses">if set to <c>true</c> only concrete classes.</param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesWithAttribute<T>(IEnumerable<Assembly> assemblies, bool onlyConcreteClasses)
where T : Attribute
{
return FindClassesWithAttribute(typeof(T), assemblies, onlyConcreteClasses);
}
/// <summary>
/// Finds the classes with attribute.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblies">The assemblies.</param>
/// <param name="onlyConcreteClasses">if set to <c>true</c> only concrete classes.</param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesWithAttribute<T>(IEnumerable<Assembly> assemblies, bool onlyConcreteClasses)
where T : Attribute
{
return FindClassesWithAttribute(typeof(T), assemblies, onlyConcreteClasses);
}
/// <summary>
/// Finds any classes with the attribute.
/// </summary>
/// <param name="attributeType">The attribute type </param>
/// <param name="assemblies">The assemblies.</param>
/// <param name="onlyConcreteClasses">if set to <c>true</c> only concrete classes.</param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesWithAttribute(
Type attributeType,
IEnumerable<Assembly> assemblies,
bool onlyConcreteClasses)
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
/// <summary>
/// Finds any classes with the attribute.
/// </summary>
/// <param name="attributeType">The attribute type </param>
/// <param name="assemblies">The assemblies.</param>
/// <param name="onlyConcreteClasses">if set to <c>true</c> only concrete classes.</param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesWithAttribute(
Type attributeType,
IEnumerable<Assembly> assemblies,
bool onlyConcreteClasses)
{
if (assemblies == null) throw new ArgumentNullException("assemblies");
if (TypeHelper.IsTypeAssignableFrom<Attribute>(attributeType) == false)
throw new ArgumentException("The type specified: " + attributeType + " is not an Attribute type");
if (TypeHelper.IsTypeAssignableFrom<Attribute>(attributeType) == false)
throw new ArgumentException("The type specified: " + attributeType + " is not an Attribute type");
var foundAssignableTypes = new List<Type>();
var foundAssignableTypes = new HashSet<Type>();
var assemblyList = assemblies.ToArray();
@@ -418,71 +430,74 @@ namespace Umbraco.Core
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(attributeType, assemblyList);
foreach (var a in referencedAssemblies)
{
{
//get all types in the assembly that are sub types of the current type
var allTypes = GetTypesWithFormattedException(a).ToArray();
var types = allTypes.Where(t => TypeHelper.IsNonStaticClass(t)
&& (onlyConcreteClasses == false || t.IsAbstract == false)
//the type must have this attribute
var types = allTypes.Where(t => TypeHelper.IsNonStaticClass(t)
&& (onlyConcreteClasses == false || t.IsAbstract == false)
//the type must have this attribute
&& t.GetCustomAttributes(attributeType, false).Any());
foundAssignableTypes.AddRange(types);
}
foreach (var t in types)
{
foundAssignableTypes.Add(t);
}
}
return foundAssignableTypes;
}
return foundAssignableTypes;
}
/// <summary>
/// Finds the classes with attribute.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblies">The assemblies.</param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesWithAttribute<T>(IEnumerable<Assembly> assemblies)
where T : Attribute
{
return FindClassesWithAttribute<T>(assemblies, true);
}
/// <summary>
/// Finds the classes with attribute.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="assemblies">The assemblies.</param>
/// <returns></returns>
public static IEnumerable<Type> FindClassesWithAttribute<T>(IEnumerable<Assembly> assemblies)
where T : Attribute
{
return FindClassesWithAttribute<T>(assemblies, true);
}
/// <summary>
/// Finds the classes with attribute in filtered local assemblies
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<Type> FindClassesWithAttribute<T>()
where T : Attribute
{
return FindClassesWithAttribute<T>(GetAssembliesWithKnownExclusions());
}
/// <summary>
/// Finds the classes with attribute in filtered local assemblies
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<Type> FindClassesWithAttribute<T>()
where T : Attribute
{
return FindClassesWithAttribute<T>(GetAssembliesWithKnownExclusions());
}
#region Private methods
/// <summary>
/// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly
/// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
/// deriving from the base type.
/// </summary>
/// <param name="assignTypeFrom"></param>
/// <param name="assemblies"></param>
/// <param name="onlyConcreteClasses"></param>
/// <param name="additionalFilter">An additional filter to apply for what types will actually be included in the return value</param>
/// <returns></returns>
private static IEnumerable<Type> GetClasses(
Type assignTypeFrom,
IEnumerable<Assembly> assemblies,
#region Private methods
/// <summary>
/// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly
/// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
/// deriving from the base type.
/// </summary>
/// <param name="assignTypeFrom"></param>
/// <param name="assemblies"></param>
/// <param name="onlyConcreteClasses"></param>
/// <param name="additionalFilter">An additional filter to apply for what types will actually be included in the return value</param>
/// <returns></returns>
private static IEnumerable<Type> GetClasses(
Type assignTypeFrom,
IEnumerable<Assembly> assemblies,
bool onlyConcreteClasses,
Func<Type, bool> additionalFilter = null)
{
{
//the default filter will always return true.
if (additionalFilter == null)
{
additionalFilter = type => true;
}
var foundAssignableTypes = new List<Type>();
var foundAssignableTypes = new HashSet<Type>();
var assemblyList = assemblies.ToArray();
@@ -510,8 +525,11 @@ namespace Umbraco.Core
.ToArray();
//add the types to our list to return
foundAssignableTypes.AddRange(filteredTypes);
foreach (var t in filteredTypes)
{
foundAssignableTypes.Add(t);
}
//now we need to include types that may be inheriting from sub classes of the type being searched for
//so we will search in assemblies that reference those types too.
foreach (var subTypesInAssembly in allSubTypes.GroupBy(x => x.Assembly))
@@ -529,54 +547,61 @@ namespace Umbraco.Core
//if there's a base class amongst the types then we'll only search for that type.
//otherwise we'll have to search for all of them.
var subTypesToSearch = new List<Type>();
var subTypesToSearch = new HashSet<Type>();
if (baseClassAttempt.Success)
{
subTypesToSearch.Add(baseClassAttempt.Result);
}
else
{
subTypesToSearch.AddRange(subTypeList);
foreach (var t in subTypeList)
{
subTypesToSearch.Add(t);
}
}
foreach (var typeToSearch in subTypesToSearch)
{
//recursively find the types inheriting from this sub type in the other non-scanned assemblies.
var foundTypes = GetClasses(typeToSearch, otherAssemblies, onlyConcreteClasses, additionalFilter);
foundAssignableTypes.AddRange(foundTypes);
foreach (var f in foundTypes)
{
foundAssignableTypes.Add(f);
}
}
}
}
return foundAssignableTypes;
}
}
return foundAssignableTypes;
}
private static IEnumerable<Type> GetTypesWithFormattedException(Assembly a)
{
//if the assembly is dynamic, do not try to scan it
if (a.IsDynamic)
return Enumerable.Empty<Type>();
private static IEnumerable<Type> GetTypesWithFormattedException(Assembly a)
{
//if the assembly is dynamic, do not try to scan it
if (a.IsDynamic)
return Enumerable.Empty<Type>();
try
{
return a.GetExportedTypes();
}
catch (ReflectionTypeLoadException ex)
{
var sb = new StringBuilder();
sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:");
foreach (var loaderException in ex.LoaderExceptions.WhereNotNull())
{
sb.AppendLine("Exception: " + loaderException);
}
throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString());
}
}
try
{
return a.GetExportedTypes();
}
catch (ReflectionTypeLoadException ex)
{
var sb = new StringBuilder();
sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:");
foreach (var loaderException in ex.LoaderExceptions.WhereNotNull())
{
sb.AppendLine("Exception: " + loaderException);
}
throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString());
}
}
#endregion
#endregion
}
}
}
+10
View File
@@ -16,6 +16,16 @@ namespace Umbraco.Core
private static readonly ConcurrentDictionary<Type, FieldInfo[]> GetFieldsCache = new ConcurrentDictionary<Type, FieldInfo[]>();
private static readonly ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]> GetPropertiesCache = new ConcurrentDictionary<Tuple<Type, bool, bool, bool>, PropertyInfo[]>();
/// <summary>
/// Checks if the method is actually overriding a base method
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
public static bool IsOverride(MethodInfo m)
{
return m.GetBaseDefinition().DeclaringType != m.DeclaringType;
}
/// <summary>
/// Find all assembly references that are referencing the assignTypeFrom Type's assembly found in the assemblyList
/// </summary>
+8
View File
@@ -156,6 +156,7 @@
<Compile Include="Events\EventExtensions.cs" />
<Compile Include="Events\MigrationEventArgs.cs" />
<Compile Include="Events\PublishEventArgs.cs" />
<Compile Include="Events\RecycleBinEventArgs.cs" />
<Compile Include="Events\TypedEventHandler.cs" />
<Compile Include="Events\MoveEventArgs.cs" />
<Compile Include="Events\NewEventArgs.cs" />
@@ -164,6 +165,7 @@
<Compile Include="Events\SaveEventArgs.cs" />
<Compile Include="Events\SendToPublishEventArgs.cs" />
<Compile Include="IApplicationEventHandler.cs" />
<Compile Include="IDisposeOnRequestEnd.cs" />
<Compile Include="IO\ResizedImage.cs" />
<Compile Include="IO\UmbracoMediaFile.cs" />
<Compile Include="Media\MediaSubfolderCounter.cs" />
@@ -237,6 +239,7 @@
<Compile Include="Models\UmbracoEntity.cs" />
<Compile Include="Models\UmbracoObjectTypes.cs" />
<Compile Include="Models\UmbracoObjectTypesExtensions.cs" />
<Compile Include="NetworkHelper.cs" />
<Compile Include="ObjectResolution\ApplicationEventsResolver.cs" />
<Compile Include="ObjectResolution\ResolverCollection.cs" />
<Compile Include="Persistence\Caching\InMemoryCacheProvider.cs" />
@@ -458,6 +461,7 @@
<Compile Include="Persistence\PetaPocoConnectionExtensions.cs" />
<Compile Include="Persistence\PetaPocoExtensions.cs" />
<Compile Include="Persistence\PetaPocoSqlExtensions.cs" />
<Compile Include="Persistence\Querying\BaseExpressionHelper.cs" />
<Compile Include="Persistence\Querying\PocoToSqlExpressionHelper.cs" />
<Compile Include="Persistence\Querying\IQuery.cs" />
<Compile Include="Persistence\Querying\ModelToSqlExpressionHelper.cs" />
@@ -496,6 +500,7 @@
<Compile Include="Persistence\Repositories\MediaTypeRepository.cs" />
<Compile Include="Persistence\Repositories\PermissionRepository.cs" />
<Compile Include="Persistence\Repositories\PetaPocoRepositoryBase.cs" />
<Compile Include="Persistence\Repositories\RecycleBinRepository.cs" />
<Compile Include="Persistence\Repositories\RelationRepository.cs" />
<Compile Include="Persistence\Repositories\RelationTypeRepository.cs" />
<Compile Include="Persistence\Repositories\RepositoryBase.cs" />
@@ -665,6 +670,9 @@
<Compile Include="Publishing\PublishStatus.cs" />
<Compile Include="Publishing\PublishStatusType.cs" />
<Compile Include="RenderingEngine.cs" />
<Compile Include="Security\AuthenticationExtensions.cs" />
<Compile Include="Security\UmbracoBackOfficeIdentity.cs" />
<Compile Include="Security\UserData.cs" />
<Compile Include="Serialization\AbstractSerializationService.cs" />
<Compile Include="Serialization\Formatter.cs" />
<Compile Include="Serialization\IFormatter.cs" />
+101 -63
View File
@@ -2,6 +2,8 @@ using System;
using System.IO;
using System.Linq;
using System.Text;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
namespace Umbraco.Core
{
@@ -10,6 +12,42 @@ namespace Umbraco.Core
/// </summary>
public static class UriExtensions
{
/// <summary>
/// Checks if the current uri is a back office request
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
internal static bool IsBackOfficeRequest(this Uri url)
{
var authority = url.GetLeftPart(UriPartial.Authority);
var afterAuthority = url.GetLeftPart(UriPartial.Query)
.TrimStart(authority)
.TrimStart("/");
//check if this is in the umbraco back office
return afterAuthority.InvariantStartsWith(GlobalSettings.Path.TrimStart("/"));
}
/// <summary>
/// Checks if the current uri is an install request
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
internal static bool IsInstallerRequest(this Uri url)
{
var authority = url.GetLeftPart(UriPartial.Authority);
var afterAuthority = url.GetLeftPart(UriPartial.Query)
.TrimStart(authority)
.TrimStart("/");
//check if this is in the umbraco back office
return afterAuthority.InvariantStartsWith(IOHelper.ResolveUrl("~/install").TrimStart("/"));
}
/// <summary>
/// This is a performance tweak to check if this is a .css, .js or .ico, .jpg, .jpeg, .png, .gif file request since
/// .Net will pass these requests through to the module when in integrated mode.
@@ -19,7 +57,7 @@ namespace Umbraco.Core
/// <returns></returns>
internal static bool IsClientSideRequest(this Uri url)
{
var toIgnore = new[] { ".js", ".css", ".ico", ".png", ".jpg", ".jpeg", ".gif" };
var toIgnore = new[] { ".js", ".css", ".ico", ".png", ".jpg", ".jpeg", ".gif", ".html", ".svg" };
return toIgnore.Any(x => Path.GetExtension(url.LocalPath).InvariantEquals(x));
}
@@ -31,14 +69,14 @@ namespace Umbraco.Core
/// <returns>The rewritten uri.</returns>
/// <remarks>Everything else remains unchanged, except for the fragment which is removed.</remarks>
public static Uri Rewrite(this Uri uri, string path)
{
{
if (!path.StartsWith("/"))
throw new ArgumentException("Path must start with a slash.", "path");
return uri.IsAbsoluteUri
? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + uri.Query)
return uri.IsAbsoluteUri
? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + uri.Query)
: new Uri(path + uri.GetSafeQuery(), UriKind.Relative);
}
}
/// <summary>
/// Rewrites the path and query of a uri.
@@ -49,18 +87,18 @@ namespace Umbraco.Core
/// <returns>The rewritten uri.</returns>
/// <remarks>Everything else remains unchanged, except for the fragment which is removed.</remarks>
public static Uri Rewrite(this Uri uri, string path, string query)
{
{
if (!path.StartsWith("/"))
throw new ArgumentException("Path must start with a slash.", "path");
if (query.Length > 0 && !query.StartsWith("?"))
throw new ArgumentException("Query must start with a question mark.", "query");
if (query == "?")
query = "";
return uri.IsAbsoluteUri
? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + query)
return uri.IsAbsoluteUri
? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + query)
: new Uri(path + query, UriKind.Relative);
}
}
/// <summary>
/// Gets the absolute path of the uri, even if the uri is relative.
@@ -68,10 +106,10 @@ namespace Umbraco.Core
/// <param name="uri">The uri.</param>
/// <returns>The absolute path of the uri.</returns>
/// <remarks>Default uri.AbsolutePath does not support relative uris.</remarks>
public static string GetSafeAbsolutePath(this Uri uri)
{
if (uri.IsAbsoluteUri)
return uri.AbsolutePath;
public static string GetSafeAbsolutePath(this Uri uri)
{
if (uri.IsAbsoluteUri)
return uri.AbsolutePath;
// cannot get .AbsolutePath on relative uri (InvalidOperation)
var s = uri.OriginalString;
@@ -80,7 +118,7 @@ namespace Umbraco.Core
var pos = posq > 0 ? posq : (posf > 0 ? posf : 0);
var path = pos > 0 ? s.Substring(0, pos) : s;
return path;
}
}
/// <summary>
/// Gets the decoded, absolute path of the uri.
@@ -89,9 +127,9 @@ namespace Umbraco.Core
/// <returns>The absolute path of the uri.</returns>
/// <remarks>Only for absolute uris.</remarks>
public static string GetAbsolutePathDecoded(this Uri uri)
{
return System.Web.HttpUtility.UrlDecode(uri.AbsolutePath);
}
{
return System.Web.HttpUtility.UrlDecode(uri.AbsolutePath);
}
/// <summary>
/// Gets the decoded, absolute path of the uri, even if the uri is relative.
@@ -100,32 +138,32 @@ namespace Umbraco.Core
/// <returns>The absolute path of the uri.</returns>
/// <remarks>Default uri.AbsolutePath does not support relative uris.</remarks>
public static string GetSafeAbsolutePathDecoded(this Uri uri)
{
return System.Web.HttpUtility.UrlDecode(uri.GetSafeAbsolutePath());
}
{
return System.Web.HttpUtility.UrlDecode(uri.GetSafeAbsolutePath());
}
/// <summary>
/// Rewrites the path of the uri so it ends with a slash.
/// </summary>
/// <param name="uri">The uri.</param>
/// <returns>The rewritten uri.</returns>
/// <remarks>Everything else remains unchanged.</remarks>
/// <summary>
/// Rewrites the path of the uri so it ends with a slash.
/// </summary>
/// <param name="uri">The uri.</param>
/// <returns>The rewritten uri.</returns>
/// <remarks>Everything else remains unchanged.</remarks>
public static Uri EndPathWithSlash(this Uri uri)
{
var path = uri.GetSafeAbsolutePath();
if (uri.IsAbsoluteUri)
{
if (path != "/" && !path.EndsWith("/"))
uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path + "/" + uri.Query);
return uri;
}
else
{
if (path != "/" && !path.EndsWith("/"))
uri = new Uri(path + "/" + uri.Query, UriKind.Relative);
}
return uri;
}
{
var path = uri.GetSafeAbsolutePath();
if (uri.IsAbsoluteUri)
{
if (path != "/" && !path.EndsWith("/"))
uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path + "/" + uri.Query);
return uri;
}
else
{
if (path != "/" && !path.EndsWith("/"))
uri = new Uri(path + "/" + uri.Query, UriKind.Relative);
}
return uri;
}
/// <summary>
/// Rewrites the path of the uri so it does not end with a slash.
@@ -134,20 +172,20 @@ namespace Umbraco.Core
/// <returns>The rewritten uri.</returns>
/// <remarks>Everything else remains unchanged.</remarks>
public static Uri TrimPathEndSlash(this Uri uri)
{
var path = uri.GetSafeAbsolutePath();
if (uri.IsAbsoluteUri)
{
if (path != "/")
uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path.TrimEnd('/') + uri.Query);
}
else
{
if (path != "/")
uri = new Uri(path.TrimEnd('/') + uri.Query, UriKind.Relative);
}
return uri;
}
{
var path = uri.GetSafeAbsolutePath();
if (uri.IsAbsoluteUri)
{
if (path != "/")
uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path.TrimEnd('/') + uri.Query);
}
else
{
if (path != "/")
uri = new Uri(path.TrimEnd('/') + uri.Query, UriKind.Relative);
}
return uri;
}
/// <summary>
/// Transforms a relative uri into an absolute uri.
@@ -155,13 +193,13 @@ namespace Umbraco.Core
/// <param name="uri">The relative uri.</param>
/// <param name="baseUri">The base absolute uri.</param>
/// <returns>The absolute uri.</returns>
public static Uri MakeAbsolute(this Uri uri, Uri baseUri)
{
if (uri.IsAbsoluteUri)
throw new ArgumentException("Uri is already absolute.", "uri");
public static Uri MakeAbsolute(this Uri uri, Uri baseUri)
{
if (uri.IsAbsoluteUri)
throw new ArgumentException("Uri is already absolute.", "uri");
return new Uri(baseUri.GetLeftPart(UriPartial.Authority) + uri.GetSafeAbsolutePath() + uri.GetSafeQuery());
}
return new Uri(baseUri.GetLeftPart(UriPartial.Authority) + uri.GetSafeAbsolutePath() + uri.GetSafeQuery());
}
static string GetSafeQuery(this Uri uri)
{
@@ -176,5 +214,5 @@ namespace Umbraco.Core
return query;
}
}
}
}
+1 -1
View File
@@ -26,7 +26,7 @@
</appSettings>
<connectionStrings>
<add name="umbracoDbDSN" connectionString="Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf" providerName="System.Data.SqlServerCe.4.0"/>
<add name="umbracoDbDSN" connectionString="Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;" providerName="System.Data.SqlServerCe.4.0"/>
</connectionStrings>
<FileSystemProviders>
+1 -1
View File
@@ -53,7 +53,7 @@ namespace Umbraco.Tests.BusinessLogic
private void InitializeDatabase()
{
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf");
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf;Flush Interval=1;");
ClearDatabase();
@@ -57,7 +57,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
public override UmbracoDatabase GetConfiguredDatabase()
{
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf", "System.Data.SqlServerCe.4.0");
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0");
}
public override DatabaseProviders GetDatabaseProvider()
@@ -63,7 +63,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
public override UmbracoDatabase GetConfiguredDatabase()
{
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf", "System.Data.SqlServerCe.4.0");
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0");
}
public override DatabaseProviders GetDatabaseProvider()
@@ -100,7 +100,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
public UmbracoDatabase GetConfiguredDatabase()
{
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf", "System.Data.SqlServerCe.4.0");
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0");
}
public string GetDatabaseSpecificSqlScript()
@@ -0,0 +1,142 @@
using System.Linq;
using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Tests.TestHelpers.Entities;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class ContentExtensionsTests
{
[Test]
public void Should_Create_New_Version_When_Publishing()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Published);
Assert.IsTrue(content.ShouldCreateNewVersion());
}
[Test]
public void Should_Create_New_Version_When_Saving_After_Publishing()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Published);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Saved);
Assert.IsTrue(content.ShouldCreateNewVersion());
}
[Test]
public void Should_Create_New_Version_When_Language_Changed()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
content.Language = "en-AU";
Assert.IsTrue(content.ShouldCreateNewVersion(PublishedState.Unpublished));
}
[Test]
public void Should_Create_New_Version_When_Any_Property_Value_Changed_And_Its_Already_Published()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
content.Properties.First().Value = "hello world";
Assert.IsTrue(content.ShouldCreateNewVersion(PublishedState.Published));
}
[Test]
public void Should_Not_Create_New_Version_When_Published_Status_Not_Changed()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
Assert.IsFalse(content.ShouldCreateNewVersion(PublishedState.Unpublished));
}
[Test]
public void Should_Not_Create_New_Version_When_Not_Published_And_Property_Changed()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
content.Properties.First().Value = "hello world";
Assert.IsFalse(content.ShouldCreateNewVersion(PublishedState.Unpublished));
}
[Test]
public void Should_Clear_Published_Flag_When_Newly_Published_Version()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Published);
Assert.IsTrue(content.ShouldClearPublishedFlagForPreviousVersions());
}
[Test]
public void Should_Not_Clear_Published_Flag_When_Saving_Version()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Published);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Saved);
Assert.IsFalse(content.ShouldClearPublishedFlagForPreviousVersions());
}
[Test]
public void Should_Clear_Published_Flag_When_Unpublishing_From_Published()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Published);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Unpublished);
Assert.IsTrue(content.ShouldClearPublishedFlagForPreviousVersions());
}
[Test]
public void Should_Not_Clear_Published_Flag_When_Unpublishing_From_Saved()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Saved);
content.ResetDirtyProperties(false);
content.ChangePublishedState(PublishedState.Unpublished);
Assert.IsFalse(content.ShouldClearPublishedFlagForPreviousVersions());
}
}
}
+15
View File
@@ -13,6 +13,21 @@ namespace Umbraco.Tests.Models
[TestFixture]
public class ContentTests
{
[Test]
public void All_Dirty_Properties_Get_Reset()
{
var contentType = MockedContentTypes.CreateTextpageContentType();
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
content.ResetDirtyProperties(false);
Assert.IsFalse(content.IsDirty());
foreach (var prop in content.Properties)
{
Assert.IsFalse(prop.IsDirty());
}
}
[Test]
public void Can_Verify_Mocked_Content()
{
@@ -0,0 +1,116 @@
using System;
using System.Diagnostics;
using System.Xml;
using NUnit.Framework;
using Rhino.Mocks;
using Rhino.Mocks.Interfaces;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Tests.TestHelpers;
using umbraco.cms.businesslogic.datatype;
using umbraco.interfaces;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class DataValueSetterTests : BaseUmbracoApplicationTest
{
protected override void FreezeResolution()
{
ShortStringHelperResolver.Current = new ShortStringHelperResolver(new DefaultShortStringHelper());
base.FreezeResolution();
}
[Test]
public void LoadValueFromDatabase_Is_Not_Called_When_SetValue_Is_Used()
{
// Arrange
var baseDataType = MockRepository.GenerateStub<BaseDataType>();
var dataTypeData = MockRepository.GenerateMock<DefaultData>(baseDataType);
dataTypeData.Stub(x => x.Value).CallOriginalMethod(OriginalCallOptions.NoExpectation);
// Act
((IDataValueSetter)dataTypeData).SetValue("Hello world", DataTypeDatabaseType.Nvarchar.ToString());
var val = dataTypeData.Value;
// Assert
dataTypeData.AssertWasNotCalled(data => data.LoadValueFromDatabase());
}
[Test]
public void LoadValueFromDatabase_Is_Called_When_SetValue_Is_Not_Used()
{
// Arrange
var baseDataType = MockRepository.GenerateStub<BaseDataType>();
var dataTypeData = MockRepository.GenerateMock<DefaultData>(baseDataType);
dataTypeData
.Stub(data => data.LoadValueFromDatabase()).WhenCalled(invocation => Debug.WriteLine("asdf"));
dataTypeData.Stub(x => x.Value).CallOriginalMethod(OriginalCallOptions.NoExpectation);
// Act
var val = dataTypeData.Value;
// Assert
dataTypeData.AssertWasCalled(data => data.LoadValueFromDatabase());
}
[Test]
public void SetValue_Is_Called_When_Executing_ToXml_On_A_Property_With_DataType_That_Implements_IDataValueSetter()
{
// Arrange
var dataTypeId = Guid.NewGuid();
var dataTypeData = MockRepository.GenerateMock<IData, IDataValueSetter>();
dataTypeData
.Stub(data => data.ToXMl(Arg<XmlDocument>.Is.Anything))
.Return(null) // you have to call Return() even though we're about to override it
.WhenCalled(invocation =>
{
var xmlDoc = (XmlDocument) invocation.Arguments[0];
invocation.ReturnValue = xmlDoc.CreateElement("test");
});
var dataType = MockRepository.GenerateStub<IDataType>();
dataType.Stub(type => type.Data).Return(dataTypeData);
var dataTypeSvc = MockRepository.GenerateStub<IDataTypeService>();
dataTypeSvc.Stub(service => service.GetDataTypeById(dataTypeId)).Return(dataType);
var property = new Property(
1234,
Guid.NewGuid(),
new PropertyType(dataTypeId, DataTypeDatabaseType.Nvarchar)
{
Alias = "test"
}, "Hello world");
// Act
var xml = property.ToXml(dataTypeSvc);
// Assert
((IDataValueSetter)dataTypeData).AssertWasCalled(setter => setter.SetValue("Hello world", DataTypeDatabaseType.Nvarchar.ToString()));
}
[TestCase(DataTypeDatabaseType.Nvarchar)]
[TestCase(DataTypeDatabaseType.Date)]
[TestCase(DataTypeDatabaseType.Integer)]
[TestCase(DataTypeDatabaseType.Ntext)]
public void DefaultData_SetValue_Ensures_Empty_String_When_Null_Value_Any_Data_Type(DataTypeDatabaseType type)
{
var defaultData = new DefaultData(MockRepository.GenerateMock<BaseDataType>());
((IDataValueSetter)defaultData).SetValue(null, type.ToString());
Assert.AreEqual(string.Empty, defaultData.Value);
}
}
}
@@ -69,7 +69,7 @@ namespace Umbraco.Tests.Persistence
//Get the connectionstring settings from config
var settings = ConfigurationManager.ConnectionStrings[Core.Configuration.GlobalSettings.UmbracoConnectionName];
//by default the conn string is: Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf
//by default the conn string is: Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;
//we'll just replace the sdf file with our custom one:
//Create the Sql CE database
var engine = new SqlCeEngine(settings.ConnectionString.Replace("UmbracoPetaPocoTests", "DatabaseContextTests"));
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models.Rdbms;
@@ -73,13 +74,47 @@ namespace Umbraco.Tests.Persistence
db.OpenSharedConnection();
// Act
string sql;
string[] sql;
db.GenerateBulkInsertCommand(servers, db.Connection, out sql);
db.CloseSharedConnection();
// Assert
Assert.That(sql,
Assert.That(sql[0],
Is.EqualTo("INSERT INTO [umbracoServer] ([umbracoServer].[address], [umbracoServer].[computerName], [umbracoServer].[registeredDate], [umbracoServer].[lastNotifiedDate], [umbracoServer].[isActive]) VALUES (@0,@1,@2,@3,@4), (@5,@6,@7,@8,@9)"));
}
[Test]
public void Generate_Bulk_Import_Sql_Exceeding_Max_Params()
{
// Arrange
var db = DatabaseContext.Database;
var servers = new List<ServerRegistrationDto>();
for (var i = 0; i < 1500; i++)
{
servers.Add(new ServerRegistrationDto
{
Address = "address" + i,
ComputerName = "computer" + i,
DateRegistered = DateTime.Now,
IsActive = true,
LastNotified = DateTime.Now
});
}
db.OpenSharedConnection();
// Act
string[] sql;
db.GenerateBulkInsertCommand(servers, db.Connection, out sql);
db.CloseSharedConnection();
// Assert
Assert.That(sql.Length, Is.EqualTo(4));
foreach (var s in sql)
{
Assert.LessOrEqual(Regex.Matches(s, "@\\d+").Count, 2000);
}
}
}
}
@@ -35,12 +35,12 @@ namespace Umbraco.Tests.Persistence
}
//Create the Sql CE database
var engine = new SqlCeEngine("Datasource=|DataDirectory|test.sdf");
var engine = new SqlCeEngine("Datasource=|DataDirectory|test.sdf;Flush Interval=1;");
engine.CreateDatabase();
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
_database = new Database("Datasource=|DataDirectory|test.sdf",
_database = new Database("Datasource=|DataDirectory|test.sdf;Flush Interval=1;",
"System.Data.SqlServerCe.4.0");
}
+4 -3
View File
@@ -160,14 +160,15 @@ namespace Umbraco.Tests
{
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
var manager = new PluginManager(false);
var filePath = Path.Combine(tempFolder, "umbraco-plugins.list");
var filePath= Path.Combine(tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName));
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>");
Assert.IsTrue(manager.DetectLegacyPluginListFile());
File.Delete(filePath);
@@ -295,7 +296,7 @@ namespace Umbraco.Tests
public void Resolves_Trees()
{
var trees = PluginManager.Current.ResolveTrees();
Assert.AreEqual(36, trees.Count());
Assert.AreEqual(40, trees.Count());
}
[Test]
@@ -61,7 +61,7 @@ namespace Umbraco.Tests.PublishedCache
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.LoginName, publishedMedia.CreatorName);
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);
@@ -306,12 +306,13 @@ namespace Umbraco.Tests.Services
public void Can_RePublish_All_Content()
{
// Arrange
var contentService = ServiceContext.ContentService;
var contentService = (ContentService)ServiceContext.ContentService;
var rootContent = contentService.GetRootContent();
foreach (var c in rootContent)
{
contentService.PublishWithChildren(c);
}
var allContent = rootContent.Concat(rootContent.SelectMany(x => x.Descendants()));
//for testing we need to clear out the contentXml table so we can see if it worked
var provider = new PetaPocoUnitOfWorkProvider();
var uow = provider.GetUnitOfWork();
@@ -319,13 +320,49 @@ namespace Umbraco.Tests.Services
{
uow.Database.TruncateTable("cmsContentXml");
}
//for this test we are also going to save a revision for a content item that is not published, this is to ensure
//that it's published version still makes it into the cmsContentXml table!
contentService.Save(allContent.Last());
// Act
var published = contentService.RePublishAll(0);
// Assert
Assert.IsTrue(published);
uow = provider.GetUnitOfWork();
using (var repo = RepositoryResolver.Current.ResolveByType<IContentRepository>(uow))
{
Assert.AreEqual(allContent.Count(), uow.Database.ExecuteScalar<int>("select count(*) from cmsContentXml"));
}
}
[Test]
public void Can_RePublish_All_Content_Of_Type()
{
// Arrange
var contentService = (ContentService)ServiceContext.ContentService;
var rootContent = contentService.GetRootContent();
foreach (var c in rootContent)
{
contentService.PublishWithChildren(c);
}
var allContent = rootContent.Concat(rootContent.SelectMany(x => x.Descendants()));
//for testing we need to clear out the contentXml table so we can see if it worked
var provider = new PetaPocoUnitOfWorkProvider();
var uow = provider.GetUnitOfWork();
using (RepositoryResolver.Current.ResolveByType<IContentRepository>(uow))
{
uow.Database.TruncateTable("cmsContentXml");
}
//for this test we are also going to save a revision for a content item that is not published, this is to ensure
//that it's published version still makes it into the cmsContentXml table!
contentService.Save(allContent.Last());
// Act
contentService.RePublishAll(new int[]{allContent.Last().ContentTypeId});
// Assert
uow = provider.GetUnitOfWork();
using (var repo = RepositoryResolver.Current.ResolveByType<IContentRepository>(uow))
{
@@ -688,15 +725,21 @@ namespace Umbraco.Tests.Services
{
// Arrange
var contentService = ServiceContext.ContentService;
var content = contentService.GetById(1048);
var temp = contentService.GetById(1048);
// Act
var copy = contentService.Copy(content, content.ParentId, false, 0);
var copy = contentService.Copy(temp, temp.ParentId, false, 0);
var content = contentService.GetById(1048);
// Assert
Assert.That(copy, Is.Not.Null);
Assert.That(copy.Id, Is.Not.EqualTo(content.Id));
Assert.AreNotSame(content, copy);
foreach (var property in copy.Properties)
{
Assert.AreNotEqual(property.Id, content.Properties[property.Alias].Id);
Assert.AreEqual(property.Value, content.Properties[property.Alias].Value);
}
//Assert.AreNotEqual(content.Name, copy.Name);
}
@@ -776,6 +819,64 @@ namespace Umbraco.Tests.Services
Assert.That(hasPublishedVersion, Is.True);
}
[Test]
public void Can_Verify_Property_Types_On_Content()
{
// Arrange
var contentTypeService = ServiceContext.ContentTypeService;
var contentType = MockedContentTypes.CreateAllTypesContentType("allDataTypes", "All DataTypes");
contentTypeService.Save(contentType);
var contentService = ServiceContext.ContentService;
var content = MockedContent.CreateAllTypesContent(contentType, "Random Content", -1);
contentService.Save(content);
var id = content.Id;
// Act
var sut = contentService.GetById(id);
// Arrange
Assert.That(sut.GetValue<bool>("isTrue"), Is.True);
Assert.That(sut.GetValue<int>("number"), Is.EqualTo(42));
Assert.That(sut.GetValue<string>("bodyText"), Is.EqualTo("Lorem Ipsum Body Text Test"));
Assert.That(sut.GetValue<string>("singleLineText"), Is.EqualTo("Single Line Text Test"));
Assert.That(sut.GetValue<string>("multilineText"), Is.EqualTo("Multiple lines \n in one box"));
Assert.That(sut.GetValue<string>("upload"), Is.EqualTo("/media/1234/koala.jpg"));
Assert.That(sut.GetValue<string>("label"), Is.EqualTo("Non-editable label"));
Assert.That(sut.GetValue<DateTime>("dateTime"), Is.EqualTo(content.GetValue<DateTime>("dateTime")));
Assert.That(sut.GetValue<string>("colorPicker"), Is.EqualTo("black"));
Assert.That(sut.GetValue<string>("folderBrowser"), Is.Empty);
Assert.That(sut.GetValue<string>("ddlMultiple"), Is.EqualTo("1234,1235"));
Assert.That(sut.GetValue<string>("rbList"), Is.EqualTo("random"));
Assert.That(sut.GetValue<DateTime>("date"), Is.EqualTo(content.GetValue<DateTime>("date")));
Assert.That(sut.GetValue<string>("ddl"), Is.EqualTo("1234"));
Assert.That(sut.GetValue<string>("chklist"), Is.EqualTo("randomc"));
Assert.That(sut.GetValue<int>("contentPicker"), Is.EqualTo(1090));
Assert.That(sut.GetValue<int>("mediaPicker"), Is.EqualTo(1091));
Assert.That(sut.GetValue<int>("memberPicker"), Is.EqualTo(1092));
Assert.That(sut.GetValue<string>("simpleEditor"), Is.EqualTo("This is simply edited"));
Assert.That(sut.GetValue<string>("ultimatePicker"), Is.EqualTo("1234,1235"));
Assert.That(sut.GetValue<string>("relatedLinks"), Is.EqualTo("<links><link title=\"google\" link=\"http://google.com\" type=\"external\" newwindow=\"0\" /></links>"));
Assert.That(sut.GetValue<string>("tags"), Is.EqualTo("this,is,tags"));
Assert.That(sut.GetValue<string>("macroContainer"), Is.Empty);
Assert.That(sut.GetValue<string>("imgCropper"), Is.Empty);
}
[Test]
public void Can_Delete_Previous_Versions_Not_Latest()
{
// Arrange
var contentService = ServiceContext.ContentService;
var content = contentService.GetById(1049);
var version = content.Version;
// Act
contentService.DeleteVersion(1049, version, true, 0);
var sut = contentService.GetById(1049);
// Assert
Assert.That(sut.Version, Is.EqualTo(version));
}
private IEnumerable<IContent> CreateContentHierarchy()
{
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
@@ -263,6 +263,41 @@ namespace Umbraco.Tests.Services
Assert.That(homepage.CompositionPropertyTypes.Count(), Is.EqualTo(4));
}
[Test]
public void Can_Copy_ContentType_By_Performing_Clone()
{
// Arrange
var service = ServiceContext.ContentTypeService;
var metaContentType = MockedContentTypes.CreateMetaContentType();
service.Save(metaContentType);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", metaContentType);
service.Save(simpleContentType);
var categoryId = simpleContentType.Id;
// Act
var sut = simpleContentType.Clone("newcategory");
service.Save(sut);
// Assert
Assert.That(sut.HasIdentity, Is.True);
var contentType = service.GetContentType(sut.Id);
var category = service.GetContentType(categoryId);
Assert.That(contentType.CompositionAliases().Any(x => x.Equals("meta")), Is.True);
Assert.AreEqual(contentType.ParentId, category.ParentId);
Assert.AreEqual(contentType.Level, category.Level);
Assert.AreEqual(contentType.PropertyTypes.Count(), category.PropertyTypes.Count());
Assert.AreNotEqual(contentType.Id, category.Id);
Assert.AreNotEqual(contentType.Key, category.Key);
Assert.AreNotEqual(contentType.Path, category.Path);
Assert.AreNotEqual(contentType.SortOrder, category.SortOrder);
Assert.AreNotEqual(contentType.PropertyTypes.First(x => x.Alias.Equals("title")).Id, category.PropertyTypes.First(x => x.Alias.Equals("title")).Id);
Assert.AreNotEqual(contentType.PropertyGroups.First(x => x.Name.Equals("Content")).Id, category.PropertyGroups.First(x => x.Name.Equals("Content")).Id);
}
private ContentType CreateComponent()
{
var component = new ContentType(-1)
@@ -0,0 +1,41 @@
using System;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Tests.TestHelpers.Entities;
namespace Umbraco.Tests.Services
{
//[TestFixture]
//public class PackagingServiceTests : BaseServiceTest
//{
// [Test]
// public void Export_Content()
// {
// var yesNo = DataTypesResolver.Current.GetById(new Guid(Constants.PropertyEditors.TrueFalse));
// var txtField = DataTypesResolver.Current.GetById(new Guid(Constants.PropertyEditors.Textbox));
// var contentWithDataType = MockedContentTypes.CreateSimpleContentType(
// "test",
// "Test",
// new PropertyTypeCollection(
// new PropertyType[]
// {
// new PropertyType(new DataTypeDefinition(-1, txtField.Id)
// {
// Name = "Testing Textfield", DatabaseType = DataTypeDatabaseType.Ntext
// }),
// new PropertyType(new DataTypeDefinition(-1, yesNo.Id)
// {
// Name = "Testing intfield", DatabaseType = DataTypeDatabaseType.Integer
// })
// }));
// var content = MockedContent.CreateSimpleContent(contentWithDataType);
// content.Name = "Test";
// var exported = ServiceContext.PackagingService.Export(content);
// }
//}
}
@@ -0,0 +1,362 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlServerCe;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Xml.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
namespace Umbraco.Tests.Services
{
/// <summary>
/// Tests covering all methods in the ContentService class.
/// This is more of an integration test as it involves multiple layers
/// as well as configuration.
/// </summary>
[TestFixture, RequiresSTA]
[NUnit.Framework.Ignore("These should not be run by the server, only directly as they are only benchmark tests")]
public class PerformanceTests : BaseDatabaseFactoryTest
{
[SetUp]
public override void Initialize()
{
base.Initialize();
}
protected override string GetDbConnectionString()
{
return @"server=.\SQLEXPRESS;database=UmbTest;user id=sa;password=test";
}
protected override string GetDbProviderName()
{
return "System.Data.SqlClient";
}
/// <summary>
/// new schema per test
/// </summary>
protected override DatabaseBehavior DatabaseTestBehavior
{
get { return DatabaseBehavior.NewSchemaPerTest; }
}
/// <summary>
/// don't create anything, we're testing against our own server
/// </summary>
protected override void CreateSqlCeDatabase()
{
}
[TearDown]
public override void TearDown()
{
base.TearDown();
}
[Test]
public void Get_All_Published_Content()
{
var result = PrimeDbWithLotsOfContent();
var contentSvc = (ContentService) ServiceContext.ContentService;
var countOfPublished = result.Count(x => x.Published);
var contentTypeId = result.First().ContentTypeId;
using (DisposableTimer.DebugDuration<PerformanceTests>("Getting published content normally"))
{
//do this 10x!
for (var i = 0; i < 10; i++)
{
//clear the cache to make this test valid
RuntimeCacheProvider.Current.Clear();
var published = new List<IContent>();
//get all content items that are published
var rootContent = contentSvc.GetRootContent();
foreach (var content in rootContent.Where(content => content.Published))
{
published.Add(content);
published.AddRange(contentSvc.GetPublishedDescendants(content));
}
Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId));
}
}
using (DisposableTimer.DebugDuration<PerformanceTests>("Getting published content optimized"))
{
//do this 10x!
for (var i = 0; i < 10; i++)
{
//clear the cache to make this test valid
RuntimeCacheProvider.Current.Clear();
//get all content items that are published
var published = contentSvc.GetAllPublished();
Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId));
}
}
}
[Test]
public void Get_All_Published_Content_Of_Type()
{
var result = PrimeDbWithLotsOfContent();
var contentSvc = (ContentService)ServiceContext.ContentService;
var countOfPublished = result.Count(x => x.Published);
var contentTypeId = result.First().ContentTypeId;
using (DisposableTimer.DebugDuration<PerformanceTests>("Getting published content of type normally"))
{
//do this 10x!
for (var i = 0; i < 10; i++)
{
//clear the cache to make this test valid
RuntimeCacheProvider.Current.Clear();
//get all content items that are published of this type
var published = contentSvc.GetContentOfContentType(contentTypeId).Where(content => content.Published);
Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId));
}
}
using (DisposableTimer.DebugDuration<PerformanceTests>("Getting published content of type optimized"))
{
//do this 10x!
for (var i = 0; i < 10; i++)
{
//clear the cache to make this test valid
RuntimeCacheProvider.Current.Clear();
//get all content items that are published of this type
var published = contentSvc.GetPublishedContentOfContentType(contentTypeId);
Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId));
}
}
}
[Test]
public void Truncate_Insert_Vs_Update_Insert()
{
var customObjectType = Guid.NewGuid();
//chuck lots of data in the db
var nodes = PrimeDbWithLotsOfContentXmlRecords(customObjectType);
//now we need to test the difference between truncating all records and re-inserting them as we do now,
//vs updating them (which might result in checking if they exist for or listening on an exception).
using (DisposableTimer.DebugDuration<PerformanceTests>("Starting truncate + normal insert test"))
{
//do this 10x!
for (var i = 0; i < 10; i++)
{
//clear all the xml entries
DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)");
//now we insert each record for the ones we've deleted like we do in the content service.
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList();
foreach (var xml in xmlItems)
{
var result = DatabaseContext.Database.Insert(xml);
}
}
}
//now, isntead of truncating, we'll attempt to update and if it doesn't work then we insert
using (DisposableTimer.DebugDuration<PerformanceTests>("Starting update test"))
{
//do this 10x!
for (var i = 0; i < 10; i++)
{
//now we insert each record for the ones we've deleted like we do in the content service.
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList();
foreach (var xml in xmlItems)
{
var result = DatabaseContext.Database.Update(xml);
}
}
}
//now, test truncating but then do bulk insertion of records
using (DisposableTimer.DebugDuration<PerformanceTests>("Starting truncate + bulk insert test"))
{
//do this 10x!
for (var i = 0; i < 10; i++)
{
//clear all the xml entries
DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)");
//now we insert each record for the ones we've deleted like we do in the content service.
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList();
DatabaseContext.Database.BulkInsertRecords(xmlItems);
}
}
//now, test truncating but then do bulk insertion of records
using (DisposableTimer.DebugDuration<PerformanceTests>("Starting truncate + bulk insert test in one transaction"))
{
//do this 10x!
for (var i = 0; i < 10; i++)
{
//now we insert each record for the ones we've deleted like we do in the content service.
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList();
using (var tr = DatabaseContext.Database.GetTransaction())
{
//clear all the xml entries
DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)");
DatabaseContext.Database.BulkInsertRecords(xmlItems, tr);
}
}
}
}
private IEnumerable<IContent> PrimeDbWithLotsOfContent()
{
var contentType1 = MockedContentTypes.CreateSimpleContentType();
contentType1.AllowedAsRoot = true;
ServiceContext.ContentTypeService.Save(contentType1);
contentType1.AllowedContentTypes = new List<ContentTypeSort>
{
new ContentTypeSort
{
Alias = contentType1.Alias,
Id = new Lazy<int>(() => contentType1.Id),
SortOrder = 0
}
};
var result = new List<IContent>();
ServiceContext.ContentTypeService.Save(contentType1);
IContent lastParent = MockedContent.CreateSimpleContent(contentType1);
ServiceContext.ContentService.SaveAndPublish(lastParent);
result.Add(lastParent);
//create 20 deep
for (var i = 0; i < 20; i++)
{
//for each level, create 20
IContent content = null;
for (var j = 1; j <= 10; j++)
{
content = MockedContent.CreateSimpleContent(contentType1, "Name" + j, lastParent);
//only publish evens
if (j % 2 == 0)
{
ServiceContext.ContentService.SaveAndPublish(content);
}
else
{
ServiceContext.ContentService.Save(content);
}
result.Add(content);
}
//assign the last one as the next parent
lastParent = content;
}
return result;
}
private IEnumerable<NodeDto> PrimeDbWithLotsOfContentXmlRecords(Guid customObjectType)
{
var nodes = new List<NodeDto>();
for (var i = 1; i < 10000; i++)
{
nodes.Add(new NodeDto
{
Level = 1,
ParentId = -1,
NodeObjectType = customObjectType,
Text = i.ToString(CultureInfo.InvariantCulture),
UserId = 0,
CreateDate = DateTime.Now,
Trashed = false,
SortOrder = 0,
Path = ""
});
}
DatabaseContext.Database.BulkInsertRecords(nodes);
//re-get the nodes with ids
var sql = new Sql();
sql.Select("*").From<NodeDto>().Where<NodeDto>(x => x.NodeObjectType == customObjectType);
nodes = DatabaseContext.Database.Fetch<NodeDto>(sql);
//create the cmsContent data, each with a new content type id (so we can query on it later if needed)
var contentTypeId = 0;
var cmsContentItems = nodes.Select(node => new ContentDto { NodeId = node.NodeId, ContentTypeId = contentTypeId++ }).ToList();
DatabaseContext.Database.BulkInsertRecords(cmsContentItems);
//create the xml data
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = TestXmlStructure }).ToList();
DatabaseContext.Database.BulkInsertRecords(xmlItems);
return nodes;
}
private const string TestXmlStructure = @"<Homepage id='1231' parentID='-1' level='1' creatorID='0' sortOrder='0' createDate='2013-07-05T12:05:28' updateDate='2013-07-26T11:58:52' nodeName='Home (1)' urlName='home-(1)' path='-1,1231' isDoc='' nodeType='1221' creatorName='admin' writerName='admin' writerID='0' template='2629' nodeTypeAlias='Homepage'>
<umbracoNaviHide>0</umbracoNaviHide>
<title>Standard Site for Umbraco by Koiak</title>
<description><![CDATA[]]></description>
<keywords><![CDATA[]]></keywords>
<slideshow><![CDATA[1250,1251,1252]]></slideshow>
<panelContent1><![CDATA[<h2>Built by Creative Founds</h2>
<p><img src='/images/web_applications.jpg' alt='Web Applications' class='fr'/><strong>Creative Founds</strong> design and build first class software solutions that deliver big results. We provide ASP.NET web and mobile applications, Umbraco development service &amp; technical consultancy.</p>
<p><a href='http://www.creativefounds.co.uk' target='_blank'>www.creativefounds.co.uk</a></p>]]></panelContent1>
<panelContent2><![CDATA[<h2>Umbraco Development</h2>
<p><img src='/images/umbraco_square.jpg' alt='Umbraco' class='fr'/>Umbraco the the leading ASP.NET open source CMS, under pinning over 150,000 websites. Our Certified Developers are experts in developing high performance and feature rich websites.</p>]]></panelContent2>
<panelContent3><![CDATA[<h2>Contact Us</h2>
<p><a href='http://www.twitter.com/chriskoiak' target='_blank'><img src='/images/twitter_square.png' alt='Contact Us on Twitter' class='fr'/></a>We'd love to hear how this package has helped you and how it can be improved. Get in touch on the <a href='http://our.umbraco.org/projects/starter-kits/standard-website-mvc' target='_blank'>project website</a> or via <a href='http://www.twitter.com/chriskoiak' target='_blank'>twitter</a></p>]]></panelContent3>
<primaryNavigation><![CDATA[1231,1232,1236,1238,1239]]></primaryNavigation>
<address>Standard Website MVC, Company Address, Glasgow, Postcode</address>
<copyright>Copyright &amp;copy; 2012 Your Company</copyright>
<affiliationLink1>http://www.umbraco.org</affiliationLink1>
<affiliationImage1>/media/1477/umbraco_logo.png</affiliationImage1>
<affiliationLink2></affiliationLink2>
<affiliationImage2></affiliationImage2>
<affiliationLink3></affiliationLink3>
<affiliationImage3></affiliationImage3>
<headerNavigation><![CDATA[1242,1243]]></headerNavigation>
<myList><![CDATA[]]></myList>
<myDate>2013-07-01T00:00:00</myDate>
</Homepage>";
private const string UpdatedXmlStructure = @"<Standard id='1238' parentID='1231' level='2' creatorID='0' sortOrder='2' createDate='2013-07-05T12:05:29' updateDate='2013-07-05T12:05:34' nodeName='Clients' urlName='clients' path='-1,1231,1238' isDoc='' nodeType='1217' creatorName='admin' writerName='admin' writerID='0' template='1213' nodeTypeAlias='Standard'>
<umbracoNaviHide>0</umbracoNaviHide>
<title></title>
<description><![CDATA[]]></description>
<keywords><![CDATA[]]></keywords>
<bodyText><![CDATA[<h2>Clients</h2>
<p><strong>This is a standard content page.</strong></p>
<p><span>Vestibulum malesuada aliquet ante, vitae ullamcorper felis faucibus vel. Vestibulum condimentum faucibus tellus porta ultrices. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. </span></p>
<p><span>Cras at auctor orci. Praesent facilisis erat nec odio consequat at posuere ligula pretium. Nulla eget felis id nisl volutpat pellentesque. Ut id augue id ligula placerat rutrum a nec purus. Maecenas sed lectus ac mi pellentesque luctus quis sit amet turpis. Vestibulum adipiscing convallis vestibulum. </span></p>
<p><span>Duis condimentum lectus at orci placerat vitae imperdiet lorem cursus. Duis hendrerit porta lorem, non suscipit quam consectetur vitae. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean elit augue, tincidunt nec tincidunt id, elementum vel est.</span></p>]]></bodyText>
<contentPanels><![CDATA[]]></contentPanels>
</Standard>";
}
}
@@ -46,37 +46,47 @@ namespace Umbraco.Tests.TestHelpers
//Used to flag if its the first test in the current fixture
private bool _isFirstTestInFixture = false;
private ApplicationContext _appContext;
[SetUp]
public override void Initialize()
{
InitializeFirstRunFlags();
base.Initialize();
var path = TestHelper.CurrentAssemblyDirectory;
AppDomain.CurrentDomain.SetData("DataDirectory", path);
ApplicationContext.Current = new ApplicationContext(
var dbFactory = new DefaultDatabaseFactory(
GetDbConnectionString(),
GetDbProviderName());
_appContext = new ApplicationContext(
//assign the db context
new DatabaseContext(new DefaultDatabaseFactory()),
new DatabaseContext(dbFactory),
//assign the service context
new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy()),
new ServiceContext(new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy()),
//disable cache
false)
{
IsReady = true
};
DatabaseContext.Initialize();
base.Initialize();
CreateDatabase();
DatabaseContext.Initialize(dbFactory.ProviderName, dbFactory.ConnectionString);
CreateSqlCeDatabase();
InitializeDatabase();
//ensure the configuration matches the current version for tests
SettingsForTests.ConfigurationStatus = UmbracoVersion.Current.ToString(3);
}
protected override void SetupApplicationContext()
{
ApplicationContext.Current = _appContext;
}
/// <summary>
/// The database behavior to use for the test/fixture
/// </summary>
@@ -85,10 +95,23 @@ namespace Umbraco.Tests.TestHelpers
get { return DatabaseBehavior.NewSchemaPerTest; }
}
protected virtual string GetDbProviderName()
{
return "System.Data.SqlServerCe.4.0";
}
/// <summary>
/// Get the db conn string
/// </summary>
protected virtual string GetDbConnectionString()
{
return @"Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;";
}
/// <summary>
/// Creates the SqlCe database if required
/// </summary>
protected virtual void CreateDatabase()
protected virtual void CreateSqlCeDatabase()
{
if (DatabaseTestBehavior == DatabaseBehavior.NoDatabasePerFixture)
return;
@@ -97,7 +120,9 @@ namespace Umbraco.Tests.TestHelpers
//Get the connectionstring settings from config
var settings = ConfigurationManager.ConnectionStrings[Core.Configuration.GlobalSettings.UmbracoConnectionName];
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf");
ConfigurationManager.AppSettings.Set(
Core.Configuration.GlobalSettings.UmbracoConnectionName,
GetDbConnectionString());
string dbFilePath = string.Concat(path, "\\UmbracoPetaPocoTests.sdf");
@@ -25,6 +25,8 @@ namespace Umbraco.Tests.TestHelpers
SetupPluginManager();
SetupApplicationContext();
FreezeResolution();
}
@@ -40,7 +42,7 @@ namespace Umbraco.Tests.TestHelpers
ApplicationContext.Current = null;
ResetPluginManager();
}
/// <summary>
/// By default this returns false which means the plugin manager will not be reset so it doesn't need to re-scan
/// all of the assemblies. Inheritors can override this if plugin manager resetting is required, generally needs
@@ -79,6 +79,38 @@ namespace Umbraco.Tests.TestHelpers.Entities
return content;
}
public static Content CreateAllTypesContent(IContentType contentType, string name, int parentId)
{
var content = new Content("Random Content Name", parentId, contentType) { Language = "en-US", Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0 };
content.SetValue("isTrue", true);
content.SetValue("number", 42);
content.SetValue("bodyText", "Lorem Ipsum Body Text Test");
content.SetValue("singleLineText", "Single Line Text Test");
content.SetValue("multilineText", "Multiple lines \n in one box");
content.SetValue("upload", "/media/1234/koala.jpg");
content.SetValue("label", "Non-editable label");
content.SetValue("dateTime", DateTime.Now.AddDays(-20));
content.SetValue("colorPicker", "black");
content.SetValue("folderBrowser", "");
content.SetValue("ddlMultiple", "1234,1235");
content.SetValue("rbList", "random");
content.SetValue("date", DateTime.Now.AddDays(-10));
content.SetValue("ddl", "1234");
content.SetValue("chklist", "randomc");
content.SetValue("contentPicker", 1090);
content.SetValue("mediaPicker", 1091);
content.SetValue("memberPicker", 1092);
content.SetValue("simpleEditor", "This is simply edited");
content.SetValue("ultimatePicker", "1234,1235");
content.SetValue("relatedLinks", "<links><link title=\"google\" link=\"http://google.com\" type=\"external\" newwindow=\"0\" /></links>");
content.SetValue("tags", "this,is,tags");
content.SetValue("macroContainer", "");
content.SetValue("imgCropper", "");
return content;
}
public static IEnumerable<Content> CreateTextpageContent(IContentType contentType, int parentId, int amount)
{
var list = new List<Content>();
@@ -166,6 +166,51 @@ namespace Umbraco.Tests.TestHelpers.Entities
return contentType;
}
public static ContentType CreateAllTypesContentType(string alias, string name)
{
var contentType = new ContentType(-1)
{
Alias = alias,
Name = name,
Description = "ContentType containing all standard DataTypes",
Icon = ".sprTreeDoc3",
Thumbnail = "doc.png",
SortOrder = 1,
CreatorId = 0,
Trashed = false
};
var contentCollection = new PropertyTypeCollection();
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.TrueFalse), DataTypeDatabaseType.Integer) { Alias = "isTrue", Name = "Is True or False", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -49 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Integer), DataTypeDatabaseType.Integer) { Alias = "number", Name = "Number", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -51 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.TinyMCEv3), DataTypeDatabaseType.Ntext) { Alias = "bodyText", Name = "Body Text", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -87 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Textbox), DataTypeDatabaseType.Nvarchar) { Alias = "singleLineText", Name = "Text String", Mandatory = false, SortOrder = 4, DataTypeDefinitionId = -88 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.TextboxMultiple), DataTypeDatabaseType.Ntext) { Alias = "multilineText", Name = "Multiple Text Strings", Mandatory = false, SortOrder = 5, DataTypeDefinitionId = -89 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.UploadField), DataTypeDatabaseType.Nvarchar) { Alias = "upload", Name = "Upload Field", Mandatory = false, SortOrder = 6, DataTypeDefinitionId = -90 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.NoEdit), DataTypeDatabaseType.Nvarchar) { Alias = "label", Name = "Label", Mandatory = false, SortOrder = 7, DataTypeDefinitionId = -92 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.DateTime), DataTypeDatabaseType.Date) { Alias = "dateTime", Name = "Date Time", Mandatory = false, SortOrder = 8, DataTypeDefinitionId = -36 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.ColorPicker), DataTypeDatabaseType.Nvarchar) { Alias = "colorPicker", Name = "Color Picker", Mandatory = false, SortOrder = 9, DataTypeDefinitionId = -37 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.FolderBrowser), DataTypeDatabaseType.Nvarchar) { Alias = "folderBrowser", Name = "Folder Browser", Mandatory = false, SortOrder = 10, DataTypeDefinitionId = -38 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.DropDownListMultiple), DataTypeDatabaseType.Nvarchar) { Alias = "ddlMultiple", Name = "Dropdown List Multiple", Mandatory = false, SortOrder = 11, DataTypeDefinitionId = -39 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.RadioButtonList), DataTypeDatabaseType.Nvarchar) { Alias = "rbList", Name = "Radio Button List", Mandatory = false, SortOrder = 12, DataTypeDefinitionId = -40 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Date), DataTypeDatabaseType.Date) { Alias = "date", Name = "Date", Mandatory = false, SortOrder = 13, DataTypeDefinitionId = -41 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.DropDownList), DataTypeDatabaseType.Integer) { Alias = "ddl", Name = "Dropdown List", Mandatory = false, SortOrder = 14, DataTypeDefinitionId = -42 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.CheckBoxList), DataTypeDatabaseType.Nvarchar) { Alias = "chklist", Name = "Checkbox List", Mandatory = false, SortOrder = 15, DataTypeDefinitionId = -43 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.ContentPicker), DataTypeDatabaseType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeDefinitionId = 1034 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.MediaPicker), DataTypeDatabaseType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeDefinitionId = 1035 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.MemberPicker), DataTypeDatabaseType.Integer) { Alias = "memberPicker", Name = "Member Picker", Mandatory = false, SortOrder = 18, DataTypeDefinitionId = 1036 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.UltraSimpleEditor), DataTypeDatabaseType.Ntext) { Alias = "simpleEditor", Name = "Ultra Simple Editor", Mandatory = false, SortOrder = 19, DataTypeDefinitionId = 1038 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.UltimatePicker), DataTypeDatabaseType.Ntext) { Alias = "ultimatePicker", Name = "Ultimate Picker", Mandatory = false, SortOrder = 20, DataTypeDefinitionId = 1039 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.RelatedLinks), DataTypeDatabaseType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeDefinitionId = 1040 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Tags), DataTypeDatabaseType.Ntext) { Alias = "tags", Name = "Tags", Mandatory = false, SortOrder = 22, DataTypeDefinitionId = 1041 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.MacroContainer), DataTypeDatabaseType.Ntext) { Alias = "macroContainer", Name = "Macro Container", Mandatory = false, SortOrder = 23, DataTypeDefinitionId = 1042 });
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.ImageCropper), DataTypeDatabaseType.Ntext) { Alias = "imgCropper", Name = "Image Cropper", Mandatory = false, SortOrder = 24, DataTypeDefinitionId = 1043 });
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
return contentType;
}
public static MediaType CreateVideoMediaType()
{
var mediaType = new MediaType(-1)
+1 -1
View File
@@ -47,7 +47,7 @@ namespace Umbraco.Tests.TestHelpers
/// </summary>
public static void InitializeDatabase()
{
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf");
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf;Flush Interval=1;");
ClearDatabase();
@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using umbraco.cms.presentation.Trees;
namespace Umbraco.Tests.Trees
{
[TestFixture]
public class BaseContentTreeTests
{
[TearDown]
public void TestTearDown()
{
BaseTree.AfterTreeRender -= EventHandler;
BaseTree.BeforeTreeRender -= EventHandler;
}
[Test]
public void Run_Optimized()
{
var tree1 = new MyOptimizedContentTree1("content");
var tree2 = new MyOptimizedContentTree2("content");
Assert.IsTrue(tree1.UseOptimizedRendering);
Assert.IsTrue(tree2.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_AfterRender()
{
var tree = new MyOptimizedContentTree1("content");
BaseTree.AfterTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_BeforeRender()
{
var tree = new MyOptimizedContentTree1("content");
BaseTree.BeforeTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Overriden_Method()
{
var tree = new MyNotOptimizedContentTree("content");
Assert.IsFalse(tree.UseOptimizedRendering);
}
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
{
}
//optimized because we are not overriding OnRenderNode
public class MyOptimizedContentTree1 : BaseContentTree
{
public MyOptimizedContentTree1(string application)
: base(application)
{
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
}
public class MyOptimizedContentTree2 : BaseContentTree
{
public MyOptimizedContentTree2(string application)
: base(application)
{
}
protected override bool LoadMinimalDocument
{
get { return true; }
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
//even if we override it will still be optimized because of the LoadMinimalDocument flag
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
{
base.OnRenderNode(ref xNode, doc);
}
}
public class MyNotOptimizedContentTree : BaseContentTree
{
public MyNotOptimizedContentTree(string application)
: base(application)
{
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
protected override bool LoadMinimalDocument
{
get { return false; }
}
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
{
base.OnRenderNode(ref xNode, doc);
}
}
}
}
@@ -0,0 +1,65 @@
using NUnit.Framework;
using umbraco.cms.presentation.Trees;
namespace Umbraco.Tests.Trees
{
[TestFixture]
public class BaseMediaTreeTests
{
[TearDown]
public void TestTearDown()
{
BaseTree.AfterTreeRender -= EventHandler;
BaseTree.BeforeTreeRender -= EventHandler;
}
[Test]
public void Run_Optimized()
{
var tree = new MyOptimizedMediaTree("media");
Assert.IsTrue(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_AfterRender()
{
var tree = new MyOptimizedMediaTree("media");
BaseTree.AfterTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
[Test]
public void Not_Optimized_Events_BeforeRender()
{
var tree = new MyOptimizedMediaTree("media");
BaseTree.BeforeTreeRender += EventHandler;
Assert.IsFalse(tree.UseOptimizedRendering);
}
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
{
}
public class MyOptimizedMediaTree : BaseMediaTree
{
public MyOptimizedMediaTree(string application)
: base(application)
{
}
protected override void CreateRootNode(ref XmlTreeNode rootNode)
{
}
}
}
}
+8 -2
View File
@@ -48,9 +48,9 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -185,9 +185,13 @@
<Compile Include="Configurations\FileSystemProviderTests.cs" />
<Compile Include="CoreXml\FrameworkXmlTests.cs" />
<Compile Include="Integration\CreateContent.cs" />
<Compile Include="Models\ContentExtensionsTests.cs" />
<Compile Include="Models\DataValueSetterTests.cs" />
<Compile Include="Persistence\PetaPocoExtensionsTest.cs" />
<Compile Include="Persistence\Repositories\UserRepositoryTest.cs" />
<Compile Include="Persistence\Repositories\UserTypeRepositoryTest.cs" />
<Compile Include="Services\PackagingServiceTests.cs" />
<Compile Include="Services\PerformanceTests.cs" />
<Compile Include="Services\UserServiceTests.cs" />
<Compile Include="TestHelpers\BaseSeleniumTest.cs" />
<Compile Include="Integration\InstallPackage.cs" />
@@ -346,6 +350,8 @@
<Compile Include="TestHelpers\Entities\MockedContentTypes.cs" />
<Compile Include="TestHelpers\Entities\MockedEntity.cs" />
<Compile Include="TestHelpers\Entities\MockedMedia.cs" />
<Compile Include="Trees\BaseContentTreeTests.cs" />
<Compile Include="Trees\BaseMediaTreeTests.cs" />
<Compile Include="UmbracoExamine\ContentServiceTest.cs" />
<Compile Include="UmbracoExamine\EventsTest.cs" />
<Compile Include="TypeHelperTests.cs" />
+32
View File
@@ -10,6 +10,38 @@ namespace Umbraco.Tests
[TestFixture]
public class UriExtensionsTests
{
[TestCase("http://www.domain.com/umbraco", true)]
[TestCase("http://www.domain.com/Umbraco/", true)]
[TestCase("http://www.domain.com/umbraco/default.aspx", true)]
[TestCase("http://www.domain.com/umbraco/test/test", true)]
[TestCase("http://www.domain.com/Umbraco/test/test.aspx", true)]
[TestCase("http://www.domain.com/umbraco/test/test.js", true)]
[TestCase("http://www.domain.com/umbrac", false)]
[TestCase("http://www.domain.com/test", false)]
[TestCase("http://www.domain.com/test/umbraco", false)]
[TestCase("http://www.domain.com/test/umbraco.aspx", false)]
public void Is_Back_Office_Request(string input, bool expected)
{
var source = new Uri(input);
Assert.AreEqual(expected, source.IsBackOfficeRequest());
}
[TestCase("http://www.domain.com/install", true)]
[TestCase("http://www.domain.com/Install/", true)]
[TestCase("http://www.domain.com/install/default.aspx", true)]
[TestCase("http://www.domain.com/install/test/test", true)]
[TestCase("http://www.domain.com/Install/test/test.aspx", true)]
[TestCase("http://www.domain.com/install/test/test.js", true)]
[TestCase("http://www.domain.com/instal", false)]
[TestCase("http://www.domain.com/umbraco", false)]
[TestCase("http://www.domain.com/umbraco/umbraco", false)]
[TestCase("http://www.domain.com/test/umbraco.aspx", false)]
public void Is_Installer_Request(string input, bool expected)
{
var source = new Uri(input);
Assert.AreEqual(expected, source.IsInstallerRequest());
}
[TestCase("http://www.domain.com/foo/bar", "/", "http://www.domain.com/")]
[TestCase("http://www.domain.com/foo/bar#hop", "/", "http://www.domain.com/")]
[TestCase("http://www.domain.com/foo/bar?q=2#hop", "/", "http://www.domain.com/?q=2")]
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
@@ -5,6 +5,10 @@
<appender-ref ref="ConsoleAppender" />
</root>
<logger name="Umbraco.Core.Publishing.PublishingStrategy">
<level value="WARN" />
</logger>
<logger name="Umbraco.Core.PluginManager">
<level value="WARN" />
</logger>
@@ -13,6 +17,10 @@
<level value="WARN" />
</logger>
<logger name="Umbraco.Core.Persistence.Migrations.Initial.DatabaseSchemaCreation">
<level value="WARN" />
</logger>
<logger name="Umbraco.Core.Persistence.Migrations.Initial.BaseDataCreation">
<level value="WARN" />
</logger>
+33 -4
View File
@@ -46,6 +46,7 @@
<IISExpressUseClassicPipelineMode />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<MvcProjectUpgradeChecked>true</MvcProjectUpgradeChecked>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\</OutputPath>
@@ -108,9 +109,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ClientDependency-Mvc.1.7.0.4\lib\ClientDependency.Core.Mvc.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=1.2.11.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -916,6 +917,7 @@
<Content Include="Umbraco_Client\Tinymce3\Langs\no.js" />
<Content Include="Umbraco_Client\Tinymce3\Langs\pl.js" />
<Content Include="Umbraco_Client\Tinymce3\Langs\pt.js" />
<Content Include="Umbraco_Client\Tinymce3\Langs\ru.js" />
<Content Include="Umbraco_Client\Tinymce3\Langs\sv.js" />
<Content Include="Umbraco_Client\Tinymce3\Langs\zh.js" />
<Content Include="Umbraco_Client\Tinymce3\license.txt" />
@@ -936,6 +938,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\rule.htm" />
@@ -958,6 +961,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Css\advlink.css" />
@@ -977,6 +981,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\link.htm" />
@@ -1029,6 +1034,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Example\dialog.htm" />
@@ -1058,6 +1064,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullscreen\editor_plugin.js" />
@@ -1091,6 +1098,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Layer\editor_plugin_src.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Legacyoutput\editor_plugin.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Legacyoutput\editor_plugin_src.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Media\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Lists\editor_plugin.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Lists\editor_plugin_src.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Media\Css\media.css" />
@@ -1140,6 +1148,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\pastetext.htm" />
@@ -1170,6 +1179,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\searchreplace.htm" />
@@ -1194,6 +1204,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\props.htm" />
@@ -1223,6 +1234,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\merge_cells.htm" />
@@ -1246,6 +1258,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\template.htm" />
@@ -1260,8 +1273,12 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\en_us_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\it.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\it_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\ja.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\ja_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\ru.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\sv.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\zh.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\dialog.htm" />
@@ -1270,6 +1287,8 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Img\ajax-loader.gif" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Img\embed.gif" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Js\dialog.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\da.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\da_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\de.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\de_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\en.js" />
@@ -1278,8 +1297,12 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\en_us_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\it.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\it_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\ja.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\ja_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\ru.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\sv.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\zh.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\editor_plugin_src.js" />
@@ -1287,8 +1310,10 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\en_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\en_us_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\he_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\it_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\ja_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\editor_plugin_src.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Js\umbracolink.js" />
@@ -1297,6 +1322,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\he_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\ja_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\dialog.htm" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\editor_plugin_src.js" />
@@ -1312,6 +1338,8 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\ja_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\ru.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\sv.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\zh.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracopaste\editor_plugin_src.js" />
@@ -1353,6 +1381,7 @@
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\no_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\pl_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\pt_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\ru_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\sv_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\zh_dlg.js" />
<Content Include="Umbraco_Client\Tinymce3\Themes\Advanced\about.htm" />
@@ -2574,9 +2603,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>6130</DevelopmentServerPort>
<DevelopmentServerPort>6160</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:6130</IISUrl>
<IISUrl>http://localhost:6160</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
@@ -21,7 +21,7 @@ More information and documentation can be found on CodePlex: http://umbracoexami
<!-- default external indexer, which excludes protected and published pages-->
<add name="ExternalIndexer" type="UmbracoExamine.UmbracoContentIndexer, UmbracoExamine"/>
</providers>
</ExamineIndexProviders>
@@ -5,7 +5,7 @@
<user>0</user>
<startNode>1080</startNode>
<fullTree>False</fullTree>
<documentTypeAlias>Home</documentTypeAlias>
<documentTypeAlias>Base</documentTypeAlias>
<fields>
<categories>
</categories>
@@ -14,6 +14,6 @@
<excerpt>
</excerpt>
</fields>
<mediaObjectSupport enabled="True" folderId="-1" mediaTypeAlias="image" mediaTypeFileProperty="umbracoFile" />
<mediaObjectSupport enabled="True" folderId="-1" mediaTypeAlias="Image" mediaTypeFileProperty="umbracoFile" />
</channel>
</metablogapi>
+1 -1
View File
@@ -101,7 +101,7 @@ namespace Umbraco.Web.UI.Install.Steps {
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox DatabaseName;
/// <summary>
/// DatabaseIntegratedSecurity control.
/// </summary>
+1 -1
View File
@@ -2,7 +2,7 @@
<packages>
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
<package id="ClientDependency-Mvc" version="1.7.0.4" targetFramework="net40" />
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
@@ -406,7 +406,7 @@
<key alias="renewSession">Förnya nu för att spara ditt arbete</key>
</area>
<area alias="login">
<key alias="bottomText"><![CDATA[<p style="text-align:right;">&copy; 2001 - {0} <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
<key alias="bottomText"><![CDATA[<p style="text-align:right;">&copy; 2001 - %0% <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
<key alias="topText">Välkommen till umbraco, skriv ditt användarnamn och lösenord i textfälten nedan:</key>
</area>
<area alias="main">
@@ -757,4 +757,4 @@
<key alias="userTypes">Användartyper</key>
<key alias="writer">Skribent</key>
</area>
</language>
</language>
@@ -1,16 +1,34 @@
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="passwordChanger.ascx.cs" Inherits="umbraco.controls.passwordChanger" %>
<a href="#" onclick="if (document.getElementById('umbPasswordChanger').style.display == '' || document.getElementById('umbPasswordChanger').style.display == 'none') {document.getElementById('umbPasswordChanger').style.display = 'block'; this.style.display = 'none';}">Change password</a><br />
<script type="text/javascript">
(function ($) {
Umbraco.Sys.registerNamespace("Umbraco.Controls");
Umbraco.Controls.PasswordChanger = {
toggle: function (e) {
if (!$("#umbPasswordChanger").is(":visible")) {
ValidatorEnable(document.getElementById('<%=CompareValidator1.ClientID %>'), true);
$(e).closest(".propertyItem").replaceWith($("#umbPasswordChanger"));
$("#umbPasswordChanger").show();
$(e).hide();
}
}
};
})(jQuery);
</script>
<div id="umbPasswordChanger" style="display: none;">
<table>
<tr><th style="width: 270px;"><%=umbraco.ui.GetText("user", "newPassword")%>:</th><td style="width: 359px">
<asp:TextBox ID="umbPasswordChanger_passwordNew" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
</td></tr>
<tr><th><%=umbraco.ui.GetText("user", "confirmNewPassword")%>:</th><td style="width: 359px">
<asp:TextBox ID="umbPasswordChanger_passwordNewConfirm" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server" ErrorMessage="Passwords must match" ControlToValidate="umbPasswordChanger_passwordNew"
ControlToCompare="umbPasswordChanger_passwordNewConfirm" Operator="Equal"></asp:CompareValidator>
</td></tr>
</table>
</div>
<a href="#" onclick="Umbraco.Controls.PasswordChanger.toggle(this);">Change password</a><br />
<div class="propertyItem" id="umbPasswordChanger" style="display: none;">
<div class="propertyItemheader"><%=umbraco.ui.GetText("user", "newPassword")%></div>
<div class="propertyItemContent">
<asp:TextBox ID="umbPasswordChanger_passwordNew" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
</div>
<div class="propertyItemheader"><%=umbraco.ui.GetText("user", "confirmNewPassword")%></div>
<div class="propertyItemContent">
<asp:TextBox ID="umbPasswordChanger_passwordNewConfirm" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server" Enabled="False" ErrorMessage="Passwords must match" ControlToValidate="umbPasswordChanger_passwordNew"
ControlToCompare="umbPasswordChanger_passwordNewConfirm" Operator="Equal"></asp:CompareValidator>
</div>
</div>
@@ -1,4 +1,4 @@
<%@ Page Language="c#" CodeBehind="EditNodeTypeNew.aspx.cs" AutoEventWireup="True"
<%@ Page Language="c#" CodeBehind="EditNodeTypeNew.aspx.cs" AutoEventWireup="True" ValidateRequest="false"
Async="true" AsyncTimeOut="300" Trace="false" Inherits="Umbraco.Web.UI.Umbraco.Settings.EditNodeTypeNew" MasterPageFile="../masterpages/umbracoPage.Master" %>
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
@@ -1,5 +1,6 @@
<%@ Page MasterPageFile="../masterpages/umbracoPage.Master" Language="c#" CodeBehind="EditTemplate.aspx.cs"
ValidateRequest="false" AutoEventWireup="True" Inherits="Umbraco.Web.UI.Umbraco.Settings.EditTemplate" %>
<%@ Import Namespace="Umbraco.Core" %>
<%@ Import Namespace="Umbraco.Core.IO" %>
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %>
@@ -19,6 +20,7 @@
jQuery(document).ready(function() {
//create the editor
editor = new Umbraco.Editors.EditTemplate({
restServiceLocation: "<%= Url.GetSaveFileServicePath() %>",
umbracoPath: '<%= IOHelper.ResolveUrl(SystemDirectories.Umbraco) %>',
editorClientId: '<%= editorSource.ClientID %>',
useMasterPages: <%=umbraco.UmbracoSettings.UseAspNetMasterPages.ToString().ToLower()%>,
@@ -114,11 +114,18 @@ namespace Umbraco.Web.UI.Umbraco.Settings.Views
NameTxt.Text = OriginalFileName;
var file = IOHelper.MapPath(SystemDirectories.MvcViews.EnsureEndsWith('/') + OriginalFileName);
// validate file path
if (file.StartsWith(IOHelper.MapPath(SystemDirectories.MvcViews.EnsureEndsWith('/')))) {
using (var sr = File.OpenText(file))
{
var s = sr.ReadToEnd();
editorSource.Text = s;
}
}
} else
{
throw new ArgumentException("Couldn't open file - illegal path");
}
}
}
@@ -62,9 +62,19 @@ $.datepicker._connectDatepicker = function(target, inst) {
*/
$.datepicker._showDatepickerOverride = $.datepicker._showDatepicker;
$.datepicker._showDatepicker = function (input) {
// keep the current value
var originalval = input.value;
// Keep the first 10 chars for now yyyy-mm-dd - this removes the time part which was breaking the standardDatePicker parsing code
input.value = originalval.length>10 ? originalval.substring(0, 10) : originalval;
// Call the original method which will show the datepicker
$.datepicker._showDatepickerOverride(input);
// Put it back
input.value = originalval;
input = input.target || input;
// find from button/image trigger
@@ -101,27 +101,57 @@
save: function(templateName, templateAlias, codeVal) {
var self = this;
umbraco.presentation.webservices.codeEditorSave.SaveTemplate(
templateName, templateAlias, codeVal, self._opts.templateId, this._opts.masterPageDropDown.val(),
function(t) { self.submitSucces(t); },
function(t) { self.submitFailure(t); });
$.post(self._opts.restServiceLocation + "SaveTemplate",
JSON.stringify({
templateName: templateName,
templateAlias: templateAlias,
templateContents: codeVal,
templateId: self._opts.templateId,
masterTemplateId: this._opts.masterPageDropDown.val()
}),
function (e) {
if (e.success) {
self.submitSuccess(e);
} else {
self.submitFailure(e.message, e.header);
}
});
},
submitSucces: function(t) {
if (t != 'true') {
top.UmbSpeechBubble.ShowMessage('error', this._opts.text.templateErrorHeader, this._opts.text.templateErrorText);
submitSuccess: function (args) {
var msg = args.message;
var header = args.header;
var path = this._opts.treeSyncPath;
var pathChanged = false;
if (args.path) {
if (path != args.path) {
pathChanged = true;
}
path = args.path;
}
top.UmbSpeechBubble.ShowMessage('save', header, msg);
UmbClientMgr.mainTree().setActiveTreeType('templates');
if (pathChanged) {
UmbClientMgr.mainTree().moveNode(this._opts.templateId, path);
}
else {
top.UmbSpeechBubble.ShowMessage('save', this._opts.text.templateSavedHeader, this._opts.text.templateSavedText);
UmbClientMgr.mainTree().syncTree(path, true);
}
UmbClientMgr.mainTree().setActiveTreeType('templates');
UmbClientMgr.mainTree().syncTree(this._opts.treeSyncPath, true);
},
submitFailure: function(t) {
top.UmbSpeechBubble.ShowMessage('error', this._opts.text.templateErrorHeader, this._opts.text.templateErrorText);
submitFailure: function (err, header) {
top.UmbSpeechBubble.ShowMessage('error', header, err);
}
});
//Set defaults for jQuery ajax calls.
$.ajaxSetup({
dataType: 'json',
cache: false,
contentType: 'application/json; charset=utf-8'
});
})(jQuery);
@@ -80,7 +80,7 @@
}),
function(e) {
if (e.success) {
self.submitSuccess(e.message, e.header);
self.submitSuccess(e);
} else {
self.submitFailure(e.message, e.header);
}
@@ -97,7 +97,7 @@
}),
function(e) {
if (e.success) {
self.submitSuccess(e.message, e.header);
self.submitSuccess(e);
} else {
self.submitFailure(e.message, e.header);
}
@@ -105,8 +105,20 @@
}
},
submitSuccess: function (err, header) {
top.UmbSpeechBubble.ShowMessage('save', header, err);
submitSuccess: function (args) {
var msg = args.message;
var header = args.header;
var path = this._opts.treeSyncPath;
var pathChanged = false;
if (args.path) {
if (path != args.path) {
pathChanged = true;
}
path = args.path;
}
top.UmbSpeechBubble.ShowMessage('save', header, msg);
UmbClientMgr.mainTree().setActiveTreeType(this._opts.currentTreeType);
@@ -114,11 +126,19 @@
if (this._opts.editorType == "Template") {
//templates are different because they are ID based, whereas view files are file based without a static id
UmbClientMgr.mainTree().syncTree(this._opts.treeSyncPath, true);
if (pathChanged) {
UmbClientMgr.mainTree().moveNode(this._opts.templateId, path);
}
else {
UmbClientMgr.mainTree().syncTree(path, true);
}
}
else {
//we need to pass in the newId parameter so it knows which node to resync after retreival from the server
UmbClientMgr.mainTree().syncTree(this._opts.treeSyncPath, true, null, newFilePath.split("/")[1]);
UmbClientMgr.mainTree().syncTree(path, true, null, newFilePath.split("/")[1]);
}
//then we need to update our current tree sync path to represent the new one
@@ -64,7 +64,16 @@
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Remove"
xdt:Locator="Condition(_defaultNamespace:assemblyIdentity[@name='HtmlAgilityPack']])"/>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
<bindingRedirect oldVersion="1.4.5.0-1.4.6.0" newVersion="1.4.6.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+6
View File
@@ -269,6 +269,12 @@
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
<!-- Ensure correct version of HtmlAgilityPack -->
<dependentAssembly>
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
<bindingRedirect oldVersion="1.4.5.0-1.4.6.0" newVersion="1.4.6.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
@@ -466,7 +466,7 @@ namespace Umbraco.Web
Mandate.ParameterNotNullOrEmpty(action, "action");
Mandate.ParameterNotNullOrEmpty(controllerName, "controllerName");
var formAction = UmbracoContext.Current.OriginalRequestUrl.ToString();
var formAction = UmbracoContext.Current.OriginalRequestUrl.PathAndQuery;
return html.RenderForm(formAction, FormMethod.Post, htmlAttributes, controllerName, action, area, additionalRouteVals);
}
@@ -13,9 +13,23 @@ namespace Umbraco.Web.Install
/// </summary>
internal class UmbracoInstallAuthorizeAttribute : AuthorizeAttribute
{
private readonly ApplicationContext _applicationContext;
private readonly ApplicationContext _applicationContext;
private readonly UmbracoContext _umbracoContext;
private ApplicationContext GetApplicationContext()
{
return _applicationContext ?? ApplicationContext.Current;
}
private UmbracoContext GetUmbracoContext()
{
return _umbracoContext ?? UmbracoContext.Current;
}
/// <summary>
/// THIS SHOULD BE ONLY USED FOR UNIT TESTS
/// </summary>
/// <param name="umbracoContext"></param>
public UmbracoInstallAuthorizeAttribute(UmbracoContext umbracoContext)
{
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
@@ -23,11 +37,9 @@ namespace Umbraco.Web.Install
_applicationContext = _umbracoContext.Application;
}
public UmbracoInstallAuthorizeAttribute()
: this(UmbracoContext.Current)
{
}
public UmbracoInstallAuthorizeAttribute()
{
}
/// <summary>
/// Ensures that the user must be logged in or that the application is not configured just yet.
@@ -41,13 +53,13 @@ namespace Umbraco.Web.Install
try
{
//if its not configured then we can continue
if (!_applicationContext.IsConfigured)
if (!GetApplicationContext().IsConfigured)
{
return true;
}
var umbCtx = GetUmbracoContext();
//otherwise we need to ensure that a user is logged in
var isLoggedIn = _umbracoContext.Security.ValidateUserContextId(_umbracoContext.Security.UmbracoUserContextId);
var isLoggedIn = umbCtx.Security.ValidateUserContextId(umbCtx.Security.UmbracoUserContextId);
if (isLoggedIn)
{
return true;

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