Compare commits

..

64 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 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
64 changed files with 1529 additions and 760 deletions
+3
View File
@@ -81,3 +81,6 @@ 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.4
SET release=6.1.6
SET comment=
SET version=%release%
+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,7 +5,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("6.1.4");
private static readonly Version Version = new Version("6.1.6");
/// <summary>
/// Gets the current version of Umbraco.
+1 -1
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;Flush Interval=1;File Access Retry Timeout=10";
const string connectionString = @"Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1;";
SaveConnectionString(connectionString, providerName);
+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
{
}
}
@@ -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>
@@ -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;
}
@@ -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 });
}
@@ -340,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);
@@ -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
@@ -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())
{
@@ -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>
+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>
+1
View File
@@ -165,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" />
+1 -1
View File
@@ -26,7 +26,7 @@
</appSettings>
<connectionStrings>
<add name="umbracoDbDSN" connectionString="Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10" 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;Flush Interval=1;File Access Retry Timeout=10");
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;Flush Interval=1;File Access Retry Timeout=10", "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;Flush Interval=1;File Access Retry Timeout=10", "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;Flush Interval=1;File Access Retry Timeout=10", "System.Data.SqlServerCe.4.0");
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;", "System.Data.SqlServerCe.4.0");
}
public string GetDatabaseSpecificSqlScript()
@@ -66,6 +66,7 @@ namespace Umbraco.Tests.Models
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
@@ -98,5 +99,18 @@ namespace Umbraco.Tests.Models
((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;Flush Interval=1;File Access Retry Timeout=10
//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"));
@@ -35,12 +35,12 @@ namespace Umbraco.Tests.Persistence
}
//Create the Sql CE database
var engine = new SqlCeEngine("Datasource=|DataDirectory|test.sdf;Flush Interval=1;File Access Retry Timeout=10");
var engine = new SqlCeEngine("Datasource=|DataDirectory|test.sdf;Flush Interval=1;");
engine.CreateDatabase();
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
_database = new Database("Datasource=|DataDirectory|test.sdf;Flush Interval=1;File Access Retry Timeout=10",
_database = new Database("Datasource=|DataDirectory|test.sdf;Flush Interval=1;",
"System.Data.SqlServerCe.4.0");
}
+1 -1
View File
@@ -296,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]
@@ -861,6 +861,22 @@ namespace Umbraco.Tests.Services
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");
@@ -105,7 +105,7 @@ namespace Umbraco.Tests.TestHelpers
/// </summary>
protected virtual string GetDbConnectionString()
{
return @"Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10";
return @"Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;";
}
/// <summary>
+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;Flush Interval=1;File Access Retry Timeout=10");
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)
{
}
}
}
}
+2
View File
@@ -350,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" />
+3 -2
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>
@@ -2602,9 +2603,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>6140</DevelopmentServerPort>
<DevelopmentServerPort>6160</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:6140</IISUrl>
<IISUrl>http://localhost:6160</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
+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,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
+16 -5
View File
@@ -88,14 +88,25 @@ namespace Umbraco.Web.Routing
#region Utilities
private bool FindByUrlAliasEnabled
private static bool FindByUrlAliasEnabled
{
get
{
var hasFinder = ContentFinderResolver.Current.ContainsType<ContentFinderByUrlAlias>();
var hasHandler = ContentFinderResolver.Current.ContainsType<ContentFinderByNotFoundHandlers>()
&& NotFoundHandlerHelper.CustomHandlerTypes.Contains(typeof(global::umbraco.SearchForAlias));
return hasFinder || hasHandler;
// finder
if (ContentFinderResolver.Current.ContainsType<ContentFinderByUrlAlias>())
return true;
// handler wrapped into a finder
if (ContentFinderResolver.Current.ContainsType<ContentFinderByNotFoundHandler<global::umbraco.SearchForAlias>>())
return true;
// handler wrapped into special finder
if (ContentFinderResolver.Current.ContainsType<ContentFinderByNotFoundHandlers>()
&& NotFoundHandlerHelper.IsNotFoundHandlerEnabled<global::umbraco.SearchForAlias>())
return true;
// anything else, we can't detect
return false;
}
}
@@ -29,115 +29,77 @@ namespace Umbraco.Web.Routing
#region Copied over and adapted from presentation.requestHandler
void HandlePageNotFound(PublishedContentRequest docRequest)
private static void HandlePageNotFound(PublishedContentRequest docRequest)
{
var url = NotFoundHandlerHelper.GetLegacyUrlForNotFoundHandlers();
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Running for legacy url='{0}'.", () => url);
foreach (var handler in GetNotFoundHandlers())
foreach (var handler in NotFoundHandlerHelper.GetNotFoundHandlers())
{
IContentFinder finder = null;
var handlerName = handler.GetType().FullName;
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}'.", () => handlerName);
// replace with our own implementation
if (handler is global::umbraco.SearchForAlias)
finder = new ContentFinderByUrlAlias();
else if (handler is global::umbraco.SearchForProfile)
finder = new ContentFinderByProfile();
else if (handler is global::umbraco.SearchForTemplate)
finder = new ContentFinderByNiceUrlAndTemplate();
else if (handler is global::umbraco.handle404)
finder = new ContentFinderByLegacy404();
var finder = NotFoundHandlerHelper.SubsituteFinder(handler);
if (finder != null)
{
var finderName = finder.GetType().FullName;
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Replace handler '{0}' by new finder '{1}'.", () => handlerName, () => finderName);
if (finder.TryFindContent(docRequest))
{
// do NOT set docRequest.PublishedContent again here as
// it would clear any template that the finder might have set
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Finder '{0}' found node with id={1}.", () => finderName, () => docRequest.PublishedContent.Id);
if (docRequest.Is404)
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Finder '{0}' set status to 404.", () => finderName);
// if we found a document, break, don't look at more handler -- we're done
break;
}
// can't find a document => continue with other handlers
if (finder.TryFindContent(docRequest) == false)
continue;
// if we did not find a document, continue, look at other handlers
continue;
}
// found a document => break, don't run other handlers, we're done
// else it's a legacy handler, run
// in theory an IContentFinder can return true yet set no document
// but none of the substitued finders (see SubstituteFinder) do it.
if (handler.Execute(url) && handler.redirectID > 0)
{
var redirectId = handler.redirectID;
docRequest.PublishedContent = docRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectId);
// do NOT set docRequest.PublishedContent again here
// as it would clear any template that the finder might have set
if (!docRequest.HasPublishedContent)
{
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found node with id={1} which is not valid.", () => handlerName, () => redirectId);
break;
}
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Finder '{0}' found node with id={1}.", () => finderName, () => docRequest.PublishedContent.Id);
if (docRequest.Is404)
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Finder '{0}' set status to 404.", () => finderName);
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => redirectId);
if (docRequest.RoutingContext.UmbracoContext.HttpContext.Response.StatusCode == 404)
{
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' set status code to 404.", () => handlerName);
docRequest.Is404 = true;
}
//// check for caching
//if (handler.CacheUrl)
//{
// if (url.StartsWith("/"))
// url = "/" + url;
// var cacheKey = (currentDomain == null ? "" : currentDomain.Name) + url;
// var culture = currentDomain == null ? null : currentDomain.Language.CultureAlias;
// SetCache(cacheKey, new CacheEntry(handler.redirectID.ToString(), culture));
// HttpContext.Current.Trace.Write("NotFoundHandler",
// string.Format("Added to cache '{0}', {1}.", url, handler.redirectID));
//}
// if we found a document, break, don't look at more handler -- we're done
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => docRequest.PublishedContent.Id);
break;
}
// if we did not find a document, continue, look at other handlers
// else it's a legacy handler: run
// can't find a document => continue with other handlers
if (handler.Execute(url) == false || handler.redirectID <= 0)
continue;
// found a document ID => ensure it's a valid document
var redirectId = handler.redirectID;
docRequest.PublishedContent = docRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectId);
if (docRequest.HasPublishedContent == false)
{
// the handler said it could handle the url, and returned a content ID
// yet that content ID is invalid... should we run the other handlers?
// I don't think so, not here, let the "last chance" finder take care.
// so, break.
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found node with id={1} which is not valid.", () => handlerName, () => redirectId);
break;
}
// found a valid document => break, don't run other handlers, we're done
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => redirectId);
if (docRequest.RoutingContext.UmbracoContext.HttpContext.Response.StatusCode == 404)
{
LogHelper.Debug<ContentFinderByNotFoundHandlers>("Handler '{0}' set status code to 404.", () => handlerName);
docRequest.Is404 = true;
}
break;
}
}
IEnumerable<INotFoundHandler> GetNotFoundHandlers()
{
// instanciate new handlers
// using definition cache
var handlers = new List<INotFoundHandler>();
foreach (var type in NotFoundHandlerHelper.CustomHandlerTypes)
{
try
{
var handler = Activator.CreateInstance(type) as INotFoundHandler;
if (handler != null)
handlers.Add(handler);
}
catch (Exception e)
{
LogHelper.Error<ContentFinderByNotFoundHandlers>(string.Format("Error instanciating handler {0}, ignoring.", type.FullName), e);
}
}
return handlers;
}
#endregion
}
}
@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using umbraco.interfaces;
namespace Umbraco.Web.Routing
{
/// <summary>
/// Provides an implementation of <see cref="IContentFinder"/> that runs legacy <c>INotFoundHandler</c> in "last chance" situation.
/// </summary>
public class ContentLastChanceFinderByNotFoundHandlers : IContentFinder
{
// notes
//
// at the moment we load the legacy INotFoundHandler
// excluding those that have been replaced by proper finders,
// and run them.
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
/// </summary>
/// <param name="docRequest">The <c>PublishedContentRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
public bool TryFindContent(PublishedContentRequest docRequest)
{
HandlePageNotFound(docRequest);
return docRequest.HasPublishedContent;
}
#region Copied over and adapted from presentation.requestHandler
private static void HandlePageNotFound(PublishedContentRequest docRequest)
{
var url = NotFoundHandlerHelper.GetLegacyUrlForNotFoundHandlers();
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Running for legacy url='{0}'.", () => url);
var handler = NotFoundHandlerHelper.GetNotFoundLastChanceHandler();
var handlerName = handler.GetType().FullName;
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}'.", () => handlerName);
var finder = NotFoundHandlerHelper.SubsituteFinder(handler);
if (finder != null)
{
var finderName = finder.GetType().FullName;
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Replace handler '{0}' by new finder '{1}'.", () => handlerName, () => finderName);
// can't find a document => exit
if (finder.TryFindContent(docRequest) == false)
return;
// found a document => we're done
// in theory an IContentFinder can return true yet set no document
// but none of the substitued finders (see SubstituteFinder) do it.
// do NOT set docRequest.PublishedContent again here
// as it would clear any template that the finder might have set
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Finder '{0}' found node with id={1}.", () => finderName, () => docRequest.PublishedContent.Id);
if (docRequest.Is404)
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Finder '{0}' set status to 404.", () => finderName);
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => docRequest.PublishedContent.Id);
return;
}
// else it's a legacy handler, run
// can't find a document => exit
if (handler.Execute(url) == false || handler.redirectID <= 0)
return;
// found a document ID => ensure it's a valid document
var redirectId = handler.redirectID;
docRequest.PublishedContent = docRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectId);
if (docRequest.HasPublishedContent == false)
{
// the handler said it could handle the url, and returned a content ID
// yet that content ID is invalid... exit.
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' found node with id={1} which is not valid.", () => handlerName, () => redirectId);
return;
}
// found a valid document => return
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' found valid node with id={1}.", () => handlerName, () => redirectId);
if (docRequest.RoutingContext.UmbracoContext.HttpContext.Response.StatusCode == 404)
{
LogHelper.Debug<ContentLastChanceFinderByNotFoundHandlers>("Handler '{0}' set status code to 404.", () => handlerName);
docRequest.Is404 = true;
}
}
#endregion
}
}
+106 -20
View File
@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
using System.Reflection;
using Umbraco.Core;
using Umbraco.Core.Logging;
using umbraco.interfaces;
namespace Umbraco.Web.Routing
{
@@ -36,14 +39,14 @@ namespace Umbraco.Web.Routing
return url;
// code from requestModule.UmbracoRewrite
string tmp = httpContext.Request.Path.ToLower();
var tmp = httpContext.Request.Path.ToLower();
// note: requestModule.UmbracoRewrite also did some stripping of &umbPage
// from the querystring... that was in v3.x to fix some issues with pre-forms
// auth. Paul Sterling confirmed in jan. 2013 that we can get rid of it.
// code from requestHandler.cleanUrl
string root = Core.IO.SystemDirectories.Root.ToLower();
var root = Core.IO.SystemDirectories.Root.ToLower();
if (!string.IsNullOrEmpty(root) && tmp.StartsWith(root))
tmp = tmp.Substring(root.Length);
tmp = tmp.TrimEnd('/');
@@ -55,7 +58,7 @@ namespace Umbraco.Web.Routing
// code from UmbracoDefault.Page_PreInit
if (tmp != "" && httpContext.Request["umbPageID"] == null)
{
string tryIntParse = tmp.Replace("/", "").Replace(".aspx", string.Empty);
var tryIntParse = tmp.Replace("/", "").Replace(".aspx", string.Empty);
int result;
if (int.TryParse(tryIntParse, out result))
tmp = tmp.Replace(".aspx", string.Empty);
@@ -77,7 +80,8 @@ namespace Umbraco.Web.Routing
return tmp;
}
static IEnumerable<Type> _customHandlerTypes;
private static IEnumerable<Type> _customHandlerTypes;
private static Type _customLastChanceHandlerType;
static void InitializeNotFoundHandlers()
{
@@ -87,46 +91,128 @@ namespace Umbraco.Web.Routing
LogHelper.Debug<NotFoundHandlerHelper>("Registering custom handlers.");
var customHandlerTypes = new List<Type>();
Type customHandlerType = null;
var customHandlers = new XmlDocument();
customHandlers.Load(Core.IO.IOHelper.MapPath(Core.IO.SystemFiles.NotFoundhandlersConfig));
foreach (XmlNode n in customHandlers.DocumentElement.SelectNodes("notFound"))
{
if (customHandlerType != null)
{
LogHelper.Debug<NotFoundHandlerHelper>("Registering '{0}'.", () => customHandlerType.FullName);
customHandlerTypes.Add(customHandlerType);
}
var assemblyName = n.Attributes.GetNamedItem("assembly").Value;
var typeName = n.Attributes.GetNamedItem("type").Value;
string ns = assemblyName;
var ns = assemblyName;
var nsAttr = n.Attributes.GetNamedItem("namespace");
if (nsAttr != null && !string.IsNullOrWhiteSpace(nsAttr.Value))
if (nsAttr != null && string.IsNullOrWhiteSpace(nsAttr.Value) == false)
ns = nsAttr.Value;
LogHelper.Debug<NotFoundHandlerHelper>("Registering '{0}.{1},{2}'.", () => ns, () => typeName, () => assemblyName);
LogHelper.Debug<NotFoundHandlerHelper>("Configured: '{0}.{1},{2}'.", () => ns, () => typeName, () => assemblyName);
Type type = null;
customHandlerType = null;
try
{
var assembly = Assembly.Load(new AssemblyName(assemblyName));
type = assembly.GetType(ns + "." + typeName);
customHandlerType = assembly.GetType(ns + "." + typeName);
}
catch (Exception e)
{
LogHelper.Error<NotFoundHandlerHelper>("Error registering handler, ignoring.", e);
LogHelper.Error<NotFoundHandlerHelper>("Error: could not load handler, ignoring.", e);
}
if (type != null)
customHandlerTypes.Add(type);
}
_customHandlerTypes = customHandlerTypes;
}
public static IEnumerable<Type> CustomHandlerTypes
{
get
// what shall we do with the last one, assuming it's not null?
// if the last chance finder wants a handler, then use the last one as the last chance handler
// else assume that the last one is a normal handler since noone else wants it, and add it to the list
if (customHandlerType != null)
{
return _customHandlerTypes;
var lastChanceFinder = ContentLastChanceFinderResolver.Current.Finder; // can be null
var finderWantsHandler = lastChanceFinder != null &&
lastChanceFinder.GetType() == typeof(ContentLastChanceFinderByNotFoundHandlers);
if (finderWantsHandler)
{
LogHelper.Debug<NotFoundHandlerHelper>("Registering '{0}' as \"last chance\" handler.", () => customHandlerType.FullName);
_customLastChanceHandlerType = customHandlerType;
}
else
{
LogHelper.Debug<NotFoundHandlerHelper>("Registering '{0}'.", () => customHandlerType.FullName);
customHandlerTypes.Add(customHandlerType);
_customLastChanceHandlerType = null;
}
}
_customHandlerTypes = customHandlerTypes.ToArray();
}
public static IEnumerable<INotFoundHandler> GetNotFoundHandlers()
{
// instanciate new handlers
// using definition cache
var handlers = new List<INotFoundHandler>();
foreach (var type in _customHandlerTypes)
{
try
{
var handler = Activator.CreateInstance(type) as INotFoundHandler;
if (handler != null)
handlers.Add(handler);
}
catch (Exception e)
{
LogHelper.Error<ContentFinderByNotFoundHandlers>(string.Format("Error instanciating handler {0}, ignoring.", type.FullName), e);
}
}
return handlers;
}
public static bool IsNotFoundHandlerEnabled<T>()
{
return _customHandlerTypes.Contains(typeof (T));
}
public static INotFoundHandler GetNotFoundLastChanceHandler()
{
if (_customLastChanceHandlerType == null) return null;
try
{
var handler = Activator.CreateInstance(_customLastChanceHandlerType) as INotFoundHandler;
if (handler != null)
return handler;
}
catch (Exception e)
{
LogHelper.Error<ContentFinderByNotFoundHandlers>(string.Format("Error instanciating handler {0}, ignoring.", _customLastChanceHandlerType.FullName), e);
}
return null;
}
public static IContentFinder SubsituteFinder(INotFoundHandler handler)
{
IContentFinder finder = null;
if (handler is global::umbraco.SearchForAlias)
finder = new ContentFinderByUrlAlias();
else if (handler is global::umbraco.SearchForProfile)
finder = new ContentFinderByProfile();
else if (handler is global::umbraco.SearchForTemplate)
finder = new ContentFinderByNiceUrlAndTemplate();
else if (handler is global::umbraco.handle404)
finder = new ContentFinderByLegacy404();
return finder;
}
}
}
@@ -140,12 +140,35 @@ namespace Umbraco.Web.Routing
// unless a template has been set already by the finder,
// template should be null at that point.
var initial = IsInitialPublishedContent;
// IsInternalRedirect if IsInitial, or already IsInternalRedirect
var isInternalRedirect = IsInitialPublishedContent || IsInternalRedirectPublishedContent;
// redirecting to self
if (content.Id == PublishedContent.Id) // neither can be null
{
// no need to set PublishedContent, we're done
IsInternalRedirectPublishedContent = isInternalRedirect;
return;
}
// else
// save
var template = _template;
var renderingEngine = RenderingEngine;
// set published content - this resets the template, and sets IsInternalRedirect to false
PublishedContent = content;
IsInternalRedirectPublishedContent = (initial && !IsInitialPublishedContent);
if (IsInternalRedirectPublishedContent && UmbracoSettings.For<WebRouting>().InternalRedirectPreservesTemplate)
IsInternalRedirectPublishedContent = isInternalRedirect;
// must restore the template if it's an internal redirect & the config option is set
if (isInternalRedirect && UmbracoSettings.For<WebRouting>().InternalRedirectPreservesTemplate)
{
// restore
_template = template;
RenderingEngine = renderingEngine;
}
}
/// <summary>
@@ -179,9 +202,11 @@ namespace Umbraco.Web.Routing
}
/// <summary>
/// Gets or sets a value indicating whether the current published has been obtained from the
/// initial published content following internal redirections exclusively.
/// Gets or sets a value indicating whether the current published content has been obtained
/// from the initial published content following internal redirections exclusively.
/// </summary>
/// <remarks>Used by PublishedContentRequestEngine.FindTemplate() to figure out whether to
/// apply the internal redirect or not, when content is not the initial content.</remarks>
public bool IsInternalRedirectPublishedContent { get; private set; }
/// <summary>
+3 -3
View File
@@ -70,15 +70,15 @@ namespace Umbraco.Web.Security
var allowGroupsList = allowGroups as IList<string> ?? allowGroups.ToList();
if (allowAction && allowGroupsList.Any(allowGroup => allowGroup != string.Empty))
{
// Allow only if member's type is in list
// Allow only if member is assigned to a group in the list
var groups = Roles.GetRolesForUser(member.LoginName);
allowAction = groups.Select(s => s.ToLowerInvariant()).Intersect(groups.Select(myGroup => myGroup.ToLowerInvariant())).Any();
allowAction = allowGroupsList.Select(s => s.ToLowerInvariant()).Intersect(groups.Select(myGroup => myGroup.ToLowerInvariant())).Any();
}
// If specific members defined, check member is of one of those
if (allowAction && allowMembers.Any())
{
// Allow only if member's type is in list
// Allow only if member's Id is in the list
allowAction = allowMembers.Contains(member.Id);
}
}
+1
View File
@@ -292,6 +292,7 @@
<Compile Include="Configuration\WebRouting.cs" />
<Compile Include="Editors\MediaController.cs" />
<Compile Include="Models\ContentEditing\ContentSortOrder.cs" />
<Compile Include="Routing\ContentLastChanceFinderByNotFoundHandlers.cs" />
<Compile Include="Security\Providers\MembersMembershipProvider.cs" />
<Compile Include="Security\Providers\UsersMembershipProvider.cs" />
<Compile Include="Standalone\ServiceContextManager.cs" />
+9 -3
View File
@@ -24,7 +24,7 @@ namespace Umbraco.Web
/// <summary>
/// Class that encapsulates Umbraco information of a specific HTTP request
/// </summary>
public class UmbracoContext : DisposableObject
public class UmbracoContext : DisposableObject, IDisposeOnRequestEnd
{
private const string HttpContextItemName = "Umbraco.Web.UmbracoContext";
private static readonly object Locker = new object();
@@ -370,8 +370,14 @@ namespace Umbraco.Web
_umbracoContext = null;
//ensure not to dispose this!
Application = null;
ContentCache = null;
MediaCache = null;
//Before we set these to null but in fact these are application lifespan singletons so
//there's no reason we need to set them to null and this also caused a problem with packages
//trying to access the cache properties on RequestEnd.
//http://issues.umbraco.org/issue/U4-2734
//http://our.umbraco.org/projects/developer-tools/301-url-tracker/version-2/44327-Issues-with-URL-Tracker-in-614
//ContentCache = null;
//MediaCache = null;
}
}
}
+31 -2
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
@@ -465,10 +466,38 @@ namespace Umbraco.Web
/// <param name="http"></param>
private static void DisposeHttpContextItems(HttpContext http)
{
// do not process if client-side request
if (http.Request.Url.IsClientSideRequest())
return;
//get a list of keys to dispose
var keys = new HashSet<object>();
foreach (DictionaryEntry i in http.Items)
{
i.Value.DisposeIfDisposable();
i.Key.DisposeIfDisposable();
if (i.Value is IDisposeOnRequestEnd || i.Key is IDisposeOnRequestEnd)
{
keys.Add(i.Key);
}
}
//dispose each item and key that was found as disposable.
foreach (var k in keys)
{
try
{
http.Items[k].DisposeIfDisposable();
}
catch (Exception ex)
{
LogHelper.Error<UmbracoModule>("Could not dispose item with key " + k, ex);
}
try
{
k.DisposeIfDisposable();
}
catch (Exception ex)
{
LogHelper.Error<UmbracoModule>("Could not dispose item key " + k, ex);
}
}
}
+23 -15
View File
@@ -302,23 +302,31 @@ namespace Umbraco.Web
typeof(DefaultUrlProvider)
);
// the legacy 404 will run from within ContentFinderByNotFoundHandlers below
// so for the time being there is no last chance finder
ContentLastChanceFinderResolver.Current = new ContentLastChanceFinderResolver();
ContentLastChanceFinderResolver.Current = new ContentLastChanceFinderResolver(
// handled by ContentLastChanceFinderByNotFoundHandlers for the time being
// soon as we get rid of INotFoundHandler support, we must enable this
//new ContentFinderByLegacy404()
// implement INotFoundHandler support... remove once we get rid of it
new ContentLastChanceFinderByNotFoundHandlers());
ContentFinderResolver.Current = new ContentFinderResolver(
// add all known resolvers in the correct order, devs can then modify this list
// on application startup either by binding to events or in their own global.asax
typeof (ContentFinderByPageIdQuery),
typeof (ContentFinderByNiceUrl),
typeof (ContentFinderByIdPath),
// these will be handled by ContentFinderByNotFoundHandlers
// so they can be enabled/disabled even though resolvers are not public yet
//typeof (ContentFinderByNiceUrlAndTemplate),
//typeof (ContentFinderByProfile),
//typeof (ContentFinderByUrlAlias),
typeof (ContentFinderByNotFoundHandlers)
);
// all built-in finders in the correct order, devs can then modify this list
// on application startup via an application event handler.
typeof (ContentFinderByPageIdQuery),
typeof (ContentFinderByNiceUrl),
typeof (ContentFinderByIdPath),
// these will be handled by ContentFinderByNotFoundHandlers so they can be enabled/disabled
// via the config file... soon as we get rid of INotFoundHandler support, we must enable
// them here.
//typeof (ContentFinderByNiceUrlAndTemplate),
//typeof (ContentFinderByProfile),
//typeof (ContentFinderByUrlAlias),
// implement INotFoundHandler support... remove once we get rid of it
typeof (ContentFinderByNotFoundHandlers)
);
SiteDomainHelperResolver.Current = new SiteDomainHelperResolver(new SiteDomainHelper());
@@ -8,7 +8,9 @@ using Umbraco.Web.Macros;
using Umbraco.Web.Mvc;
using umbraco;
using umbraco.cms.businesslogic.macro;
using System.Collections.Generic;
using Umbraco.Core;
using Template = umbraco.cms.businesslogic.template.Template;
namespace Umbraco.Web.WebServices
@@ -90,15 +92,22 @@ namespace Umbraco.Web.WebServices
public JsonResult SaveTemplate(string templateName, string templateAlias, string templateContents, int templateId, int masterTemplateId)
{
Template t;
bool pathChanged = false;
try
{
t = new Template(templateId)
{
Text = templateName,
Alias = templateAlias,
MasterTemplate = masterTemplateId,
Alias = templateAlias,
Design = templateContents
};
//check if the master page has changed
if (t.MasterTemplate != masterTemplateId)
{
pathChanged = true;
t.MasterTemplate = masterTemplateId;
}
}
catch (ArgumentException ex)
{
@@ -110,7 +119,17 @@ namespace Umbraco.Web.WebServices
{
t.Save();
return Success(ui.Text("speechBubbles", "templateSavedText"), ui.Text("speechBubbles", "templateSavedHeader"));
//ensure the correct path is synced as the parent might have been changed
// http://issues.umbraco.org/issue/U4-2300
if (pathChanged)
{
//need to re-look it up
t = new Template(templateId);
}
var syncPath = "-1,init," + t.Path.Replace("-1,", "");
return Success(ui.Text("speechBubbles", "templateSavedText"), ui.Text("speechBubbles", "templateSavedHeader"),
new {path = syncPath});
}
catch (Exception ex)
{
@@ -118,20 +137,21 @@ namespace Umbraco.Web.WebServices
}
}
/// <summary>
/// Returns a successful message
/// </summary>
/// <param name="message">The message to display in the speach bubble</param>
/// <param name="header">The header to display in the speach bubble</param>
/// <returns></returns>
private JsonResult Success(string message, string header)
{
return Json(new
{
success = true,
message = message,
header = header
});
/// <summary>
/// Returns a successful message
/// </summary>
/// <param name="message">The message to display in the speach bubble</param>
/// <param name="header">The header to display in the speach bubble</param>
/// <param name="additionalVals"></param>
/// <returns></returns>
private JsonResult Success(string message, string header, object additionalVals = null)
{
var d = additionalVals == null ? new Dictionary<string, object>() : additionalVals.ToDictionary<object>();
d["success"] = true;
d["message"] = message;
d["header"] = header;
return Json(d);
}
/// <summary>
@@ -60,7 +60,11 @@ namespace umbraco.presentation.umbraco.Search
}
else
{
var operation = criteria.Field("__nodeName", txt.MultipleCharacterWildcard());
var words = txt.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(w => w.ToLower().MultipleCharacterWildcard()).ToList();
var operation = criteria.GroupedOr(new[] { "__nodeName" }, new[] { words[0] });
words.RemoveAt(0);
foreach (var word in words)
operation = operation.And().GroupedOr(new[] { "__nodeName" }, new[] { word });
// ensure the user can only find nodes they are allowed to see
if (UmbracoContext.Current.UmbracoUser.StartNodeId > 0)
@@ -2,8 +2,10 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Models;
using umbraco.BasePages;
using umbraco.BusinessLogic;
@@ -24,14 +26,7 @@ namespace umbraco.cms.presentation.Trees
public BaseContentTree(string application) : base(application) { }
private User _user;
/// <summary>
/// Determines whether the (legacy) Document object passed to the OnRenderNode-method
/// should be initialized with a full set of properties.
/// By default the Document will be initialized, so setting the boolean to True will
/// ensure that the Document object is loaded with a minimum set of properties to
/// improve performance.
/// </summary>
protected virtual bool LoadMinimalDocument { get; set; }
/// <summary>
@@ -73,61 +68,69 @@ function openContent(id) {
/// Renders the specified tree item.
/// </summary>
/// <param name="Tree">The tree.</param>
/*public override void Render(ref XmlTree Tree)
{
//get documents to render
Document[] docs = Document.GetChildrenForTree(m_id);
var args = new TreeEventArgs(Tree);
OnBeforeTreeRender(docs, args);
foreach (Document dd in docs)
{
List<IAction> allowedUserOptions = GetUserActionsForNode(dd);
if (CanUserAccessNode(dd, allowedUserOptions))
{
XmlTreeNode node = CreateNode(dd, allowedUserOptions);
OnRenderNode(ref node, dd);
OnBeforeNodeRender(ref Tree, ref node, EventArgs.Empty);
if (node != null)
{
Tree.Add(node);
OnAfterNodeRender(ref Tree, ref node, EventArgs.Empty);
}
}
}
OnAfterTreeRender(docs, args);
}*/
public override void Render(ref XmlTree Tree)
{
//get documents to render
var entities = Services.EntityService.GetChildren(m_id, UmbracoObjectTypes.Document).ToArray();
var args = new TreeEventArgs(Tree);
OnBeforeTreeRender(entities, args, true);
foreach (var entity in entities)
if (UseOptimizedRendering == false)
{
var e = entity as UmbracoEntity;
List<IAction> allowedUserOptions = GetUserActionsForNode(e);
if (CanUserAccessNode(e, allowedUserOptions))
//We cannot run optimized mode since there are subscribers to events/methods that require document instances
// so we'll render the original way by looking up the docs.
//get documents to render
var docs = Document.GetChildrenForTree(m_id);
var args = new TreeEventArgs(Tree);
OnBeforeTreeRender(docs, args);
foreach (var dd in docs)
{
XmlTreeNode node = CreateNode(e, allowedUserOptions);
OnRenderNode(ref node, new Document(entity, LoadMinimalDocument));
OnBeforeNodeRender(ref Tree, ref node, EventArgs.Empty);
if (node != null)
var allowedUserOptions = GetUserActionsForNode(dd);
if (CanUserAccessNode(dd, allowedUserOptions))
{
Tree.Add(node);
OnAfterNodeRender(ref Tree, ref node, EventArgs.Empty);
var node = CreateNode(dd, allowedUserOptions);
OnRenderNode(ref node, dd);
OnBeforeNodeRender(ref Tree, ref node, EventArgs.Empty);
if (node != null)
{
Tree.Add(node);
OnAfterNodeRender(ref Tree, ref node, EventArgs.Empty);
}
}
}
OnAfterTreeRender(docs, args);
}
else
{
//We ARE running in optmized mode, this means we will NOT be raising the BeforeTreeRender or AfterTreeRender
// events and NOT calling the OnRenderNode method - we've already detected that there are not subscribers or implementations
// to call so that is fine.
var entities = Services.EntityService.GetChildren(m_id, UmbracoObjectTypes.Document).ToArray();
foreach (var entity in entities)
{
var e = entity as UmbracoEntity;
var allowedUserOptions = GetUserActionsForNode(e);
if (CanUserAccessNode(e, allowedUserOptions))
{
var node = CreateNode(e, allowedUserOptions);
//in optimized mode the LoadMinimalDocument will ALWAYS be true, if it is not true then we will
// be rendering in non-optimized mode and this code will not get executed so we don't need to worry
// about performance here.
OnRenderNode(ref node, new Document(e, LoadMinimalDocument));
OnBeforeNodeRender(ref Tree, ref node, EventArgs.Empty);
if (node != null)
{
Tree.Add(node);
OnAfterNodeRender(ref Tree, ref node, EventArgs.Empty);
}
}
}
}
OnAfterTreeRender(entities, args, true);
}
#region Tree Create-node-helper Methods - Legacy
@@ -475,5 +478,35 @@ function openContent(id) {
return umbraco.BusinessLogic.Actions.Action.FromString(fullMenu);
}
/// <summary>
/// Returns true if we can use the EntityService to render the tree or revert to the original way
/// using normal documents
/// </summary>
/// <remarks>
/// We determine this by:
/// * If there are any subscribers to the events: BeforeTreeRender or AfterTreeRender - then we cannot run optimized
/// * If there are any overrides of the method: OnRenderNode - then we cannot run optimized
/// </remarks>
internal bool UseOptimizedRendering
{
get
{
if (HasEntityBasedEventSubscribers)
{
return false;
}
//now we need to check if the current tree type has OnRenderNode overridden with a custom implementation
//Strangely - this even works in med trust!
var method = this.GetType().GetMethod("OnRenderNode", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(XmlTreeNode).MakeByRefType(), typeof(Document) }, null);
if (TypeHelper.IsOverride(method) && LoadMinimalDocument == false)
{
return false;
}
return true;
}
}
}
}
@@ -2,12 +2,14 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using umbraco.BasePages;
using umbraco.BusinessLogic;
using umbraco.BusinessLogic.Actions;
using umbraco.cms.businesslogic.web;
using umbraco.interfaces;
using Umbraco.Core;
using Media = umbraco.cms.businesslogic.media.Media;
@@ -17,7 +19,6 @@ namespace umbraco.cms.presentation.Trees
{
public abstract class BaseMediaTree : BaseTree
{
private DisposableTimer _timer;
private User _user;
public BaseMediaTree(string application)
@@ -57,78 +58,109 @@ function openMedia(id) {
}
}
//Updated Render method for improved performance, but currently not usable because of backwards compatibility
//with the OnBeforeTreeRender/OnAfterTreeRender events, which sends an array for legacy Media items.
public override void Render(ref XmlTree tree)
{
//_timer = DisposableTimer.Start(x => LogHelper.Debug<BaseMediaTree>("Media tree loaded" + " (took " + x + "ms)"));
var entities = Services.EntityService.GetChildren(m_id, UmbracoObjectTypes.Media).ToArray();
var args = new TreeEventArgs(tree);
OnBeforeTreeRender(entities, args, false);
foreach (UmbracoEntity entity in entities)
if (UseOptimizedRendering == false)
{
XmlTreeNode xNode = XmlTreeNode.Create(this);
xNode.NodeID = entity.Id.ToString(CultureInfo.InvariantCulture);
xNode.Text = entity.Name;
//We cannot run optimized mode since there are subscribers to events/methods that require document instances
// so we'll render the original way by looking up the docs.
xNode.HasChildren = entity.HasChildren;
xNode.Source = this.IsDialog ? GetTreeDialogUrl(entity.Id) : GetTreeServiceUrl(entity.Id);
var docs = new Media(m_id).Children;
xNode.Icon = entity.ContentTypeIcon;
xNode.OpenIcon = entity.ContentTypeIcon;
if (IsDialog == false)
var args = new TreeEventArgs(tree);
OnBeforeTreeRender(docs, args);
foreach (var dd in docs)
{
if(this.ShowContextMenu == false)
xNode.Menu = null;
xNode.Action = "javascript:openMedia(" + entity.Id + ");";
}
else
{
xNode.Menu = this.ShowContextMenu ? new List<IAction>(new IAction[] { ActionRefresh.Instance }) : null;
if (this.DialogMode == TreeDialogModes.fulllink)
var e = dd;
var xNode = PerformNodeRender(e.Id, e.Text, e.HasChildren, e.ContentType.IconUrl, e.ContentType.Alias, () => GetLinkValue(e, e.Id.ToString(CultureInfo.InvariantCulture)));
OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty);
if (xNode != null)
{
string nodeLink = GetLinkValue(entity);
if (string.IsNullOrEmpty(nodeLink) == false)
{
xNode.Action = "javascript:openMedia('" + nodeLink + "');";
}
else
{
if (string.Equals(entity.ContentTypeAlias, Constants.Conventions.MediaTypes.Folder, StringComparison.OrdinalIgnoreCase))
{
//#U4-2254 - Inspiration to use void from here: http://stackoverflow.com/questions/4924383/jquery-object-object-error
xNode.Action = "javascript:void jQuery('.umbTree #" + entity.Id.ToString(CultureInfo.InvariantCulture) + "').click();";
}
else
{
xNode.Action = null;
xNode.Style.DimNode();
}
}
tree.Add(xNode);
OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty);
}
}
OnAfterTreeRender(docs, args);
}
else
{
//We ARE running in optmized mode, this means we will NOT be raising the BeforeTreeRender or AfterTreeRender
// events - we've already detected that there are not subscribers or implementations
// to call so that is fine.
var entities = Services.EntityService.GetChildren(m_id, UmbracoObjectTypes.Media).ToArray();
foreach (UmbracoEntity entity in entities)
{
var e = entity;
var xNode = PerformNodeRender(e.Id, entity.Name, e.HasChildren, e.ContentTypeIcon, e.ContentTypeAlias, () => GetLinkValue(e));
OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty);
if (xNode != null)
{
tree.Add(xNode);
OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty);
}
}
}
}
private XmlTreeNode PerformNodeRender(int nodeId, string nodeName, bool hasChildren, string icon, string contentTypeAlias, Func<string> getLinkValue)
{
var xNode = XmlTreeNode.Create(this);
xNode.NodeID = nodeId.ToString(CultureInfo.InvariantCulture);
xNode.Text = nodeName;
xNode.HasChildren = hasChildren;
xNode.Source = this.IsDialog ? GetTreeDialogUrl(nodeId) : GetTreeServiceUrl(nodeId);
xNode.Icon = icon;
xNode.OpenIcon = icon;
if (IsDialog == false)
{
if (this.ShowContextMenu == false)
xNode.Menu = null;
xNode.Action = "javascript:openMedia(" + nodeId + ");";
}
else
{
xNode.Menu = this.ShowContextMenu ? new List<IAction>(new IAction[] { ActionRefresh.Instance }) : null;
if (this.DialogMode == TreeDialogModes.fulllink)
{
string nodeLink = getLinkValue();
if (string.IsNullOrEmpty(nodeLink) == false)
{
xNode.Action = "javascript:openMedia('" + nodeLink + "');";
}
else
{
xNode.Action = "javascript:openMedia('" + entity.Id.ToString(CultureInfo.InvariantCulture) + "');";
if (string.Equals(contentTypeAlias, Constants.Conventions.MediaTypes.Folder, StringComparison.OrdinalIgnoreCase))
{
//#U4-2254 - Inspiration to use void from here: http://stackoverflow.com/questions/4924383/jquery-object-object-error
xNode.Action = "javascript:void jQuery('.umbTree #" + nodeId.ToString(CultureInfo.InvariantCulture) + "').click();";
}
else
{
xNode.Action = null;
xNode.Style.DimNode();
}
}
}
OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty);
if (xNode != null)
else
{
tree.Add(xNode);
OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty);
xNode.Action = "javascript:openMedia('" + nodeId.ToString(CultureInfo.InvariantCulture) + "');";
}
}
//stop the timer and log the output
//_timer.Dispose();
OnAfterTreeRender(entities, args, false);
return xNode;
}
/// <summary>
/// Returns the value for a link in WYSIWYG mode, by default only media items that have a
@@ -183,5 +215,26 @@ function openMedia(id) {
/// </summary>
public static List<Guid> LinkableMediaDataTypes { get; protected set; }
/// <summary>
/// Returns true if we can use the EntityService to render the tree or revert to the original way
/// using normal documents
/// </summary>
/// <remarks>
/// We determine this by:
/// * If there are any subscribers to the events: BeforeTreeRender or AfterTreeRender - then we cannot run optimized
/// </remarks>
internal bool UseOptimizedRendering
{
get
{
if (HasEntityBasedEventSubscribers)
{
return false;
}
return true;
}
}
}
}
@@ -527,6 +527,7 @@ namespace umbraco.cms.presentation.Trees
AfterTreeRender(sender, e);
}
[Obsolete("Do not use this method to raise events, it is no longer used and will cause very high performance spikes!")]
protected internal virtual void OnBeforeTreeRender(IEnumerable<IUmbracoEntity> sender, TreeEventArgs e, bool isContent)
{
if (BeforeTreeRender != null)
@@ -542,6 +543,7 @@ namespace umbraco.cms.presentation.Trees
}
}
[Obsolete("Do not use this method to raise events, it is no longer used and will cause very high performance spikes!")]
protected internal virtual void OnAfterTreeRender(IEnumerable<IUmbracoEntity> sender, TreeEventArgs e, bool isContent)
{
if (AfterTreeRender != null)
@@ -557,6 +559,14 @@ namespace umbraco.cms.presentation.Trees
}
}
/// <summary>
/// Returns true if there are subscribers to either BeforeTreeRender or AfterTreeRender
/// </summary>
internal bool HasEntityBasedEventSubscribers
{
get { return BeforeTreeRender != null || AfterTreeRender != null; }
}
/// <summary>
/// Event that is raised once actions are assigned to nodes
/// </summary>
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Text;
using umbraco.businesslogic;
using umbraco.cms.businesslogic;
@@ -1,10 +1,12 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using umbraco.BusinessLogic.Actions;
using umbraco.businesslogic;
using umbraco.cms.businesslogic.web;
using umbraco.cms.presentation.Trees;
using umbraco.interfaces;
using Umbraco.Core;
using Action = umbraco.BusinessLogic.Actions.Action;
namespace umbraco
{
@@ -94,8 +94,7 @@ namespace umbraco
{
//write out the template header
sw.Write("@inherits ");
sw.Write(typeof(UmbracoViewPage<>).FullName.TrimEnd("`1"));
sw.Write("<dynamic>");
sw.Write(typeof(UmbracoTemplatePage).FullName.TrimEnd("`1"));
}
public bool Delete()
@@ -272,11 +272,15 @@ namespace umbraco.dialogs
{
if (CurrentApp == Constants.Applications.Content)
{
Services.ContentService.Move((IContent)currContent, Request.GetItemAs<int>("copyTo"), getUser().Id);
//Backwards comp. change, so old events are fired #U4-2731
var doc = new Document(currContent as IContent);
doc.Move(Request.GetItemAs<int>("copyTo"));
}
else
{
Services.MediaService.Move((IMedia)currContent, Request.GetItemAs<int>("copyTo"), getUser().Id);
//Backwards comp. change, so old events are fired #U4-2731
var media = new umbraco.cms.businesslogic.media.Media(currContent as IMedia);
media.Move(Request.GetItemAs<int>("copyTo"));
library.ClearLibraryCacheForMedia(currContent.Id);
}
@@ -290,7 +294,9 @@ namespace umbraco.dialogs
{
//NOTE: We ONLY support Copy on content not media for some reason.
var newContent = Services.ContentService.Copy((IContent)currContent, Request.GetItemAs<int>("copyTo"), RelateDocuments.Checked, getUser().Id);
//Backwards comp. change, so old events are fired #U4-2731
var newContent = new Document(currContent as IContent);
newContent.Copy(Request.GetItemAs<int>("copyTo"), getUser(), RelateDocuments.Checked);
feedback.Text = ui.Text("moveOrCopy", "copyDone", nodes, getUser()) + "</p><p><a href='#' onclick='" + ClientTools.Scripts.CloseModalWindow() + "'>" + ui.Text("closeThisWindow") + "</a>";
feedback.type = uicontrols.Feedback.feedbacktype.success;
@@ -64,7 +64,7 @@ namespace umbraco.cms.presentation.members
}
handled = true;
}
setupExtraEditorControls();
return handled;
}
private void setupExtraEditorControls(){
@@ -10,6 +10,7 @@ using System.Xml;
using Umbraco.Core.Logging;
using umbraco.BasePages;
using umbraco.BusinessLogic;
using umbraco.businesslogic.Exceptions;
using umbraco.cms.businesslogic.media;
using umbraco.cms.businesslogic.propertytype;
using umbraco.cms.businesslogic.web;
@@ -64,20 +65,27 @@ namespace umbraco.cms.presentation.user
protected void Page_Load(object sender, EventArgs e)
{
//if the current user is not an admin they cannot edit a user at all
if (CurrentUser.IsAdmin() == false)
{
throw new UserAuthorizationException("Access denied");
}
int UID = int.Parse(Request.QueryString["id"]);
u = BusinessLogic.User.GetUser(UID);
// do initial check for edit rights
//the true admin can only edit the true admin
if (u.Id == 0 && CurrentUser.Id != 0)
{
throw new Exception("Only the root user can edit the 'root' user (id:0)");
}
else if (u.IsAdmin() && !CurrentUser.IsAdmin())
//only another admin can edit another admin (who is not the true admin)
if (u.IsAdmin() && CurrentUser.IsAdmin() == false)
{
throw new Exception("Admin users can only be edited by admins");
}
// check if canvas editing is enabled
DefaultToLiveEditing.Visible = UmbracoSettings.EnableCanvasEditing;
@@ -351,6 +359,8 @@ namespace umbraco.cms.presentation.user
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//lapps.SelectionMode = ListSelectionMode.Multiple;
lapps.RepeatLayout = RepeatLayout.Flow;
lapps.RepeatDirection = RepeatDirection.Vertical;
@@ -89,13 +89,24 @@ namespace umbraco.webservices
{
//NOTE: The legacy code threw an exception so will continue to do that.
AuthorizeRequest(DefaultApps.settings.ToString(), true);
var templateFile =
System.IO.File.OpenText(IOHelper.MapPath(SystemDirectories.Umbraco + "/scripting/templates/cshtml/" + templateId));
var content = templateFile.ReadToEnd();
templateFile.Close();
return content;
var snippetPath = SystemDirectories.Umbraco + "/scripting/templates/cshtml/";
var filePath = IOHelper.MapPath(snippetPath + templateId);
//Directory check.. only allow files in script dir and below to be edited
if (filePath.StartsWith(IOHelper.MapPath(snippetPath)))
{
var templateFile =
System.IO.File.OpenText(filePath);
var content = templateFile.ReadToEnd();
templateFile.Close();
return content;
}
else
{
throw new ArgumentException("Couldn't open snippet - Illegal path");
}
}
}
@@ -65,6 +65,17 @@ namespace umbraco.cms.businesslogic.datatype
/// <param name="strDbType"></param>
void IDataValueSetter.SetValue(object val, string strDbType)
{
//We need to ensure that val is not a null value, if it is then we'll convert this to an empty string.
//The reason for this is because by default the DefaultData.Value property returns an empty string when
// there is no value, this is based on the PropertyDataDto.GetValue return value which defaults to an
// empty string (which is called from this class's method LoadValueFromDatabase).
//Some legacy implementations of DefaultData are expecting an empty string when there is
// no value so we need to keep this consistent.
if (val == null)
{
val = string.Empty;
}
_value = val;
//now that we've set our value, we can update our BaseDataType object with the correct values from the db
//instead of making it query for itself. This is a peformance optimization enhancement.
@@ -11,10 +11,17 @@ namespace umbraco.editorControls.datepicker
public override System.Xml.XmlNode ToXMl(System.Xml.XmlDocument d)
{
if (Value != null && Value.ToString() != "")
return d.CreateTextNode(((DateTime) Value).ToString("s"));
else
return d.CreateTextNode("");
if (Value != null && Value.ToString() != "")
{
if(Value is DateTime)
return d.CreateTextNode(((DateTime) Value).ToString("s"));
DateTime convertedDate;
if (DateTime.TryParse(Value.ToString(), out convertedDate))
return d.CreateTextNode(convertedDate.ToString("s"));
}
return d.CreateTextNode("");
}
public override void MakeNew(int PropertyId)
@@ -8,14 +8,14 @@ namespace umbraco.editorControls.imagecropper
public override XmlNode ToXMl(XmlDocument data)
{
if (Value.ToString() != "") {
XmlDocument xd = new XmlDocument();
if (Value != null && Value.ToString() != "")
{
var xd = new XmlDocument();
xd.LoadXml(Value.ToString());
return data.ImportNode(xd.DocumentElement, true);
} else {
return base.ToXMl(data);
}
return base.ToXMl(data);
}
}
}