Compare commits

..

70 Commits

Author SHA1 Message Date
Sebastiaan Janssen a42526b890 This file just keeps being marked as "changed" by git, committing it so I don't have to discard changes all the time 2015-05-12 11:15:02 +02:00
Shannon 3a36513307 Fixes: U4-6609 SQL Exception when trying to delete a template that isn't assigned to any doc type 2015-05-12 17:59:06 +10:00
Shannon 0548a32405 adds some simple docs to umb settings 2015-05-12 17:32:26 +10:00
Shannon 433950dd59 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2015-05-12 12:39:57 +10:00
Shannon ad8926668e Fixes: U4-6588 UmbracoSettings Error404 support Guids and Xpath - To achieve this, had to create an Id -> Key and Key -> Id method on EntityService including a cache for it which means updating all relavent cache refreshers to clear this cache when things are removed. Moved the logic for parsing an Umbraco XPath query (with tokens) to a stand-alone testable class (though haven't written tests), move the logic for looking up a not found page to the NotFoundHandlerHelper (instead of legacy 'library'). Fixes the $root query, since I don't think that ever worked. I've tested $root now for both MNTP and for the not found handler and it works. 2015-05-12 12:39:46 +10:00
Sebastiaan Janssen 4ebc0fe4cf U4-6383 Download all translation tasks as XML Error
#U4-6383 Fixed Due in version 7.2.5
2015-05-11 21:33:52 +02:00
Shannon 1b1455067e Fixes: U4-6606 maxInvalidPasswordAttempts work for the UsersMembershipProvider doesn't work any more 2015-05-11 19:44:59 +10:00
Shannon 795de94a5f Fixes: U4-6102 After renaming Grid row configurations all data is lost for renames. So now we have warnings for both deletes and renames. 2015-05-11 18:46:26 +10:00
Shannon d6699ab3b3 Fixes: U4-6102 After renaming Grid row configurations all data is lost, also ensures that all events are unsubscribed on destroy 2015-05-11 16:18:35 +10:00
Shannon d94b334375 Moves login logging to the provider level 2015-05-11 12:22:56 +10:00
Shannon a4a49b1466 Revert "Fixes MVC 4.0.0.1 problem once and for all." - All MVC ref's are 4.0.0.0, no web config transforms (also there was never a 4.0.0.1 version of System.Net.Http). Everything works on my machine now, even with 4.0.0.1 installed in the GAC. 2015-05-11 11:45:13 +10:00
Shannon Deminick 2c92cd9ca9 Merge pull request #683 from umbraco/U4-6603
U4-6603 Log failed login attempts
2015-05-11 09:07:24 +10:00
Sebastiaan Janssen c34605937c U4-6603 Log failed login attempts
#U4-6603 Fixed
2015-05-10 17:47:32 +02:00
Shannon Deminick 2a9d3df822 Merge pull request #682 from hfloyd/dev-v7
English Language file updates (Umbraco/config/lang)
2015-05-08 08:48:38 +10:00
Heather Floyd 3b849987bf Small fixes to 'en' language file. Update of 'en-us' language file to match 'en' language file. 2015-05-07 16:41:12 -04:00
Shannon 8443513b2b fixes sorting with multipletextbox 2015-05-07 13:39:28 +10:00
Shannon fec9d066f0 Merge branch 'property-editor-fixes' of https://github.com/pynej/Umbraco-CMS into pynej-property-editor-fixes
Conflicts:
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.controller.js
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.html
	src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs
2015-05-07 13:24:59 +10:00
Shannon a69c7dd1fc Manually merges PR: 564 2015-05-07 13:09:29 +10:00
Shannon 4e6a3458d0 Fixes: U4-6600 Label on files not just folders in file browser (media) and fixes up the last image rendered in the photo browser, as well as the overlays, whitespace and overflow and vertical alignment. 2015-05-07 12:57:23 +10:00
Shannon a5bb8ba8ee Merge branch 'iamphill-media-label' into dev-v7 2015-05-07 12:01:44 +10:00
Shannon d4f3dbcfc0 Merge branch 'media-label' of https://github.com/iamphill/Umbraco-CMS into iamphill-media-label 2015-05-07 12:01:31 +10:00
Shannon 6a0656fbb0 fixes spacing for radio/check boxes (U4-6036) tested in ie, ff and chrome 2015-05-07 11:59:10 +10:00
Shannon Deminick 9dc0999ebd Merge pull request #595 from redmorello/U4-6036
U4 6036 - Checkbox and Radio button styling incorrect in backend
2015-05-07 11:49:30 +10:00
Shannon 813f1a1f2d Fixes: U4-6035 Properrty.WasDirty() always returns false 2015-05-07 11:43:53 +10:00
Shannon e45b0a53b8 Merge branch 'aaronpowell-master-v7' into dev-v7 2015-05-07 11:07:16 +10:00
Shannon 685635c568 Merge branch 'master-v7' of https://github.com/aaronpowell/Umbraco-CMS into aaronpowell-master-v7 2015-05-07 11:06:55 +10:00
Shannon Deminick a3e37de1ad Merge pull request #633 from bjarnef/dev-v7-U4-4507
U4-4507 - Make expand arrow in sections as a toggle
2015-05-07 11:02:08 +10:00
Shannon Deminick 692a8f807e Merge pull request #638 from bjarnef/dev-v7-U4-6276
Fix for U4-6276 - Keep headline at same position
2015-05-07 10:51:32 +10:00
Shannon f4bdcae411 Fixes: U4-6236 umbraco 7 macro parameters saving "null" 2015-05-07 10:47:36 +10:00
Shannon Deminick 3a726348d2 Merge pull request #673 from kgiszewski/dev-v7
Fix for U4-6530
2015-05-07 10:21:42 +10:00
Shannon Deminick d8b029eba6 Merge pull request #680 from WebCentrum/dev-v7-gridsort
U4-6593 - After sort, reset the TinyMCE editors with previous settings
2015-05-07 10:13:29 +10:00
Shannon 7c01670caf fixes mem leaks by not unsubscribing from events 2015-05-07 09:11:39 +10:00
Shannon 3ce5ff882e Fixes U4-5213 in a better way using a query string so it's clear where it redirects to 2015-05-07 09:11:25 +10:00
Shannon 6e7aa19073 Fixes U4-5213 in a better way using a query string so it's clear where it redirects to 2015-05-07 09:00:43 +10:00
Shannon 1cac4ed075 Fixes MVC 4.0.0.1 problem once and for all. 2015-05-07 08:10:45 +10:00
Stephan e358390211 Bugfix Xml cache - bad, bad Stephan 2015-05-06 11:10:04 +02:00
Sebastiaan Janssen 2e6c643dde Bump version 2015-05-06 11:08:25 +02:00
Sebastiaan Janssen d84b8aa675 Fix duplication of the mysql DbProviderFactory when using NuGet 2015-05-06 11:04:09 +02:00
Shannon Deminick 41a0c1f491 Merge pull request #679 from WebCentrum/dev-v7-loginredir
U4-5213 - Login redirect to originally requested URL
2015-05-06 17:46:07 +10:00
Shannon e8d4777d74 re-formatted some of the PR 2015-05-06 17:36:46 +10:00
Shannon e03ef76fcd Merge branch 'Jeavon-U4-5480' into dev-v7 2015-05-06 17:35:13 +10:00
Shannon 781ca34e34 Merge branch 'U4-5480' of https://github.com/Jeavon/Umbraco-CMS into Jeavon-U4-5480 2015-05-06 17:34:59 +10:00
Shannon d01e963365 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7
Conflicts:
	src/Umbraco.Web.UI/packages.config
2015-05-06 17:28:05 +10:00
Shannon 821daa82c4 Fixes: U4-6474 Update to latest examine v0.1.63 2015-05-06 17:14:10 +10:00
Sebastiaan Janssen a51dd93ffe Expressed version range was wrong 2015-05-06 08:58:45 +02:00
Allyen 8299243129 U4-6593 - After sort, reset the TinyMCE editors with previous settings 2015-05-05 22:07:18 +02:00
Sebastiaan Janssen 4144590189 Upgrade to latest MySql.Data and loosen up NuGet dependency 2015-05-05 12:15:28 +02:00
Allyen 2f4ff6aaae Login redirect to originally requested URL 2015-05-04 11:49:07 +02:00
Sebastiaan Janssen ab0e549c70 We got rid of macroRenderings project ages ago, why is this file still here? 2015-05-01 14:27:49 +02:00
Sebastiaan Janssen be065b2fa3 Generate symbols nupkg (apparently you can create it from an existing NuSpec file, very cool)
Making sure that all pdbs ARE actually generated in Release mode (the AllBinaries file was missing loads of files)
Generate all and include all xml doc files too
Corrects WebPI zip, also shouldn't include dotLess.Core.dll
2015-05-01 14:27:26 +02:00
Sebastiaan Janssen f0dfd0dce2 U4-6568 NuGet 7.2.4 missing Microsoft.Threading.Tasks.dll and Microsoft.Threading.Tasks.Extensions.dll
#U4-6568 Fixed Due in version 7.2.5
2015-04-29 16:15:24 +02:00
Shannon da579c91e1 Fixes: U4-6460 7.2.2 -> 7.2.4 update fails with "an item with the same key has already been added" error 2015-04-27 13:40:41 +10:00
Shannon 550d690a31 Fixes: U4-6559 ServerVariables parsing - An Item with the same key has already been added 2015-04-27 12:41:19 +10:00
Shannon Deminick 40b75b7cf5 Merge pull request #672 from alecrt/dev-v7
U4-6295 - Fix for BusinessLogic.Log.CleanLogs task error
2015-04-27 10:56:33 +10:00
Shannon Deminick 0b28a68678 Merge pull request #675 from abjerner/patch-6
listview.html: the arrows for symbolizing ascending and descending are wrong
2015-04-27 10:53:52 +10:00
Anders Bjerner 5f27355247 listview.html: the arrows for symbolizing ascending and descending are wrong 2015-04-26 14:44:25 +02:00
Sebastiaan Janssen 356ea6824f U4-6547 Re: U4-6096 German Translator file broken again in V7.2.4
#U4-6547 Fixed Due in version 7.2.5
2015-04-23 16:59:57 +02:00
kgiszewski dc3e144493 Fix for U4-6530 2015-04-20 10:28:35 -04:00
alecrt f20fed3ce8 Fix for U4-6295 - BusinessLogic.Log.CleanLogs task error 2015-04-18 19:00:03 +02:00
bjarnef df5c5e78ff Headline was cuttet off in Firefox
In Firefox 35.0.1 the headline was cuttet off. The 1.4 line-height in
commit 824212f6c9 ensure the headline
isn't cuttet off. However line-height: normal act as fallback as 1em it
too little and cause the text might be cuttet off.
2015-02-16 20:58:40 +01:00
bjarnef 5579823b2d Remove padding-left from h1 in modal-left
Removed left-padding from h1 in umb-modal-left to align it with the
other text in the modal.
2015-02-16 00:11:41 +01:00
bjarnef 824212f6c9 Keep headline at same position
I made a small change to make sure the headline is in same position
regardless it is editable or readonly.
2015-02-15 22:20:34 +01:00
bjarnef 7091cb6012 Change code for help videos
Change code for in help.controller.js as it was.
2015-02-05 10:52:55 +01:00
bjarnef a721f6836f Pointer cursor for sections in IE10
IE10 displayed a text cursor for tray and help section. Added cursor:
pointer; to make sure a pointer cursor is displayed.
2015-02-05 03:31:41 +01:00
bjarnef 83840ba6dd U4-4507 - Make expand arrow in sections as a toggle
I have made some suggestions, so the right arrow act as a toggle button,
so you easily can collapse the extra overflow-sections. Furthermore I
have made some changes, so when you click userDialog or helpDialog other
open dialogs close and also sections. When you click a section or expand
it also close dialogs, so you don't have to close those dialogs first.
2015-02-04 21:55:19 +01:00
Aaron Powell b8097219fb Implementing a test for U4-6035 2014-12-21 17:56:33 +11:00
redmorello e5ec935128 Update forms.less
Removed negative left margin from checkbox and radio button inputs.
2014-12-18 11:08:44 +00:00
redmorello 3ea16e66d4 Update forms.less
Removed negative left margin from input and radio button inputs.
2014-12-18 11:07:08 +00:00
Phil Hughes 562367e9a2 Label on files not just folders 2014-12-16 15:25:13 +00:00
Jeavon Leopold ee386d06da Fix for U4-5480 "Bad value for attribute rel on element img in Richtext editor" by removing the attributes in the RTE value converter so they don't render on the front end site but still exist in the Umbraco UI 2014-10-01 18:48:23 +01:00
118 changed files with 1835 additions and 1023 deletions
+1 -2
View File
@@ -49,12 +49,11 @@ ECHO Setting node_modules folder to hidden to prevent VS13 from crashing on it w
attrib +h ..\src\Umbraco.Web.UI.Client\node_modules
ECHO Adding Web.config transform files to the NuGet package
REN .\_BuildOutput\WebApp\MacroScripts\Web.config Web.config.transform
REN .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
REN .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
ECHO Packing the NuGet release files
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version%
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version% -Symbols
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %version%
IF ERRORLEVEL 1 GOTO :showerror
+1 -1
View File
@@ -145,7 +145,7 @@
DestinationFiles="@(WebPiFiles->'$(WebPiFolder)%(RecursiveDir)%(Filename)%(Extension)')" />
<!-- Zip the files -->
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameWebPi)%22 %22$(WebPiFolderAbsolutePath)*%22" />
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameWebPi)%22 %22$(WebPiFolderAbsolutePath)*%22 -x!dotLess.Core.dll" />
</Target>
<Target Name="ZipWebApp" DependsOnTargets="CreateSystemFolders" >
@@ -1,73 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>UmbracoCms.Core.AllBinaries</id>
<version>6.1.2</version>
<title>Umbraco Cms Core All Binaries</title>
<authors>Morten Christensen</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains the core assemblies and all of the dependant assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
<summary>Contains the core assemblies and all of the dependant assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
</metadata>
<files>
<file src="..\_BuildOutput\bin\businesslogic.dll" target="lib\businesslogic.dll" />
<file src="..\_BuildOutput\bin\AutoMapper.dll" target="lib\AutoMapper.dll" />
<file src="..\_BuildOutput\bin\AutoMapper.Net4.dll" target="lib\AutoMapper.Net4.dll" />
<file src="..\_BuildOutput\bin\businesslogic.dll" target="lib\businesslogic.dll" />
<file src="..\_BuildOutput\bin\ClientDependency.Core.dll" target="lib\ClientDependency.Core.dll" />
<file src="..\_BuildOutput\bin\ClientDependency.Core.Mvc.dll" target="lib\ClientDependency.Core.Mvc.dll" />
<file src="..\_BuildOutput\bin\cms.dll" target="lib\cms.dll" />
<file src="..\_BuildOutput\bin\controls.dll" target="lib\controls.dll" />
<file src="..\_BuildOutput\bin\CookComputing.XmlRpcV2.dll" target="lib\CookComputing.XmlRpcV2.dll" />
<file src="..\_BuildOutput\bin\Examine.dll" target="lib\Examine.dll" />
<file src="..\_BuildOutput\bin\HtmlAgilityPack.dll" target="lib\HtmlAgilityPack.dll" />
<file src="..\_BuildOutput\bin\ICSharpCode.SharpZipLib.dll" target="lib\ICSharpCode.SharpZipLib.dll" />
<file src="..\_BuildOutput\bin\ImageProcessor.dll" target="lib\ImageProcessor.dll" />
<file src="..\_BuildOutput\bin\ImageProcessor.Web.dll" target="lib\ImageProcessor.Web.dll" />
<file src="..\_BuildOutput\bin\interfaces.dll" target="lib\interfaces.dll" />
<file src="..\_BuildOutput\bin\log4net.dll" target="lib\log4net.dll" />
<file src="..\_BuildOutput\bin\Lucene.Net.dll" target="lib\Lucene.Net.dll" />
<file src="..\_BuildOutput\bin\Microsoft.ApplicationBlocks.Data.dll" target="lib\Microsoft.ApplicationBlocks.Data.dll" />
<file src="..\_BuildOutput\bin\Microsoft.Threading.Tasks.dll" target="lib\Microsoft.Threading.Tasks.dll" />
<file src="..\_BuildOutput\bin\Microsoft.Threading.Tasks.Extensions.dll" target="lib\Microsoft.Threading.Tasks.Extensions.dll" />
<file src="..\_BuildOutput\bin\Microsoft.Web.Infrastructure.dll" target="lib\Microsoft.Web.Infrastructure.dll" />
<file src="..\_BuildOutput\bin\Microsoft.Web.Mvc.FixedDisplayModes.dll" target="lib\Microsoft.Web.Mvc.FixedDisplayModes.dll" />
<file src="..\_BuildOutput\bin\MiniProfiler.dll" target="lib\MiniProfiler.dll" />
<file src="..\_BuildOutput\bin\MySql.Data.dll" target="lib\MySql.Data.dll" />
<file src="..\_BuildOutput\bin\Newtonsoft.Json.dll" target="lib\Newtonsoft.Json.dll" />
<file src="..\_BuildOutput\bin\NuGet.Core.dll" target="lib\NuGet.Core.dll" />
<file src="..\_BuildOutput\bin\SQLCE4Umbraco.dll" target="lib\SQLCE4Umbraco.dll" />
<file src="..\_BuildOutput\bin\System.Data.SqlServerCe.dll" target="lib\System.Data.SqlServerCe.dll" />
<file src="..\_BuildOutput\bin\System.Data.SqlServerCe.Entity.dll" target="lib\System.Data.SqlServerCe.Entity.dll" />
<file src="..\_BuildOutput\bin\System.Net.Http.dll" target="lib\System.Net.Http.dll" />
<file src="..\_BuildOutput\bin\System.Net.Http.Extensions.dll" target="lib\System.Net.Http.Extensions.dll" />
<file src="..\_BuildOutput\bin\System.Net.Http.Formatting.dll" target="lib\System.Net.Http.Formatting.dll" />
<file src="..\_BuildOutput\bin\System.Net.Http.Primitives.dll" target="lib\System.Net.Http.Primitives.dll" />
<file src="..\_BuildOutput\bin\System.Net.Http.WebRequest.dll" target="lib\System.Net.Http.WebRequest.dll" />
<file src="..\_BuildOutput\bin\System.Web.Helpers.dll" target="lib\System.Web.Helpers.dll" />
<file src="..\_BuildOutput\bin\System.Web.Http.dll" target="lib\System.Web.Http.dll" />
<file src="..\_BuildOutput\bin\System.Web.Http.WebHost.dll" target="lib\System.Web.Http.WebHost.dll" />
<file src="..\_BuildOutput\bin\System.Web.Mvc.dll" target="lib\System.Web.Mvc.dll" />
<file src="..\_BuildOutput\bin\System.Web.Razor.dll" target="lib\System.Web.Razor.dll" />
<file src="..\_BuildOutput\bin\System.Web.WebPages.Administration.dll" target="lib\System.Web.WebPages.Administration.dll" />
<file src="..\_BuildOutput\bin\System.Web.WebPages.Deployment.dll" target="lib\System.Web.WebPages.Deployment.dll" />
<file src="..\_BuildOutput\bin\System.Web.WebPages.dll" target="lib\System.Web.WebPages.dll" />
<file src="..\_BuildOutput\bin\System.Web.WebPages.Razor.dll" target="lib\System.Web.WebPages.Razor.dll" />
<file src="..\_BuildOutput\bin\TidyNet.dll" target="lib\TidyNet.dll" />
<file src="..\_BuildOutput\bin\Umbraco.Core.dll" target="lib\Umbraco.Core.dll" />
<file src="..\_BuildOutput\bin\umbraco.DataLayer.dll" target="lib\umbraco.DataLayer.dll" />
<file src="..\_BuildOutput\bin\umbraco.dll" target="lib\umbraco.dll" />
<file src="..\_BuildOutput\bin\umbraco.editorControls.dll" target="lib\umbraco.editorControls.dll" />
<file src="..\_BuildOutput\bin\umbraco.MacroEngines.dll" target="lib\umbraco.MacroEngines.dll" />
<file src="..\_BuildOutput\bin\umbraco.providers.dll" target="lib\umbraco.providers.dll" />
<file src="..\_BuildOutput\bin\Umbraco.Web.UI.dll" target="lib\Umbraco.Web.UI.dll" />
<file src="..\_BuildOutput\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
<file src="..\_BuildOutput\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
</files>
</package>
@@ -1,71 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>UmbracoCms.Core</id>
<version>7.0.0</version>
<title>Umbraco Cms Core Binaries</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
</metadata>
<files>
<file src="..\..\src\SQLCE4Umbraco\obj\Debug\SQLCE4Umbraco.dll" target="lib" />
<file src="..\..\src\SQLCE4Umbraco\obj\Debug\SQLCE4Umbraco.pdb" target="lib" />
<file src="..\..\src\SQLCE4Umbraco\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\SQLCE4Umbraco" />
<file src="..\..\src\umbraco.businesslogic\obj\Debug\businesslogic.dll" target="lib" />
<file src="..\..\src\umbraco.businesslogic\obj\Debug\businesslogic.pdb" target="lib" />
<file src="..\..\src\umbraco.businesslogic\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.businesslogic" />
<file src="..\..\src\umbraco.cms\obj\Debug\cms.dll" target="lib" />
<file src="..\..\src\umbraco.cms\obj\Debug\cms.pdb" target="lib" />
<file src="..\..\src\umbraco.cms\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.cms" />
<file src="..\..\src\umbraco.controls\obj\Debug\controls.dll" target="lib" />
<file src="..\..\src\umbraco.controls\obj\Debug\controls.pdb" target="lib" />
<file src="..\..\src\umbraco.controls\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.controls" />
<file src="..\..\src\umbraco.interfaces\obj\Debug\interfaces.dll" target="lib" />
<file src="..\..\src\umbraco.interfaces\obj\Debug\interfaces.pdb" target="lib" />
<file src="..\..\src\umbraco.interfaces\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.interfaces" />
<file src="..\..\src\Umbraco.Core\obj\Debug\Umbraco.Core.dll" target="lib" />
<file src="..\..\src\Umbraco.Core\obj\Debug\Umbraco.Core.pdb" target="lib" />
<file src="..\..\src\Umbraco.Core\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
<file src="..\..\src\umbraco.datalayer\obj\Debug\umbraco.DataLayer.dll" target="lib" />
<file src="..\..\src\umbraco.datalayer\obj\Debug\umbraco.DataLayer.pdb" target="lib" />
<file src="..\..\src\umbraco.datalayer\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.datalayer" />
<file src="..\..\src\umbraco.editorControls\obj\Debug\umbraco.editorControls.dll" target="lib" />
<file src="..\..\src\umbraco.editorControls\obj\Debug\umbraco.editorControls.pdb" target="lib" />
<file src="..\..\src\umbraco.editorControls\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.editorControls" />
<file src="..\..\src\umbraco.MacroEngines\obj\Debug\umbraco.MacroEngines.dll" target="lib" />
<file src="..\..\src\umbraco.MacroEngines\obj\Debug\umbraco.MacroEngines.pdb" target="lib" />
<file src="..\..\src\umbraco.MacroEngines\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.MacroEngines" />
<file src="..\..\src\umbraco.providers\obj\Debug\umbraco.providers.dll" target="lib" />
<file src="..\..\src\umbraco.providers\obj\Debug\umbraco.providers.pdb" target="lib" />
<file src="..\..\src\umbraco.providers\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.providers" />
<file src="..\..\src\Umbraco.Web\obj\Debug\umbraco.dll" target="lib" />
<file src="..\..\src\Umbraco.Web\obj\Debug\umbraco.pdb" target="lib" />
<file src="..\..\src\Umbraco.Web\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
<file src="..\..\src\bin\Debug\Umbraco.Web.UI.dll" target="lib" />
<file src="..\..\src\bin\Debug\Umbraco.Web.UI.pdb" target="lib" />
<file src="..\..\src\Umbraco.Web.UI\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web.UI" />
<file src="..\..\src\UmbracoExamine\obj\Debug\UmbracoExamine.dll" target="lib" />
<file src="..\..\src\UmbracoExamine\obj\Debug\UmbracoExamine.pdb" target="lib" />
<file src="..\..\src\UmbracoExamine\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\UmbracoExamine" />
</files>
</package>
+33 -2
View File
@@ -26,13 +26,13 @@
<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="MySql.Data" version="[6.9.6, 7.0.0)" />
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
<dependency id="ClientDependency" version="[1.8.3.1, 2.0.0)" />
<dependency id="ClientDependency-Mvc" version="[1.8.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.0.0, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.5, 7.0.0)" />
<dependency id="Examine" version="[0.1.62, 1.0.0)" />
<dependency id="Examine" version="[0.1.63, 1.0.0)" />
<dependency id="ImageProcessor" version="[1.9.5, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[3.3.1, 5.0.0)" />
</dependencies>
@@ -49,6 +49,7 @@
<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\SQLCE4Umbraco.dll" target="lib\SQLCE4Umbraco.dll" />
<file src="..\_BuildOutput\WebApp\bin\SQLCE4Umbraco.xml" target="lib\SQLCE4Umbraco.xml" />
<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" />
@@ -65,8 +66,38 @@
<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.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.xml" target="lib\UmbracoExamine.xml" />
<file src="..\_BuildOutput\WebApp\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
<file src="tools\install.core.ps1" target="tools\install.ps1" />
<!-- Added to be able to produce a symbols package -->
<file src="..\_BuildOutput\bin\SQLCE4Umbraco.pdb" target="lib" />
<file src="..\..\src\SQLCE4Umbraco\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\SQLCE4Umbraco" />
<file src="..\_BuildOutput\bin\businesslogic.pdb" target="lib" />
<file src="..\..\src\umbraco.businesslogic\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.businesslogic" />
<file src="..\_BuildOutput\bin\cms.pdb" target="lib" />
<file src="..\..\src\umbraco.cms\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.cms" />
<file src="..\_BuildOutput\bin\controls.pdb" target="lib" />
<file src="..\..\src\umbraco.controls\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.controls" />
<file src="..\_BuildOutput\bin\interfaces.pdb" target="lib" />
<file src="..\..\src\umbraco.interfaces\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.interfaces" />
<file src="..\_BuildOutput\bin\Umbraco.Core.pdb" target="lib" />
<file src="..\..\src\Umbraco.Core\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
<file src="..\_BuildOutput\bin\umbraco.DataLayer.pdb" target="lib" />
<file src="..\..\src\umbraco.datalayer\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.datalayer" />
<file src="..\_BuildOutput\bin\umbraco.editorControls.pdb" target="lib" />
<file src="..\..\src\umbraco.editorControls\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.editorControls" />
<file src="..\_BuildOutput\bin\umbraco.MacroEngines.pdb" target="lib" />
<file src="..\..\src\umbraco.MacroEngines\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.MacroEngines" />
<file src="..\_BuildOutput\bin\umbraco.providers.pdb" target="lib" />
<file src="..\..\src\umbraco.providers\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.providers" />
<file src="..\_BuildOutput\bin\umbraco.pdb" target="lib" />
<file src="..\..\src\Umbraco.Web\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
<file src="..\_BuildOutput\bin\Umbraco.Web.UI.pdb" target="lib" />
<file src="..\..\src\Umbraco.Web.UI\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web.UI" />
<file src="..\_BuildOutput\bin\UmbracoExamine.pdb" target="lib" />
<file src="..\..\src\UmbracoExamine\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\UmbracoExamine" />
</files>
</package>
+4 -2
View File
@@ -37,8 +37,10 @@
<DbProviderFactories xdt:Transform="InsertIfMissing">
<remove invariant="System.Data.SqlServerCe.4.0" xdt:Locator="Match(invariant)" xdt:Transform="InsertIfMissing" />
<add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe" xdt:Locator="Match(invariant)" xdt:Transform="SetAttributes(invariant,description,type)" />
<remove invariant="MySql.Data.MySqlClient" xdt:Locator="Match(invariant)" xdt:Transform="InsertIfMissing" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data" xdt:Locator="Match(invariant)" xdt:Transform="SetAttributes(invariant,description,type)" />
<remove invariant="MySql.Data.MySqlClient" xdt:Locator="Match(invariant)" xdt:Transform="InsertIfMissing" />
<add invariant="MySql.Data.MySqlClient" xdt:Locator="Match(invariant)" xdt:Transform="Remove" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data" xdt:Locator="Match(invariant)" xdt:Transform="InsertIfMissing" />
<add invariant="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data" xdt:Locator="Match(invariant)" xdt:Transform="SetAttributes(type)" />
</DbProviderFactories>
</system.data>
<clientDependency xdt:Transform="RemoveAttributes(version)" />
+1 -2
View File
@@ -1,3 +1,2 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.2.5
RC
7.2.5
+1 -1
View File
@@ -12,4 +12,4 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.2.5")]
[assembly: AssemblyInformationalVersion("7.2.5-RC")]
[assembly: AssemblyInformationalVersion("7.2.5")]
+3
View File
@@ -54,5 +54,8 @@ namespace Umbraco.Core.Cache
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
public const string IdToKeyCacheKey = "UI2K";
public const string KeyToIdCacheKey = "UK2I";
}
}
@@ -34,7 +34,7 @@ namespace Umbraco.Core.Configuration
{
get
{
var converted = ObjectExtensions.TryConvertTo<T>(RawValue);
var converted = RawValue.TryConvertTo<T>();
if (converted.Success == false)
throw new InvalidCastException("Could not convert value " + RawValue + " to type " + typeof(T));
return converted.Result;
@@ -1,8 +1,9 @@
using System.Xml.Linq;
using System;
using System.Xml.Linq;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class ContentErrorPageElement : InnerTextConfigurationElement<int>, IContentErrorPage
internal class ContentErrorPageElement : InnerTextConfigurationElement<string>, IContentErrorPage
{
public ContentErrorPageElement(XElement rawXml)
: base(rawXml)
@@ -14,7 +15,43 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
}
public bool HasContentId
{
get { return ContentId != int.MinValue; }
}
public bool HasContentKey
{
get { return ContentKey != Guid.Empty; }
}
public int ContentId
{
get
{
int parsed;
if (int.TryParse(Value, out parsed))
{
return parsed;
}
return int.MinValue;
}
}
public Guid ContentKey
{
get
{
Guid parsed;
if (Guid.TryParse(Value, out parsed))
{
return parsed;
}
return Guid.Empty;
}
}
public string ContentXPath
{
get { return Value; }
}
@@ -1,8 +1,14 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
using System;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IContentErrorPage
{
int ContentId { get; }
Guid ContentKey { get; }
string ContentXPath { get; }
bool HasContentId { get; }
bool HasContentKey { get; }
string Culture { get; set; }
}
}
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Configuration
/// Gets the version comment (like beta or RC).
/// </summary>
/// <value>The version comment.</value>
public static string CurrentComment { get { return "RC"; } }
public static string CurrentComment { get { return ""; } }
// Get the version of the umbraco.dll by looking at a class in that dll
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
+45
View File
@@ -0,0 +1,45 @@
using System.Web;
namespace Umbraco.Core
{
public static class HttpContextExtensions
{
public static string GetCurrentRequestIpAddress(this HttpContextBase httpContext)
{
if (httpContext == null)
{
return "Unknown, httpContext is null";
}
if (httpContext.Request == null)
{
return "Unknown, httpContext.Request is null";
}
if (httpContext.Request.ServerVariables == null)
{
return "Unknown, httpContext.Request.ServerVariables is null";
}
// From: http://stackoverflow.com/a/740431/5018
try
{
var ipAddress = httpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(ipAddress))
return httpContext.Request.ServerVariables["REMOTE_ADDR"];
var addresses = ipAddress.Split(',');
if (addresses.Length != 0)
return addresses[0];
return httpContext.Request.ServerVariables["REMOTE_ADDR"];
}
catch (System.Exception ex)
{
//This try catch is to just always ensure that no matter what we're not getting any exceptions caused since
// that would cause people to not be able to login
return string.Format("Unknown, exception occurred trying to resolve IP {0}", ex);
}
}
}
}
+1 -68
View File
@@ -337,74 +337,7 @@ namespace Umbraco.Core.Models
ChangePublishedState(PublishedState.Unpublished);
}
}
/// <summary>
/// Indicates whether a specific property on the current <see cref="IContent"/> entity is dirty.
/// </summary>
/// <param name="propertyName">Name of the property to check</param>
/// <returns>True if Property is dirty, otherwise False</returns>
public override bool IsPropertyDirty(string propertyName)
{
bool existsInEntity = base.IsPropertyDirty(propertyName);
if (existsInEntity)
return true;
return Properties.Any(x => x.IsPropertyDirty(propertyName));
}
/// <summary>
/// Indicates whether the current entity is dirty.
/// </summary>
/// <returns>True if entity is dirty, otherwise False</returns>
public override bool IsDirty()
{
return IsEntityDirty() || IsAnyUserPropertyDirty();
}
/// <summary>
/// Returns true if only the entity properties are direty
/// </summary>
/// <returns></returns>
public bool IsEntityDirty()
{
return base.IsDirty();
}
/// <summary>
/// Returns true if any of the properties are dirty
/// </summary>
/// <returns></returns>
public bool IsAnyUserPropertyDirty()
{
return Properties.Any(x => x.IsDirty());
}
/// <summary>
/// Returns a list of all dirty user defined properties
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetDirtyUserProperties()
{
return Properties.Where(x => x.IsDirty()).Select(x => x.Alias);
}
/// <summary>
/// Resets dirty properties by clearing the dictionary used to track changes.
/// </summary>
/// <remarks>
/// Please note that resetting the dirty properties could potentially
/// obstruct the saving of a new or updated entity.
/// </remarks>
public override void ResetDirtyProperties()
{
base.ResetDirtyProperties();
foreach (var property in Properties)
{
property.ResetDirtyProperties();
}
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
+86 -1
View File
@@ -466,6 +466,8 @@ namespace Umbraco.Core.Models
public abstract void ChangeTrashedState(bool isTrashed, int parentId = -20);
#region Dirty property handling
/// <summary>
/// We will override this method to ensure that when we reset the dirty properties that we
/// also reset the dirty changes made to the content's Properties (user defined)
@@ -480,6 +482,89 @@ namespace Umbraco.Core.Models
prop.ResetDirtyProperties(rememberPreviouslyChangedProperties);
}
}
/// <summary>
/// Indicates whether the current entity is dirty.
/// </summary>
/// <returns>True if entity is dirty, otherwise False</returns>
public override bool IsDirty()
{
return IsEntityDirty() || this.IsAnyUserPropertyDirty();
}
/// <summary>
/// Indicates whether the current entity was dirty.
/// </summary>
/// <returns>True if entity was dirty, otherwise False</returns>
public override bool WasDirty()
{
return WasEntityDirty() || this.WasAnyUserPropertyDirty();
}
/// <summary>
/// Returns true if only the entity properties are dirty
/// </summary>
/// <returns></returns>
public bool IsEntityDirty()
{
return base.IsDirty();
}
/// <summary>
/// Returns true if only the entity properties were dirty
/// </summary>
/// <returns></returns>
public bool WasEntityDirty()
{
return base.WasDirty();
}
/// <summary>
/// Indicates whether a specific property on the current <see cref="IContent"/> entity is dirty.
/// </summary>
/// <param name="propertyName">Name of the property to check</param>
/// <returns>
/// True if any of the class properties are dirty or
/// True if any of the user defined PropertyType properties are dirty based on their alias,
/// otherwise False
/// </returns>
public override bool IsPropertyDirty(string propertyName)
{
bool existsInEntity = base.IsPropertyDirty(propertyName);
if (existsInEntity)
return true;
if (Properties.Contains(propertyName))
{
return Properties[propertyName].IsDirty();
}
return false;
}
/// <summary>
/// Indicates whether a specific property on the current entity was changed and the changes were committed
/// </summary>
/// <param name="propertyName">Name of the property to check</param>
/// <returns>
/// True if any of the class properties are dirty or
/// True if any of the user defined PropertyType properties are dirty based on their alias,
/// otherwise False
/// </returns>
public override bool WasPropertyDirty(string propertyName)
{
bool existsInEntity = base.WasPropertyDirty(propertyName);
if (existsInEntity)
return true;
if (Properties.Contains(propertyName))
{
return Properties[propertyName].WasDirty();
}
return false;
}
#endregion
}
}
+24 -8
View File
@@ -77,10 +77,9 @@ namespace Umbraco.Core.Models
/// </remarks>
internal static bool RequiresSaving(this IContent entity, PublishedState publishedState)
{
var dirtyEntity = (ICanBeDirty)entity;
var publishedChanged = dirtyEntity.IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished;
var publishedChanged = entity.IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished;
//check if any user prop has changed
var propertyValueChanged = ((Content)entity).IsAnyUserPropertyDirty();
var propertyValueChanged = entity.IsAnyUserPropertyDirty();
//We need to know if any other property apart from Published was changed here
//don't create a new version if the published state has changed to 'Save' but no data has actually been changed
@@ -114,6 +113,25 @@ namespace Umbraco.Core.Models
return ShouldCreateNewVersion(entity, publishedState);
}
/// <summary>
/// Returns a list of all dirty user defined properties
/// </summary>
/// <returns></returns>
public static IEnumerable<string> GetDirtyUserProperties(this IContentBase entity)
{
return entity.Properties.Where(x => x.IsDirty()).Select(x => x.Alias);
}
public static bool IsAnyUserPropertyDirty(this IContentBase entity)
{
return entity.Properties.Any(x => x.IsDirty());
}
public static bool WasAnyUserPropertyDirty(this IContentBase entity)
{
return entity.Properties.Any(x => x.WasDirty());
}
/// <summary>
/// Determines if a new version should be created
/// </summary>
@@ -128,15 +146,13 @@ namespace Umbraco.Core.Models
/// </remarks>
internal static bool ShouldCreateNewVersion(this IContent entity, PublishedState publishedState)
{
var dirtyEntity = (ICanBeDirty)entity;
//check if the published state has changed or the language
var publishedChanged = dirtyEntity.IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished;
var langChanged = dirtyEntity.IsPropertyDirty("Language");
var publishedChanged = entity.IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished;
var langChanged = entity.IsPropertyDirty("Language");
var contentChanged = publishedChanged || langChanged;
//check if any user prop has changed
var propertyValueChanged = ((Content)entity).IsAnyUserPropertyDirty();
var propertyValueChanged = entity.IsAnyUserPropertyDirty();
//return true if published or language has changed
if (contentChanged)
@@ -78,7 +78,7 @@ namespace Umbraco.Core.Models.EntityBase
/// Indicates that the entity had been changed and the changes were committed
/// </summary>
/// <returns></returns>
public bool WasDirty()
public virtual bool WasDirty()
{
return _lastPropertyChangedInfo != null && _lastPropertyChangedInfo.Any();
}
@@ -4,6 +4,7 @@ using System.Configuration.Provider;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.Security;
@@ -893,5 +894,15 @@ namespace Umbraco.Core.Security
return sb.ToString();
}
/// <summary>
/// Returns the current request IP address for logging if there is one
/// </summary>
/// <returns></returns>
protected string GetCurrentRequestIpAddress()
{
var httpContext = HttpContext.Current == null ? (HttpContextBase) null : new HttpContextWrapper(HttpContext.Current);
return httpContext.GetCurrentRequestIpAddress();
}
}
}
+81 -1
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Cache;
using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
@@ -19,12 +20,13 @@ namespace Umbraco.Core.Services
private readonly IMediaService _mediaService;
private readonly IMemberService _memberService;
private readonly IMemberTypeService _memberTypeService;
private readonly IRuntimeCacheProvider _runtimeCache;
private readonly IDataTypeService _dataTypeService;
private readonly Dictionary<string, Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>> _supportedObjectTypes;
public EntityService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory,
IContentService contentService, IContentTypeService contentTypeService, IMediaService mediaService, IDataTypeService dataTypeService,
IMemberService memberService, IMemberTypeService memberTypeService)
IMemberService memberService, IMemberTypeService memberTypeService, IRuntimeCacheProvider runtimeCache)
{
_uowProvider = provider;
_repositoryFactory = repositoryFactory;
@@ -34,6 +36,7 @@ namespace Umbraco.Core.Services
_dataTypeService = dataTypeService;
_memberService = memberService;
_memberTypeService = memberTypeService;
_runtimeCache = runtimeCache;
_supportedObjectTypes = new Dictionary<string, Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>>
{
@@ -45,6 +48,83 @@ namespace Umbraco.Core.Services
{typeof (IMember).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.Member, _memberService.GetById)},
{typeof (IMemberType).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.MemberType, _memberTypeService.Get)}
};
}
/// <summary>
/// Returns the integer id for a given GUID
/// </summary>
/// <param name="key"></param>
/// <param name="umbracoObjectType"></param>
/// <returns></returns>
public Attempt<int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType)
{
var result = _runtimeCache.GetCacheItem<int?>(CacheKeys.IdToKeyCacheKey + key, () =>
{
using (var uow = _uowProvider.GetUnitOfWork())
{
switch (umbracoObjectType)
{
case UmbracoObjectTypes.Document:
case UmbracoObjectTypes.MemberType:
case UmbracoObjectTypes.Media:
case UmbracoObjectTypes.Template:
case UmbracoObjectTypes.MediaType:
case UmbracoObjectTypes.DocumentType:
case UmbracoObjectTypes.Member:
case UmbracoObjectTypes.DataType:
return uow.Database.ExecuteScalar<int?>(new Sql().Select("id").From<NodeDto>().Where<NodeDto>(dto => dto.UniqueId == key));
case UmbracoObjectTypes.RecycleBin:
case UmbracoObjectTypes.Stylesheet:
case UmbracoObjectTypes.MemberGroup:
case UmbracoObjectTypes.ContentItem:
case UmbracoObjectTypes.ContentItemType:
case UmbracoObjectTypes.ROOT:
case UmbracoObjectTypes.Unknown:
default:
throw new NotSupportedException();
}
}
});
return result.HasValue ? Attempt.Succeed(result.Value) : Attempt<int>.Fail();
}
/// <summary>
/// Returns the GUID for a given integer id
/// </summary>
/// <param name="id"></param>
/// <param name="umbracoObjectType"></param>
/// <returns></returns>
public Attempt<Guid> GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType)
{
var result = _runtimeCache.GetCacheItem<Guid?>(CacheKeys.KeyToIdCacheKey + id, () =>
{
using (var uow = _uowProvider.GetUnitOfWork())
{
switch (umbracoObjectType)
{
case UmbracoObjectTypes.Document:
case UmbracoObjectTypes.MemberType:
case UmbracoObjectTypes.Media:
case UmbracoObjectTypes.Template:
case UmbracoObjectTypes.MediaType:
case UmbracoObjectTypes.DocumentType:
case UmbracoObjectTypes.Member:
case UmbracoObjectTypes.DataType:
return uow.Database.ExecuteScalar<Guid?>(new Sql().Select("uniqueID").From<NodeDto>().Where<NodeDto>(dto => dto.NodeId == id));
case UmbracoObjectTypes.RecycleBin:
case UmbracoObjectTypes.Stylesheet:
case UmbracoObjectTypes.MemberGroup:
case UmbracoObjectTypes.ContentItem:
case UmbracoObjectTypes.ContentItemType:
case UmbracoObjectTypes.ROOT:
case UmbracoObjectTypes.Unknown:
default:
throw new NotSupportedException();
}
}
});
return result.HasValue ? Attempt.Succeed(result.Value) : Attempt<Guid>.Fail();
}
public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true)
@@ -7,6 +7,21 @@ namespace Umbraco.Core.Services
{
public interface IEntityService
{
/// <summary>
/// Returns the integer id for a given GUID
/// </summary>
/// <param name="key"></param>
/// <param name="umbracoObjectType"></param>
/// <returns></returns>
Attempt<int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType);
/// <summary>
/// Returns the GUID for a given integer id
/// </summary>
/// <param name="id"></param>
/// <param name="umbracoObjectType"></param>
/// <returns></returns>
Attempt<Guid> GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType);
/// <summary>
/// Gets an UmbracoEntity by its Id, and optionally loads the complete object graph.
@@ -85,14 +85,14 @@ namespace Umbraco.Core.Services
}
//get the lazy value from cache
result.Add(culture, new Lazy<XDocument>(() => _cache.GetCacheItem<XDocument>(
string.Format("{0}-{1}", typeof(LocalizedTextServiceFileSources).Name, culture.Name), () =>
result[culture] = new Lazy<XDocument>(() => _cache.GetCacheItem<XDocument>(
string.Format("{0}-{1}", typeof (LocalizedTextServiceFileSources).Name, culture.Name), () =>
{
using (var fs = localCopy.OpenRead())
{
return XDocument.Load(fs);
}
}, isSliding: true, timeout: TimeSpan.FromMinutes(10), dependentFiles: new[] { localCopy.FullName })));
}, isSliding: true, timeout: TimeSpan.FromMinutes(10), dependentFiles: new[] {localCopy.FullName}));
}
return result;
});
+2 -1
View File
@@ -167,7 +167,8 @@ namespace Umbraco.Core.Services
if (_entityService == null)
_entityService = new Lazy<IEntityService>(() => new EntityService(
provider, repositoryFactory.Value,
_contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value, _memberService.Value, _memberTypeService.Value));
_contentService.Value, _contentTypeService.Value, _mediaService.Value, _dataTypeService.Value, _memberService.Value, _memberTypeService.Value,
cache.RuntimeCache));
if (_relationService == null)
_relationService = new Lazy<IRelationService>(() => new RelationService(provider, repositoryFactory.Value, _entityService.Value));
+27 -2
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Events;
@@ -207,6 +208,9 @@ namespace Umbraco.Core.Services
}
}
//TODO: Remove this in 7.3, we need to track this in a db column!
private readonly ConcurrentDictionary<int, int> _failedLoginAttempts = new ConcurrentDictionary<int, int>();
/// <summary>
/// Get an <see cref="IUser"/> by username
/// </summary>
@@ -217,7 +221,18 @@ namespace Umbraco.Core.Services
using (var repository = _repositoryFactory.CreateUserRepository(_uowProvider.GetUnitOfWork()))
{
var query = Query<IUser>.Builder.Where(x => x.Username.Equals(username));
return repository.GetByQuery(query).FirstOrDefault();
var user = repository.GetByQuery(query).FirstOrDefault();
if (user != null)
{
//check if they have any failed logins and merge
int failedAttempts;
if (_failedLoginAttempts.TryGetValue(user.Id, out failedAttempts))
{
user.FailedPasswordAttempts = failedAttempts;
}
}
return user;
}
}
@@ -284,6 +299,9 @@ namespace Umbraco.Core.Services
}
else
{
int failedAttempts;
_failedLoginAttempts.TryRemove(user.Id, out failedAttempts);
if (DeletingUser.IsRaisedEventCancelled(new DeleteEventArgs<IUser>(user), this))
return;
@@ -317,6 +335,8 @@ namespace Umbraco.Core.Services
{
repository.AddOrUpdate(entity);
uow.Commit();
_failedLoginAttempts.AddOrUpdate(entity.Id, i => entity.FailedPasswordAttempts, (i, i1) => entity.FailedPasswordAttempts);
}
if (raiseEvents)
@@ -342,10 +362,15 @@ namespace Umbraco.Core.Services
{
foreach (var member in entities)
{
repository.AddOrUpdate(member);
repository.AddOrUpdate(member);
}
//commit the whole lot in one go
uow.Commit();
foreach (var member in entities)
{
_failedLoginAttempts.AddOrUpdate(member.Id, i => member.FailedPasswordAttempts, (i, i1) => member.FailedPasswordAttempts);
}
}
if (raiseEvents)
+3 -1
View File
@@ -64,7 +64,7 @@
</Reference>
<Reference Include="MySql.Data">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll</HintPath>
<HintPath>..\packages\MySql.Data.6.9.6\lib\net45\MySql.Data.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -313,6 +313,7 @@
<Compile Include="Events\SendToPublishEventArgs.cs" />
<Compile Include="Exceptions\InvalidCompositionException.cs" />
<Compile Include="HideFromTypeFinderAttribute.cs" />
<Compile Include="HttpContextExtensions.cs" />
<Compile Include="IApplicationEventHandler.cs" />
<Compile Include="IDisposeOnRequestEnd.cs" />
<Compile Include="Manifest\GridEditorConverter.cs" />
@@ -1216,6 +1217,7 @@
<Compile Include="WriteLock.cs" />
<Compile Include="XmlExtensions.cs" />
<Compile Include="XmlHelper.cs" />
<Compile Include="Xml\UmbracoXPathPathSyntaxParser.cs" />
<Compile Include="Xml\XPath\MacroNavigator.cs" />
<Compile Include="Xml\XPath\INavigableContentType.cs" />
<Compile Include="Xml\XPath\NavigableNavigator.cs" />
@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Core.Xml
{
/// <summary>
/// This is used to parse our customize Umbraco XPath expressions (i.e. that include special tokens like $site) into
/// a real XPath statement
/// </summary>
internal class UmbracoXPathPathSyntaxParser
{
/// <summary>
/// Parses custom umbraco xpath expression
/// </summary>
/// <param name="xpathExpression">The Xpath expression</param>
/// <param name="nodeContextId">
/// The current node id context of executing the query - null if there is no current node, in which case
/// some of the parameters like $current, $parent, $site will be disabled
/// </param>
/// <param name="getPath">The callback to create the nodeId path, given a node Id</param>
/// <param name="publishedContentExists">The callback to return whether a published node exists based on Id</param>
/// <returns></returns>
public static string ParseXPathQuery(
string xpathExpression,
int? nodeContextId,
Func<int, IEnumerable<string>> getPath,
Func<int, bool> publishedContentExists)
{
//TODO: This should probably support some of the old syntax and token replacements, currently
// it does not, there is a ticket raised here about it: http://issues.umbraco.org/issue/U4-6364
// previous tokens were: "$currentPage", "$ancestorOrSelf", "$parentPage" and I beleive they were
// allowed 'inline', not just at the beginning... whether or not we want to support that is up
// for discussion.
Mandate.ParameterNotNullOrEmpty(xpathExpression, "xpathExpression");
Mandate.ParameterNotNull(getPath, "getPath");
Mandate.ParameterNotNull(publishedContentExists, "publishedContentExists");
//no need to parse it
if (xpathExpression.StartsWith("$") == false)
return xpathExpression;
//get nearest published item
Func<IEnumerable<string>, int> getClosestPublishedAncestor = (path =>
{
foreach (var i in path)
{
int idAsInt;
if (int.TryParse(i, out idAsInt))
{
var exists = publishedContentExists(int.Parse(i));
if (exists)
return idAsInt;
}
}
return -1;
});
const string rootXpath = "descendant::*[@id={0}]";
//parseable items:
var vars = new Dictionary<string, Func<string, string>>();
//These parameters must have a node id context
if (nodeContextId.HasValue)
{
vars.Add("$current", q =>
{
var closestPublishedAncestorId = getClosestPublishedAncestor(getPath(nodeContextId.Value));
return q.Replace("$current", string.Format(rootXpath, closestPublishedAncestorId));
});
vars.Add("$parent", q =>
{
//remove the first item in the array if its the current node
//this happens when current is published, but we are looking for its parent specifically
var path = getPath(nodeContextId.Value).ToArray();
if (path[0] == nodeContextId.ToString())
{
path = path.Skip(1).ToArray();
}
var closestPublishedAncestorId = getClosestPublishedAncestor(path);
return q.Replace("$parent", string.Format(rootXpath, closestPublishedAncestorId));
});
vars.Add("$site", q =>
{
var closestPublishedAncestorId = getClosestPublishedAncestor(getPath(nodeContextId.Value));
return q.Replace("$site", string.Format(rootXpath, closestPublishedAncestorId) + "/ancestor-or-self::*[@level = 1]");
});
}
//TODO: This used to just replace $root with string.Empty BUT, that would never work
// the root is always "/root . Need to confirm with Per why this was string.Empty before!
vars.Add("$root", q => q.Replace("$root", "/root"));
foreach (var varible in vars)
{
if (xpathExpression.StartsWith(varible.Key))
{
xpathExpression = varible.Value(xpathExpression);
break;
}
}
return xpathExpression;
}
}
}
+16 -16
View File
@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.0.0" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net45" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net40" />
<package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="2.0.30506.0" targetFramework="net40" />
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.22" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" />
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
<package id="MySql.Data" version="6.6.5" targetFramework="net40" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net40" />
<package id="AutoMapper" version="3.0.0" targetFramework="net45" userInstalled="true" />
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net45" userInstalled="true" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net4" userInstalled="true" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net4" userInstalled="true" />
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net4" userInstalled="true" />
<package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.AspNet.WebPages" version="2.0.30506.0" targetFramework="net4" userInstalled="true" />
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.Net.Http" version="2.2.22" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net4" userInstalled="true" />
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" userInstalled="true" />
<package id="MySql.Data" version="6.9.6" targetFramework="net45" userInstalled="true" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" userInstalled="true" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net4" userInstalled="true" />
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net4" userInstalled="true" />
</packages>
@@ -28,10 +28,16 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings
Assert.IsTrue(SettingsSection.Content.Error404Collection.Count() == 3);
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(0).Culture == "default");
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(0).ContentId == 1047);
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(0).HasContentId);
Assert.IsFalse(SettingsSection.Content.Error404Collection.ElementAt(0).HasContentKey);
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(1).Culture == "en-US");
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(1).ContentId == 1048);
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(1).ContentXPath == "$site/error [@name = 'error']");
Assert.IsFalse(SettingsSection.Content.Error404Collection.ElementAt(1).HasContentId);
Assert.IsFalse(SettingsSection.Content.Error404Collection.ElementAt(1).HasContentKey);
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(2).Culture == "en-UK");
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(2).ContentId == 1049);
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(2).ContentKey == new Guid("8560867F-B88F-4C74-A9A4-679D8E5B3BFC"));
Assert.IsTrue(SettingsSection.Content.Error404Collection.ElementAt(2).HasContentKey);
Assert.IsFalse(SettingsSection.Content.Error404Collection.ElementAt(2).HasContentId);
}
[Test]
@@ -42,8 +42,8 @@
</error404>-->
<error404>
<errorPage culture="default">1047</errorPage>
<errorPage culture="en-US">1048</errorPage>
<errorPage culture="en-UK">1049</errorPage>
<errorPage culture="en-US">$site/error [@name = 'error']</errorPage>
<errorPage culture="en-UK">8560867F-B88F-4C74-A9A4-679D8E5B3BFC</errorPage>
</error404>
<!--<error404>1</error404>-->
</errors>
+31
View File
@@ -701,6 +701,37 @@ namespace Umbraco.Tests.Models
Assert.That(contentType.WasPropertyDirty("Alias"), Is.True);
}
[Test]
public void After_Committing_Changes_Was_Dirty_Is_True_On_Changed_Property()
{
// Arrange
var contentType = MockedContentTypes.CreateTextpageContentType();
contentType.ResetDirtyProperties(); //reset
var content = MockedContent.CreateTextpageContent(contentType, "test", -1);
content.ResetDirtyProperties();
// Act
content.SetPropertyValue("title", "new title");
Assert.That(content.IsEntityDirty(), Is.False);
Assert.That(content.IsDirty(), Is.True);
Assert.That(content.IsPropertyDirty("title"), Is.True);
Assert.That(content.IsAnyUserPropertyDirty(), Is.True);
Assert.That(content.GetDirtyUserProperties().Count(), Is.EqualTo(1));
Assert.That(content.Properties[0].IsDirty(), Is.True);
Assert.That(content.Properties["title"].IsDirty(), Is.True);
content.ResetDirtyProperties(); //this would be like committing the entity
// Assert
Assert.That(content.WasDirty(), Is.True);
Assert.That(content.Properties[0].WasDirty(), Is.True);
Assert.That(content.WasPropertyDirty("title"), Is.True);
Assert.That(content.Properties["title"].IsDirty(), Is.False);
Assert.That(content.Properties["title"].WasDirty(), Is.True);
}
[Test]
public void If_Not_Committed_Was_Dirty_Is_False()
{
+2 -2
View File
@@ -58,9 +58,9 @@
<Reference Include="AutoMapper.Net4">
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=0.1.62.2941, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="Examine, Version=0.1.63.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Examine.0.1.62.2941\lib\Examine.dll</HintPath>
<HintPath>..\packages\Examine.0.1.63.0\lib\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
+1 -1
View File
@@ -2,7 +2,7 @@
<packages>
<package id="AspNetWebApi.SelfHost" version="4.0.20710.0" targetFramework="net45" />
<package id="AutoMapper" version="3.0.0" targetFramework="net45" />
<package id="Examine" version="0.1.62.2941" targetFramework="net45" />
<package id="Examine" version="0.1.63.0" targetFramework="net45" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
@@ -229,7 +229,7 @@ textarea {
.radio input[type="radio"],
.checkbox input[type="checkbox"] {
float: left;
margin-left: -20px;
margin-left: 0px;
}
// Move the options list down to align with labels
@@ -22,6 +22,9 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
if (scope.showTray) {
return 'slide';
}
else if (scope.showTray === false) {
return 'slide';
}
else {
return '';
}
@@ -49,26 +52,35 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
}
});
}
//Listen for global state changes
eventsService.on("appState.globalState.changed", function (e, args) {
if (args.key === "showTray") {
scope.showTray = args.value;
}
if (args.key === "stickyNavigation") {
scope.stickyNavigation = args.value;
}
});
eventsService.on("appState.sectionState.changed", function (e, args) {
if (args.key === "currentSection") {
scope.currentSection = args.value;
}
});
eventsService.on("app.reInitialize", function (e, args) {
var evts = [];
//Listen for global state changes
evts.push(eventsService.on("appState.globalState.changed", function(e, args) {
if (args.key === "showTray") {
scope.showTray = args.value;
}
if (args.key === "stickyNavigation") {
scope.stickyNavigation = args.value;
}
}));
evts.push(eventsService.on("appState.sectionState.changed", function(e, args) {
if (args.key === "currentSection") {
scope.currentSection = args.value;
}
}));
evts.push(eventsService.on("app.reInitialize", function(e, args) {
//re-load the sections if we're re-initializing (i.e. package installed)
loadSections();
loadSections();
}));
//ensure to unregister from all events!
scope.$on('$destroy', function () {
for (var e in evts) {
eventsService.unsubscribe(evts[e]);
}
});
//on page resize
@@ -83,6 +95,13 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
};
scope.sectionClick = function (section) {
if (navigationService.userDialog) {
navigationService.userDialog.close();
}
if (navigationService.helpDialog) {
navigationService.helpDialog.close();
}
navigationService.hideSearch();
navigationService.showTree(section.alias);
$location.path("/" + section.alias);
@@ -92,8 +111,20 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
navigationService.reloadSection(section.alias);
};
scope.trayClick = function(){
navigationService.showTray();
scope.trayClick = function () {
// close dialogs
if (navigationService.userDialog) {
navigationService.userDialog.close();
}
if (navigationService.helpDialog) {
navigationService.helpDialog.close();
}
if (appState.getGlobalState("showTray") === true) {
navigationService.hideTray();
} else {
navigationService.showTray();
}
};
loadSections();
@@ -48,27 +48,29 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not
element.addClass(className);
}
var unsubscribe = [];
//listen for the forms saving event
scope.$on(savingEventName, function (ev, args) {
unsubscribe.push(scope.$on(savingEventName, function(ev, args) {
element.addClass(className);
//set the flag so we can check to see if we should display the error.
isSavingNewItem = $routeParams.create;
});
}));
//listen for the forms saved event
scope.$on(savedEvent, function (ev, args) {
unsubscribe.push(scope.$on(savedEvent, function(ev, args) {
//remove validation class
element.removeClass(className);
//clear form state as at this point we retrieve new data from the server
//and all validation will have cleared at this point
formCtrl.$setPristine();
});
}));
//This handles the 'unsaved changes' dialog which is triggered when a route is attempting to be changed but
// the form has pending changes
var locationEvent = $rootScope.$on('$locationChangeStart', function(event, nextLocation, currentLocation) {
unsubscribe.push($rootScope.$on('$locationChangeStart', function(event, nextLocation, currentLocation) {
if (!formCtrl.$dirty || isSavingNewItem) {
return;
}
@@ -91,11 +93,11 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not
eventsService.emit("valFormManager.pendingChanges", true);
}
});
}));
//Ensure to remove the event handler when this instance is destroyted
scope.$on('$destroy', function() {
if(locationEvent){
locationEvent();
for (var u in unsubscribe) {
unsubscribe[u]();
}
});
@@ -96,8 +96,10 @@ function valPropertyMsg(serverValidationManager) {
//create properties on our custom scope so we can use it in our template
scope.errorMsg = "";
var unsubscribe = [];
//listen for form error changes
scope.$on("valStatusChanged", function (evt, args) {
unsubscribe.push(scope.$on("valStatusChanged", function(evt, args) {
if (args.form.$invalid) {
//first we need to check if the valPropertyMsg validity is invalid
@@ -123,10 +125,10 @@ function valPropertyMsg(serverValidationManager) {
hasError = false;
scope.errorMsg = "";
}
}, true);
}, true));
//listen for the forms saving event
scope.$on("formSubmitting", function (ev, args) {
unsubscribe.push(scope.$on("formSubmitting", function(ev, args) {
showValidation = true;
if (hasError && scope.errorMsg === "") {
scope.errorMsg = getErrorMsg();
@@ -135,15 +137,15 @@ function valPropertyMsg(serverValidationManager) {
scope.errorMsg = "";
stopWatch();
}
});
}));
//listen for the forms saved event
scope.$on("formSubmitted", function (ev, args) {
unsubscribe.push(scope.$on("formSubmitted", function(ev, args) {
showValidation = false;
scope.errorMsg = "";
formCtrl.$setValidity('valPropertyMsg', true);
stopWatch();
});
}));
//listen for server validation changes
// NOTE: we pass in "" in order to listen for all validation changes to the content property, not for
@@ -179,7 +181,16 @@ function valPropertyMsg(serverValidationManager) {
serverValidationManager.unsubscribe(scope.property.alias, "");
});
}
//when the scope is disposed we need to unsubscribe
scope.$on('$destroy', function () {
for (var u in unsubscribe) {
unsubscribe[u]();
}
});
}
};
}
angular.module('umbraco.directives.validation').directive("valPropertyMsg", valPropertyMsg);
@@ -43,8 +43,10 @@ function valToggleMsg(serverValidationManager) {
}
});
var unsubscribe = [];
//listen for the saving event (the result is a callback method which is called to unsubscribe)
var unsubscribeSaving = scope.$on("formSubmitting", function (ev, args) {
unsubscribe.push(scope.$on("formSubmitting", function(ev, args) {
showValidation = true;
if (formCtrl[attr.valMsgFor].$error[attr.valToggleMsg]) {
element.show();
@@ -56,20 +58,21 @@ function valToggleMsg(serverValidationManager) {
else {
element.hide();
}
});
}));
//listen for the saved event (the result is a callback method which is called to unsubscribe)
var unsubscribeSaved = scope.$on("formSubmitted", function (ev, args) {
unsubscribe.push(scope.$on("formSubmitted", function(ev, args) {
showValidation = false;
element.hide();
});
}));
//when the element is disposed we need to unsubscribe!
// NOTE: this is very important otherwise if this directive is part of a modal, the listener still exists because the dom
// element might still be there even after the modal has been hidden.
element.bind('$destroy', function () {
unsubscribeSaving();
unsubscribeSaved();
for (var u in unsubscribe) {
unsubscribe[u]();
}
});
}
@@ -537,6 +537,13 @@ angular.module('umbraco.services')
template: 'views/common/dialogs/ysod.html',
show: true
});
},
confirmDialog: function (ysodError) {
options.template = 'views/common/dialogs/confirm.html';
options.show = true;
return openDialog(options);
}
};
});
@@ -513,23 +513,26 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
* Opens the user dialog, next to the sections navigation
* template is located in views/common/dialogs/user.html
*/
showUserDialog: function() {
showUserDialog: function () {
// hide tray and close help dialog
if (service.helpDialog) {
service.helpDialog.close();
}
service.hideTray();
if(userDialog){
userDialog.close();
userDialog = null;
if (service.userDialog) {
service.userDialog.close();
service.userDialog = undefined;
}
userDialog = dialogService.open(
{
template: "views/common/dialogs/user.html",
modalClass: "umb-modal-left",
show: true
});
service.userDialog = dialogService.open(
{
template: "views/common/dialogs/user.html",
modalClass: "umb-modal-left",
show: true
});
return userDialog;
return service.userDialog;
},
/**
@@ -541,7 +544,13 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
* Opens the user dialog, next to the sections navigation
* template is located in views/common/dialogs/user.html
*/
showHelpDialog: function() {
showHelpDialog: function () {
// hide tray and close user dialog
service.hideTray();
if (service.userDialog) {
service.userDialog.close();
}
if(service.helpDialog){
service.helpDialog.close();
service.helpDialog = undefined;
@@ -206,7 +206,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
},
/** builds an image grid row */
buildRow: function(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin) {
buildRow: function(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, totalRemaining) {
var currRowWidth = 0;
var row = { images: [] };
@@ -253,8 +253,8 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
this.setImageStyle(row.images[j], sizes[j].width, sizes[j].height, margin, bottomMargin);
}
if (row.images.length === 1) {
//if there's only one image on the row, set the container to max width
if (row.images.length === 1 && totalRemaining > 1) {
//if there's only one image on the row and there are more images remaining, set the container to max width
row.images[0].style.width = maxRowWidth + "px";
}
@@ -278,7 +278,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
buildGrid: function(images, maxRowWidth, maxRowHeight, startingIndex, minDisplayHeight, idealImgPerRow, margin,imagesOnly) {
var rows = [];
var imagesProcessed = 0;
var imagesProcessed = 0;
//first fill in all of the original image sizes and URLs
for (var i = startingIndex; i < images.length; i++) {
@@ -298,7 +298,8 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
var currImgs = images.slice(imagesProcessed);
//build the row
var row = this.buildRow(currImgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin);
var remaining = images.length - imagesProcessed;
var row = this.buildRow(currImgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, remaining);
if (row.images.length > 0) {
rows.push(row);
imagesProcessed += row.images.length;
@@ -48,14 +48,16 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $
eventsService.emit("app.closeDialogs", event);
};
var evts = [];
//when a user logs out or timesout
eventsService.on("app.notAuthenticated", function() {
evts.push(eventsService.on("app.notAuthenticated", function() {
$scope.authenticated = null;
$scope.user = null;
});
}));
//when the app is read/user is logged in, setup the data
eventsService.on("app.ready", function (evt, data) {
evts.push(eventsService.on("app.ready", function (evt, data) {
$scope.authenticated = data.authenticated;
$scope.user = data.user;
@@ -73,7 +75,7 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $
notificationsService.add(notification);
}
}
});
})
//if the user has changed we need to redirect to the root so they don't try to continue editing the
//last item in the URL (NOTE: the user id can equal zero, so we cannot just do !data.lastUserId since that will resolve to true)
@@ -104,6 +106,13 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $
}, 3000);
}
}));
//ensure to unregister from all events!
$scope.$on('$destroy', function () {
for (var e in evts) {
eventsService.unsubscribe(evts[e]);
}
});
}
@@ -47,15 +47,17 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
$scope.selectedId = navigationService.currentId;
var evts = [];
//Listen for global state changes
eventsService.on("appState.globalState.changed", function (e, args) {
evts.push(eventsService.on("appState.globalState.changed", function(e, args) {
if (args.key === "showNavigation") {
$scope.showNavigation = args.value;
}
});
}));
//Listen for menu state changes
eventsService.on("appState.menuState.changed", function (e, args) {
evts.push(eventsService.on("appState.menuState.changed", function(e, args) {
if (args.key === "showMenuDialog") {
$scope.showContextMenuDialog = args.value;
}
@@ -71,20 +73,21 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
if (args.key === "currentNode") {
$scope.menuNode = args.value;
}
});
}));
//Listen for section state changes
eventsService.on("appState.treeState.changed", function (e, args) {
evts.push(eventsService.on("appState.treeState.changed", function(e, args) {
var f = args;
if (args.value.root && args.value.root.metaData.containsTrees === false) {
$rootScope.emptySection = true;
}else{
}
else {
$rootScope.emptySection = false;
}
});
}));
//Listen for section state changes
eventsService.on("appState.sectionState.changed", function (e, args) {
evts.push(eventsService.on("appState.sectionState.changed", function(e, args) {
//section changed
if (args.key === "currentSection") {
$scope.currentSection = args.value;
@@ -93,26 +96,26 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
if (args.key === "showSearchResults") {
$scope.showSearchResults = args.value;
}
});
}));
//This reacts to clicks passed to the body element which emits a global call to close all dialogs
eventsService.on("app.closeDialogs", function (event) {
evts.push(eventsService.on("app.closeDialogs", function(event) {
if (appState.getGlobalState("stickyNavigation")) {
navigationService.hideNavigation();
//TODO: don't know why we need this? - we are inside of an angular event listener.
angularHelper.safeApply($scope);
}
});
}));
//when a user logs out or timesout
eventsService.on("app.notAuthenticated", function () {
evts.push(eventsService.on("app.notAuthenticated", function() {
$scope.authenticated = false;
});
}));
//when the application is ready and the user is authorized setup the data
eventsService.on("app.ready", function (evt, data) {
evts.push(eventsService.on("app.ready", function(evt, data) {
$scope.authenticated = true;
});
}));
//this reacts to the options item in the tree
//todo, migrate to nav service
@@ -151,6 +154,13 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
}, 300);
}
};
//ensure to unregister from all events!
$scope.$on('$destroy', function () {
for (var e in evts) {
eventsService.unsubscribe(evts[e]);
}
});
}
//register it
+15 -3
View File
@@ -2,7 +2,6 @@
app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', 'editorState', 'fileManager', 'assetsService', 'eventsService', '$cookies', '$templateCache',
function (userService, $log, $rootScope, $location, navigationService, appState, editorState, fileManager, assetsService, eventsService, $cookies, $templateCache) {
//This sets the default jquery ajax headers to include our csrf token, we
// need to user the beforeSend method because our token changes per user/login so
// it cannot be static
@@ -16,8 +15,10 @@ app.run(['userService', '$log', '$rootScope', '$location', 'navigationService',
eventsService.on("app.authenticated", function(evt, data) {
assetsService._loadInitAssets().then(function() {
appState.setGlobalState("isReady", true);
//send the ready event
//send the ready event with the included returnToPath,returnToSearch data
eventsService.emit("app.ready", data);
returnToPath = null, returnToSearch = null;
});
});
@@ -44,7 +45,18 @@ app.run(['userService', '$log', '$rootScope', '$location', 'navigationService',
wiring up it's controller, etc... and then redirect to the rejected URL. */
$rootScope.$on('$routeChangeError', function(event, current, previous, rejection) {
event.preventDefault();
$location.path(rejection.path).search(rejection.search);
var returnPath = null;
if (rejection.path == "/login" || rejection.path.startsWith("/login/")) {
//Set the current path before redirecting so we know where to redirect back to
returnPath = encodeURIComponent($location.url());
}
$location.path(rejection.path)
if (returnPath) {
$location.search("returnPath", returnPath);
}
});
@@ -305,7 +305,8 @@ textarea {
.radio input[type="radio"],
.checkbox input[type="checkbox"] {
float: left;
margin-left: -20px;
margin-left: 0px;
margin-right:5px;
}
// Move the options list down to align with labels
@@ -63,6 +63,7 @@
.umb-modal-left .umb-panel-header .umb-headline, .umb-modal-left .umb-panel-header h1 {
width: auto;
padding-left: 0;
}
/* umb.dialog is used for the dialogs on the conent tree*/
@@ -48,6 +48,7 @@
background: none;
margin: 15px 0 0 20px;
padding: 3px 5px;
line-height: 1.4;
height: auto;
width: 100%;
border: 1px solid @grayLighter;
@@ -91,7 +92,7 @@
margin: -6px 0 0 0;
padding: 0 0 2px 0;
border-radius: 0;
line-height: 1em;
line-height: normal;
border: 1px solid transparent;
color: @black;
letter-spacing: -0.01em
@@ -25,7 +25,7 @@
}
.umb-codeeditor{
width: 99%;
width: 99%;
}
//
@@ -68,7 +68,7 @@ div.umb-codeeditor .umb-btn-toolbar {
.mce-ico{font-size: 12px !important; color: @blackLight !important;}
/* Special case to support helviticons for the tiny mce button controls */
.mce-ico.mce-i-custom[class^="icon-"],
.mce-ico.mce-i-custom[class*=" icon-"] {
.mce-ico.mce-i-custom[class*=" icon-"] {
font-family: icomoon;
font-size:16px !important;
}
@@ -100,8 +100,8 @@ ul.color-picker li a {
/* pre-value editor */
.control-group.color-picker-preval pre {
display: inline;
margin-right: 20px;
display: inline;
margin-right: 20px;
margin-left: 10px;
}
@@ -116,8 +116,8 @@ ul.color-picker li a {
// --------------------------------------------------
.umb-mediapicker .add-link{
display: inline-block;
height: 120px;
width: 120px;
height: 120px;
width: 120px;
text-align: center;
color: @grayLight;
border: 2px @grayLight dashed !important;
@@ -187,7 +187,7 @@ ul.color-picker li a {
.umb-sortable-thumbnails li img
{
max-width:100%;
max-width:100%;
max-height:100%;
margin:auto;
display:block;
@@ -206,12 +206,12 @@ ul.color-picker li a {
.umb-sortable-thumbnails .icon-holder *
{
color: @grayLight;
display: block
display: block
}
//
// Cropper
// Cropper
// -------------------------------------------------
.umb-cropper{
@@ -237,7 +237,7 @@ ul.color-picker li a {
position: relative;
margin: auto;
}
.umb-cropper-gravity .viewport{
overflow: hidden;
position: relative;
@@ -301,15 +301,15 @@ ul.color-picker li a {
// --------------------------------------------------
.umb-folderbrowser .add-link{
display: inline-block;
height: 120px;
width: 120px;
height: 120px;
width: 120px;
text-align: center;
border: 1px @grayLight dashed;
line-height: 120px
}
.umb-folderbrowser .selector-overlay{
display: none !important;
display: none;
}
.umb-upload-drop-zone{
@@ -368,7 +368,7 @@ ul.color-picker li a {
.umb-photo-folder .picrow div a:first-child {
.umb-photo-folder .picrow div a:first-child {
width:100%;
height:100%;
}
@@ -382,7 +382,7 @@ ul.color-picker li a {
.umb-photo-folder a:hover{text-decoration: none}
.umb-photo-folder .umb-non-thumbnail{
text-align: center;
vertical-align: center;
vertical-align: middle;
font-size: 12px;
background: @grayLighter;
color: @black;
@@ -390,7 +390,7 @@ ul.color-picker li a {
}
//this is a temp hack, to provide selectors in the dialog:
.umb-photo-folder .pic:hover .selector-overlay{
.umb-photo-folder .pic:hover .selector-overlay {
position: absolute;
bottom: 0px;
left: 0px;
@@ -402,6 +402,11 @@ ul.color-picker li a {
text-align: center;
color: white;
opacity: 0.4;
text-decoration:none;
overflow: hidden;
text-overlow: ellipsis;
white-space: nowrap;
}
.umb-photo-folder .umb-non-thumbnail i{
@@ -410,7 +415,10 @@ ul.color-picker li a {
line-height: 60px;
display: block;
margin: auto;
padding-top: 20px;
/*vertically aligns */
position: relative;
top: 50%;
transform: translateY(-50%);
}
.umb-photo-folder .selected{
@@ -505,4 +513,4 @@ ul.color-picker li a {
// --------------------------------------------------
.bootstrap-datetimepicker-widget .btn{padding: 0;}
.bootstrap-datetimepicker-widget .picker-switch .btn{ background: none; border: none;}
.umb-datepicker .input-append .add-on{cursor: pointer;}
.umb-datepicker .input-append .add-on{cursor: pointer;}
@@ -7,6 +7,7 @@ ul.sections {
background: @blackLight;
height: 100%;
width: 80px;
border-right: 1px solid @grayDark;
}
ul.sections li {
@@ -42,6 +43,7 @@ ul.sections li a {
width: 100%;
height: 100%;
margin: 0 0 0 -4px;
cursor: pointer; // make sure IE10 displays pointer cursor for expand and help sections.
}
ul.sections a span {
@@ -63,7 +65,7 @@ ul.sections:hover a span {
// -------------------------
ul.sections li.avatar {
height: 69px;
height: 67px;
padding: 30px 0 2px 0;
text-align: center;
margin: 0 0 0 -4px;
@@ -116,7 +118,38 @@ ul.sections li.help a {
// -------------------------
li.expand a, li.expand{border: none !Important;}
ul.sections-tray {
padding-top: 102px;
width: 80px;
li.expand {
&.open > a > i.icon {
-webkit-transition: all 1s !important;
-o-transition: all 1s !important;
-moz-transition: all 1s !important;
transition: all 1s !important;
&:before {
-ms-transform: rotate(180deg) !important; /* IE 9 */
-webkit-transform: rotate(180deg) !important; /* Chrome, Safari, Opera */
-o-transform: rotate(180deg) !important;
-moz-transform: rotate(180deg) !important;
transform: rotate(180deg) !important;
}
}
}
ul.sections-tray {
padding-top: 99px;
width: 80px;
& > li:first-child > a {
border-top: 1px solid #343434;
}
& > li {
// 5px (instead of 4px) because of vertical border
border-left-width: 5px;
&.current, &:hover {
border-left-width: 5px;
}
}
}
@@ -35,7 +35,7 @@ angular.module("umbraco")
});
helpService.findVideos(rq).then(function(videos){
$scope.videos = videos;
$scope.videos = videos;
});
});
@@ -37,7 +37,7 @@
<li class="span2" ng-repeat="video in videos">
<div class="thumbnail" style="margin-right: 20px">
<a target="_blank" href="{{video.link}}?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=tv" title="{{video.title}}">
<img ng-src="{{video.thumbnail}}" alt="{{video.title}}">
<img ng-src="{{video.thumbnail}}" alt="{{video.title}}">
</a>
</div>
</li>
@@ -73,7 +73,7 @@ function InsertMacroController($scope, entityResource, macroResource, umbPropEdi
var val = item.value;
if (!_.isString(item.value)) {
if (item.value != null && item.value != undefined && !_.isString(item.value)) {
try {
val = angular.toJson(val);
}
@@ -5,14 +5,14 @@ angular.module("umbraco")
$scope.history = historyService.getCurrent();
$scope.version = Umbraco.Sys.ServerVariables.application.version + " assembly: " + Umbraco.Sys.ServerVariables.application.assemblyVersion;
var evtHandlers = [];
evtHandlers.push(eventsService.on("historyService.add", function (e, args) {
var evts = [];
evts.push(eventsService.on("historyService.add", function (e, args) {
$scope.history = args.all;
}));
evtHandlers.push(eventsService.on("historyService.remove", function (e, args) {
evts.push(eventsService.on("historyService.remove", function (e, args) {
$scope.history = args.all;
}));
evtHandlers.push(eventsService.on("historyService.removeAll", function (e, args) {
evts.push(eventsService.on("historyService.removeAll", function (e, args) {
$scope.history = [];
}));
@@ -62,8 +62,8 @@ angular.module("umbraco")
//remove all event handlers
$scope.$on('$destroy', function () {
for (var i = 0; i < evtHandlers.length; i++) {
evtHandlers[i]();
for (var e = 0; e < evts.length; e++) {
evts[e]();
}
});
@@ -1,10 +1,24 @@
/** This controller is simply here to launch the login dialog when the route is explicitly changed to /login */
angular.module('umbraco').controller("Umbraco.LoginController", function (eventsService, $scope, userService, $location) {
angular.module('umbraco').controller("Umbraco.LoginController", function (eventsService, $scope, userService, $location, $rootScope) {
userService._showLoginDialog();
eventsService.on("app.ready", function(){
$scope.avatar = "assets/img/application/logo.png";
$location.path("/").search("");
var evtOn = eventsService.on("app.ready", function(evt, data){
$scope.avatar = "assets/img/application/logo.png";
var path = "/";
//check if there's a returnPath query string, if so redirect to it
var locationObj = $location.search();
if (locationObj.returnPath) {
path = decodeURIComponent(locationObj.returnPath);
}
$location.url(path);
});
});
$scope.$on('$destroy', function () {
eventsService.unsubscribe(evtOn);
});
});
@@ -12,14 +12,17 @@
<div ng-style="img.style" class="umb-non-thumbnail" ng-if="!img.thumbnail">
<i class="icon large {{img.icon}}"></i>
{{img.name}}
</div>
<div ng-if="img.thumbnail" class="umb-photo" ng-style="img.thumbStyle" alt="{{img.name}}">
</div>
<div ng-if="img.thumbnail" class="umb-photo" ng-style="img.thumbStyle" alt="{{img.name}}"></div>
</a>
<a href ng-click="clickHandler(img, $event, true)"
ng-if="img.isFolder" class="selector-overlay">
<localize key="buttons_select">Select</localize>
<a href ng-click="clickHandler(img, $event, true)" class="selector-overlay">
<localize key="buttons_select" ng-if="img.isFolder">Select</localize>
<span ng-if="!img.isFolder">{{img.name}}</span>
</a>
</div>
</div>
@@ -16,7 +16,7 @@
</a>
</li>
<li class="expand" ng-show="needTray">
<li class="expand" ng-class="{ 'open': showTray === true }" ng-show="needTray">
<a href ng-click="trayClick()">
<i class="icon icon-arrow-right"></i>
</a>
@@ -49,13 +49,18 @@ function mediaPickerController($scope, dialogService, entityResource, $log, icon
}
};
$scope.$on("formSubmitting", function (ev, args) {
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
var currIds = _.map($scope.renderModel, function (i) {
return i.id;
});
$scope.model.value = trim(currIds.join(), ",");
});
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
unsubscribe();
});
//load media data
var modelIds = $scope.model.value ? $scope.model.value.split(',') : [];
entityResource.getByIds(modelIds, dialogOptions.entityType).then(function (data) {
@@ -58,10 +58,15 @@ angular.module('umbraco')
};
$scope.$on("formSubmitting", function (ev, args) {
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
$scope.model.value = trim($scope.ids.join(), ",");
});
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
unsubscribe();
});
function trim(str, chr) {
var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^'+chr+'+|'+chr+'+$', 'g');
return str.replace(rgxtrim, '');
@@ -43,13 +43,18 @@ angular.module('umbraco')
//we always need to ensure we dont submit anything broken
$scope.$on("formSubmitting", function (ev, args) {
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
if($scope.model.value.type === "member"){
$scope.model.value.id = -1;
$scope.model.value.query = "";
}
});
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
unsubscribe();
});
function populate(item){
$scope.clear();
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
@@ -91,15 +91,17 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont
//set model to null
$scope.model.value = null;
};
var unsubscribe = [];
//listen for the saved event, when that occurs we'll
//change to changing = false;
$scope.$on("formSubmitted", function () {
unsubscribe.push($scope.$on("formSubmitted", function() {
if ($scope.model.config.disableToggle === false) {
$scope.changing = false;
}
});
$scope.$on("formSubmitting", function() {
}
}));
unsubscribe.push($scope.$on("formSubmitting", function() {
//if there was a previously generated password displaying, clear it
if ($scope.changing && $scope.model.value) {
$scope.model.value.generatedPassword = null;
@@ -108,6 +110,13 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont
//we are not changing, so the model needs to be null
$scope.model.value = null;
}
}));
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
for (var u in unsubscribe) {
unsubscribe[u]();
}
});
$scope.showReset = function() {
@@ -53,7 +53,7 @@ function contentPickerController($scope, dialogService, entityResource, editorSt
startNode: {
query: "",
type: "content",
id: -1
id: $scope.model.config.startNodeId ? $scope.model.config.startNodeId : -1 // get start node for simple Content Picker
}
};
@@ -158,13 +158,18 @@ function contentPickerController($scope, dialogService, entityResource, editorSt
$scope.renderModel = [];
};
$scope.$on("formSubmitting", function (ev, args) {
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
var currIds = _.map($scope.renderModel, function (i) {
return i.id;
});
$scope.model.value = trim(currIds.join(), ",");
});
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
unsubscribe();
});
//load current data
var modelIds = $scope.model.value ? $scope.model.value.split(',') : [];
entityResource.getByIds(modelIds, entityType).then(function (data) {
@@ -1,79 +1,97 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.GridPrevalueEditor.RowConfigController",
function ($scope) {
function RowConfigController($scope) {
$scope.currentRow = angular.copy($scope.dialogOptions.currentRow);
$scope.editors = $scope.dialogOptions.editors;
$scope.columns = $scope.dialogOptions.columns;
$scope.currentRow = $scope.dialogOptions.currentRow;
$scope.editors = $scope.dialogOptions.editors;
$scope.columns = $scope.dialogOptions.columns;
$scope.scaleUp = function(section, max, overflow) {
var add = 1;
if (overflow !== true) {
add = (max > 1) ? 1 : max;
}
//var add = (max > 1) ? 1 : max;
section.grid = section.grid + add;
};
$scope.scaleUp = function(section, max, overflow){
var add = 1;
if(overflow !== true){
add = (max > 1) ? 1 : max;
}
//var add = (max > 1) ? 1 : max;
section.grid = section.grid+add;
};
$scope.scaleDown = function(section) {
var remove = (section.grid > 1) ? 1 : section.grid;
section.grid = section.grid - remove;
};
$scope.scaleDown = function(section){
var remove = (section.grid > 1) ? 1 : section.grid;
section.grid = section.grid-remove;
};
$scope.percentage = function(spans) {
return ((spans / $scope.columns) * 100).toFixed(1);
};
$scope.percentage = function(spans){
return ((spans / $scope.columns) * 100).toFixed(1);
};
$scope.toggleCollection = function(collection, toggle){
if(toggle){
collection = [];
}else{
delete collection;
}
};
$scope.toggleCollection = function(collection, toggle) {
if (toggle) {
collection = [];
}
else {
delete collection;
}
};
/****************
area
*****************/
$scope.configureCell = function(cell, row){
if($scope.currentCell && $scope.currentCell=== cell){
delete $scope.currentCell;
}else{
if(cell === undefined){
var available = $scope.availableRowSpace;
var space = 4;
/****************
area
*****************/
$scope.configureCell = function(cell, row) {
if ($scope.currentCell && $scope.currentCell === cell) {
delete $scope.currentCell;
}
else {
if (cell === undefined) {
var available = $scope.availableRowSpace;
var space = 4;
if(available < 4 && available > 0){
space = available;
}
cell = {
grid: space
};
row.areas.push(cell);
}
$scope.currentCell = cell;
if (available < 4 && available > 0) {
space = available;
}
};
$scope.deleteArea = function(index){
$scope.currentRow.areas.splice(index, 1);
};
$scope.closeArea = function(){
$scope.currentCell = undefined;
};
cell = {
grid: space
};
row.areas.push(cell);
}
$scope.currentCell = cell;
}
};
$scope.$watch("currentRow", function(row){
if(row){
var total = 0;
_.forEach(row.areas, function(area){
total = (total + area.grid);
});
$scope.deleteArea = function(index) {
$scope.currentRow.areas.splice(index, 1);
};
$scope.closeArea = function() {
$scope.currentCell = undefined;
};
$scope.availableRowSpace = $scope.columns - total;
}
}, true);
});
$scope.nameChanged = false;
var originalName = $scope.currentRow.name;
$scope.$watch("currentRow", function(row) {
if (row) {
var total = 0;
_.forEach(row.areas, function(area) {
total = (total + area.grid);
});
$scope.availableRowSpace = $scope.columns - total;
if (originalName) {
if (originalName != row.name) {
$scope.nameChanged = true;
}
else {
$scope.nameChanged = false;
}
}
}
}, true);
$scope.complete = function () {
angular.extend($scope.dialogOptions.currentRow, $scope.currentRow);
$scope.close();
}
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.GridPrevalueEditor.RowConfigController", RowConfigController);
@@ -1,11 +1,17 @@
<div class="umb-panel usky-grid usky-grid-configuration"
ng-controller="Umbraco.PropertyEditors.GridPrevalueEditor.RowConfigController">
<div class="umb-panel-body no-header with-footer">
<div class="umb-forms-settings">
<h5><localize key="grid_addRowConfiguration" /></h5>
<p><localize key="grid_addRowConfigurationDetail" /></p>
<div class="alert alert-warn ng-scope" ng-show="nameChanged">
Modifying a row configuration name will result in loss of
data for any existing content that is based on this configuration.
</div>
<umb-control-group label="@general_name">
<input type="text" ng-model="currentRow.name" />
</umb-control-group>
@@ -83,7 +89,11 @@ ng-controller="Umbraco.PropertyEditors.GridPrevalueEditor.RowConfigController">
<div class="umb-panel-footer">
<div class="umb-el-wrap umb-panel-buttons">
<div class="btn-toolbar umb-btn-toolbar pull-right">
<a href="" ng-click="close()" class="btn btn-primary">
<a href ng-click="close()" class="btn btn-link">
<localize key="general_cancel">Cancel</localize>
</a>
<a href ng-click="complete()" class="btn btn-primary">
<localize key="general_ok" class="ng-isolate-scope ng-scope">Done</localize>
</a>
</div>
@@ -0,0 +1,26 @@
<div>
<div class="umb-panel-body no-header with-footer compact">
<umb-pane>
<h3 class="alert alert-warn ng-scope">Warning!</h3>
<p>
You are deleting the row configuration '<strong>{{dialogData.rowName}}</strong>'
</p>
<p>
Modifying a row configuration name will result in loss of
data for any existing content that is based on this configuration.
</p>
<p>
<localize key="general_areyousure">Are you sure?</localize>
</p>
</umb-pane>
</div>
<div class="umb-panel-footer">
<umb-confirm on-confirm="submit" on-cancel="close">
</umb-confirm>
</div>
</div>
@@ -14,6 +14,8 @@ angular.module("umbraco")
// Sortable options
// *********************************************
var draggedRteSettings;
$scope.sortableOptions = {
distance: 10,
cursor: "move",
@@ -40,15 +42,22 @@ angular.module("umbraco")
},
start: function (e, ui) {
draggedRteSettings = {};
ui.item.find('.mceNoEditor').each(function () {
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
// remove all RTEs in the dragged row and save their settings
var id = $(this).attr('id');
draggedRteSettings[id] = _.findWhere(tinyMCE.editors, { id: id }).settings;
tinyMCE.execCommand('mceRemoveEditor', false, id);
});
},
stop: function (e, ui) {
// reset all RTEs affected by the dragging
ui.item.parents(".usky-column").find('.mceNoEditor').each(function () {
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
tinyMCE.execCommand('mceAddEditor', false, $(this).attr('id'));
var id = $(this).attr('id');
draggedRteSettings[id] = draggedRteSettings[id] || _.findWhere(tinyMCE.editors, { id: id }).settings;
tinyMCE.execCommand('mceRemoveEditor', false, id);
tinyMCE.init(draggedRteSettings[id]);
});
}
};
@@ -98,6 +107,7 @@ angular.module("umbraco")
},
update: function (event, ui) {
// add all RTEs which are affected by the dragging
if (!ui.sender) {
if (cancelMove) {
ui.item.sortable.cancel();
@@ -121,6 +131,11 @@ angular.module("umbraco")
start: function (e, ui) {
ui.item.find('.mceNoEditor').each(function () {
notIncludedRte = [];
// save the dragged RTE settings
draggedRteSettings = _.findWhere(tinyMCE.editors, { id: $(this).attr('id') }).settings;
// remove the dragged RTE
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
});
},
@@ -128,14 +143,21 @@ angular.module("umbraco")
stop: function (e, ui) {
ui.item.parents(".usky-cell").find('.mceNoEditor').each(function () {
if ($.inArray($(this).attr('id'), notIncludedRte) < 0) {
// add all dragged's neighbouring RTEs in the new cell
notIncludedRte.splice(0, 0, $(this).attr('id'));
}
});
$timeout(function () {
// reconstruct the dragged RTE
tinyMCE.init(draggedRteSettings);
_.forEach(notIncludedRte, function (id) {
tinyMCE.execCommand('mceRemoveEditor', false, id);
tinyMCE.execCommand('mceAddEditor', false, id);
console.info("stop " + id);
// reset all the other RTEs
if (id != draggedRteSettings.id) {
var rteSettings = _.findWhere(tinyMCE.editors, { id: id }).settings;
tinyMCE.execCommand('mceRemoveEditor', false, id);
tinyMCE.init(rteSettings);
}
});
}, 500, false);
}
@@ -127,9 +127,24 @@ angular.module("umbraco")
);
};
//var rowDeletesPending = false;
$scope.deleteLayout = function (index) {
//rowDeletesPending = true;
$scope.deleteLayout = function(index){
$scope.model.value.layouts.splice(index, 1);
//show ok/cancel dialog
var confirmDialog = dialogService.open(
{
template: "views/propertyEditors/grid/dialogs/rowdeleteconfirm.html",
show: true,
callback: function() {
$scope.model.value.layouts.splice(index, 1);
},
dialogData: {
rowName: $scope.model.value.layouts[index].name
}
}
);
};
@@ -216,7 +231,7 @@ angular.module("umbraco")
/****************
Clean up
*****************/
$scope.$on("formSubmitting", function (ev, args) {
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
var ts = $scope.model.value.templates;
var ls = $scope.model.value.layouts;
@@ -237,4 +252,9 @@ angular.module("umbraco")
});
});
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
unsubscribe();
});
});
@@ -1,8 +1,8 @@
<div class="umb-editor">
<input name="integerField" type="number" class="umb-editor umb-number"
<input name="integerField" type="number" class="umb-editor umb-number "
ng-model="model.value"
val-server="value"
fix-number />
fix-number min="{{model.config.min}}" max="{{model.config.max}}" step="{{model.config.step}}" />
<span class="help-inline" val-msg-for="integerField" val-toggle-msg="number">Not a number</span>
<span class="help-inline" val-msg-for="integerField" val-toggle-msg="valServer">{{propertyForm.requiredField.errorMsg}}</span>
@@ -50,14 +50,14 @@
<td>
<a href="#" ng-click="sort('Name', true)" prevent-default class="sortable">
<localize key="general_name">Name</localize>
<i class="icon" ng-class="{'icon-navigation-down': isSortDirection('Name', 'asc'), 'icon-navigation-up': isSortDirection('Name', 'desc')}"></i>
<i class="icon" ng-class="{'icon-navigation-up': isSortDirection('Name', 'asc'), 'icon-navigation-down': isSortDirection('Name', 'desc')}"></i>
</a>
</td>
<td ng-repeat="column in options.includeProperties">
<a href="#" ng-click="sort(column.alias, column.allowSorting)" ng-class="{'sortable':column.allowSorting}" prevent-default>
<span ng-bind="column.header"></span>
<i class="icon" ng-class="{'icon-navigation-down': isSortDirection(column.alias, 'asc'), 'icon-navigation-up': isSortDirection(column.alias, 'desc')}"></i>
<i class="icon" ng-class="{'icon-navigation-up': isSortDirection(column.alias, 'asc'), 'icon-navigation-down': isSortDirection(column.alias, 'desc')}"></i>
</a>
</td>
@@ -85,7 +85,7 @@ angular.module('umbraco')
$scope.renderModel = [];
};
$scope.$on("formSubmitting", function (ev, args) {
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
var syntax = [];
angular.forEach($scope.renderModel, function(value, key){
syntax.push(value.syntax);
@@ -94,6 +94,11 @@ angular.module('umbraco')
$scope.model.value = syntax.join("");
});
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
unsubscribe();
});
function trim(str, chr) {
var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^'+chr+'+|'+chr+'+$', 'g');
@@ -1,7 +1,5 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.MarkdownEditorController",
//inject umbracos assetsServce and dialog service
function ($scope, assetsService, dialogService, $timeout) {
function MarkdownEditorController($scope, assetsService, dialogService, $timeout) {
//tell the assets service to load the markdown.editor libs from the markdown editors
//plugin folder
@@ -11,36 +9,41 @@ function ($scope, assetsService, dialogService, $timeout) {
}
assetsService
.load([
"lib/markdown/markdown.converter.js",
.load([
"lib/markdown/markdown.converter.js",
"lib/markdown/markdown.sanitizer.js",
"lib/markdown/markdown.editor.js"
])
.then(function () {
//this function will execute when all dependencies have loaded
// but in the case that they've been previously loaded, we can only
// init the md editor after this digest because the DOM needs to be ready first
// so run the init on a timeout
$timeout(function() {
var converter2 = new Markdown.Converter();
var editor2 = new Markdown.Editor(converter2, "-" + $scope.model.alias);
editor2.run();
.then(function () {
//subscribe to the image dialog clicks
editor2.hooks.set("insertImageDialog", function (callback) {
// we need a short delay to wait for the textbox to appear.
setTimeout(function () {
//this function will execute when all dependencies have loaded
// but in the case that they've been previously loaded, we can only
// init the md editor after this digest because the DOM needs to be ready first
// so run the init on a timeout
$timeout(function () {
var converter2 = new Markdown.Converter();
var editor2 = new Markdown.Editor(converter2, "-" + $scope.model.alias);
editor2.run();
dialogService.mediaPicker({
callback: function (data) {
callback(data.image);
}
//subscribe to the image dialog clicks
editor2.hooks.set("insertImageDialog", function (callback) {
dialogService.mediaPicker({
callback: function (data) {
callback(data.image);
}
});
return true; // tell the editor that we'll take care of getting the image url
});
return true; // tell the editor that we'll take care of getting the image url
});
}, 200);
});
});
//load the seperat css for the editor to avoid it blocking our js loading TEMP HACK
assetsService.loadCss("lib/markdown/markdown.css");
});
//load the seperat css for the editor to avoid it blocking our js loading TEMP HACK
assetsService.loadCss("lib/markdown/markdown.css");
})
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.MarkdownEditorController", MarkdownEditorController);
@@ -65,13 +65,18 @@ function memberGroupPicker($scope, dialogService){
$scope.renderModel = [];
};
$scope.$on("formSubmitting", function (ev, args) {
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
var currIds = _.map($scope.renderModel, function (i) {
return i.id;
});
$scope.model.value = trim(currIds.join(), ",");
});
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
unsubscribe();
});
}
angular.module('umbraco').controller("Umbraco.PropertyEditors.MemberGroupPickerController", memberGroupPicker);
@@ -60,13 +60,18 @@ function memberPickerController($scope, dialogService, entityResource, $log, ico
$scope.renderModel = [];
};
$scope.$on("formSubmitting", function (ev, args) {
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
var currIds = _.map($scope.renderModel, function (i) {
return i.id;
});
$scope.model.value = trim(currIds.join(), ",");
});
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
unsubscribe();
});
//load member data
var modelIds = $scope.model.value ? $scope.model.value.split(',') : [];
entityResource.getByIds(modelIds, "Member").then(function (data) {
@@ -1,5 +1,13 @@
function MultipleTextBoxController($scope) {
$scope.sortableOptions = {
axis: 'y',
containment: 'parent',
cursor: 'move',
items: '> div.control-group',
tolerance: 'pointer'
};
if (!$scope.model.value) {
$scope.model.value = [];
}
@@ -1,17 +1,20 @@
<div class="umb-editor umb-multiple-textbox" ng-controller="Umbraco.PropertyEditors.MultipleTextBoxController">
<div class="control-group" ng-repeat="item in model.value">
<input type="text" name="item_{{$index}}" ng-model="item.value" class="umb-editor" />
<a prevent-default href="" title="Remove this text box"
ng-show="model.value.length > model.config.min"
ng-click="remove($index)">
<i class="icon icon-remove"></i>
</a>
<div ui-sortable="sortableOptions" ng-model="model.value">
<div class="control-group" ng-repeat="item in model.value">
<i class="icon icon-navigation handle"></i>
<input type="text" name="item_{{$index}}" ng-model="item.value" class="umb-editor" />
<a prevent-default href="" title="Remove this text box"
ng-show="model.value.length > model.config.min"
ng-click="remove($index)">
<i class="icon icon-remove"></i>
</a>
</div>
</div>
<a prevent-default href="" title="Add another text box"
ng-show="model.config.max <= 0 || model.value.length < model.config.max"
ng-click="add()">
ng-show="model.config.max <= 0 || model.value.length < model.config.max"
ng-click="add()">
<i class="icon icon-add"></i>
</a>
</div>
</div>
@@ -58,12 +58,16 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController",
}
};
$scope.$on("formSubmitting", function (ev, args) {
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
var commands = _.where($scope.tinyMceConfig.commands, {selected: true});
$scope.model.value.toolbar = _.pluck(commands, "frontEndCommand");
});
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
unsubscribe();
});
});
+8 -14
View File
@@ -84,9 +84,8 @@
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
<DocumentationFile>bin\Umbraco.Web.UI.XML</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
@@ -96,7 +95,7 @@
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>none</DebugType>
<DebugType>pdbonly</DebugType>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
@@ -127,9 +126,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\dotless.1.4.1.0\lib\dotless.Core.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=0.1.62.2941, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Examine.0.1.62.2941\lib\Examine.dll</HintPath>
<Reference Include="Examine">
<HintPath>..\packages\Examine.0.1.63.0\lib\Examine.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -152,12 +151,6 @@
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.165\lib\net45\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.165\lib\net45\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
@@ -172,7 +165,7 @@
</Reference>
<Reference Include="MySql.Data">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll</HintPath>
<HintPath>..\packages\MySql.Data.6.9.6\lib\net45\MySql.Data.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -2070,6 +2063,7 @@
<Content Include="Umbraco\PartialViewMacros\Templates\Navigation.cshtml" />
<Content Include="Umbraco\PartialViewMacros\Templates\SiteMap.cshtml" />
<Content Include="Umbraco\Views\AuthorizeUpgrade.cshtml" />
<Content Include="Umbraco\Translation\translationTasks.dtd" />
<None Include="Umbraco_client\CodeMirror\js\mode\coffeescript\LICENSE" />
<None Include="Umbraco_client\CodeMirror\js\mode\pascal\LICENSE" />
<None Include="Umbraco_client\CodeMirror\js\mode\perl\LICENSE" />
@@ -12,6 +12,12 @@
<errors>
<error404>1</error404>
<!--
The value for error pages can be:
* A content item's integer ID (example: 1234)
* A content item's GUID ID (example: 26C1D84F-C900-4D53-B167-E25CC489DAC8)
* An XPath statement (example: //errorPages[@nodeName='My cool error']
-->
<!--
<error404>
<errorPage culture="default">1</errorPage>
+25 -26
View File
@@ -1,29 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.0.0" targetFramework="net45" />
<package id="ClientDependency" version="1.8.3.1" targetFramework="net45" />
<package id="ClientDependency-Mvc" version="1.8.0.0" targetFramework="net45" />
<package id="dotless" version="1.4.1.0" targetFramework="net45" />
<package id="Examine" version="0.1.62.2941" targetFramework="net45" />
<package id="ImageProcessor" version="1.9.5.0" targetFramework="net45" />
<package id="ImageProcessor.Web" version="3.3.1.0" targetFramework="net45" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
<package id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.1" targetFramework="net40" />
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net40" />
<package id="Microsoft.AspNet.WebApi" version="4.0.30506.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="4.0.30506.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="4.0.30506.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="2.0.30506.0" targetFramework="net40" />
<package id="Microsoft.Bcl.Async" version="1.0.165" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
<package id="MySql.Data" version="6.6.5" targetFramework="net40" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net40" />
<package id="UrlRewritingNet.UrlRewriter" version="2.0.60829.1" targetFramework="net40" />
<package id="AutoMapper" version="3.0.0" targetFramework="net45" userInstalled="true" />
<package id="ClientDependency" version="1.8.3.1" targetFramework="net45" userInstalled="true" />
<package id="ClientDependency-Mvc" version="1.8.0.0" targetFramework="net45" userInstalled="true" />
<package id="dotless" version="1.4.1.0" targetFramework="net45" userInstalled="true" />
<package id="Examine" version="0.1.63.0" targetFramework="net45" />
<package id="ImageProcessor" version="1.9.5.0" targetFramework="net45" userInstalled="true" />
<package id="ImageProcessor.Web" version="3.3.1.0" targetFramework="net45" userInstalled="true" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net4" userInstalled="true" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net4" userInstalled="true" />
<package id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.1" targetFramework="net4" userInstalled="true" />
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net4" userInstalled="true" />
<package id="Microsoft.AspNet.WebApi" version="4.0.30506.0" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.AspNet.WebApi.Core" version="4.0.30506.0" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="4.0.30506.0" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.AspNet.WebPages" version="2.0.30506.0" targetFramework="net4" userInstalled="true" />
<package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net45" userInstalled="true" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" userInstalled="true" />
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" userInstalled="true" />
<package id="MySql.Data" version="6.9.6" targetFramework="net45" userInstalled="true" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" userInstalled="true" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" userInstalled="true" />
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net4" userInstalled="true" />
<package id="UrlRewritingNet.UrlRewriter" version="2.0.60829.1" targetFramework="net4" userInstalled="true" />
</packages>
@@ -781,7 +781,7 @@ das Dokument '%1%' wurde von '%2%' zur Übersetzung in '%5%' freigegeben.
Zum Bearbeiten verwenden Sie bitte diesen Link: http://%3%/translation/details.aspx?id=%4%.
Sie können sich auch alle anstehenden Übersetzungen gesammelt im Umbraco-Verwaltungsbereich anzeigen lassen: http://%3%/Umbraco/Umbraco.aspx
Sie können sich auch alle anstehenden Übersetzungen gesammelt im Umbraco-Verwaltungsbereich anzeigen lassen: http://%3%/Umbraco.aspx
Einen schönen Tag wünscht
Ihr freundlicher Umbraco-Robot
@@ -244,8 +244,8 @@
<key alias="nameentity">Name the %0%...</key>
<key alias="entername">Enter a name...</key>
<key alias="search">Type to search...</key>
<key alias="filter">Type to filter...</key>
<key alias="enterTags">Type to add tags (press enter after each tag)...</key>
<key alias="filter">Type to filter...</key>
<key alias="enterTags">Type to add tags (press enter after each tag)...</key>
</area>
<area alias="editcontenttype">
<key alias="allowAtRoot" version="7.2">Allow at root</key>
@@ -679,9 +679,11 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="paSimpleHelp">If you just want to setup simple protection using a single login and password</key>
</area>
<area alias="publish">
<key alias="contentPublishedFailedAwaitingRelease"><![CDATA[
<key alias="contentPublishedFailedAwaitingRelease">
<![CDATA[
%0% could not be published because the item is scheduled for release.
]]></key>
]]>
</key>
<key alias="contentPublishedFailedInvalid"><![CDATA[
%0% could not be published because these properties: %1% did not pass validation rules.
]]></key>
@@ -44,16 +44,16 @@
<key alias="invalidNode">Invalid node.</key>
<key alias="invalidDomain">Invalid domain format.</key>
<key alias="duplicateDomain">Domain has already been assigned.</key>
<key alias="domain">Domain</key>
<key alias="language">Language</key>
<key alias="domain">Domain</key>
<key alias="domainCreated">New domain '%0%' has been created</key>
<key alias="domainDeleted">Domain '%0%' is deleted</key>
<key alias="domainExists">Domain '%0%' has already been assigned</key>
<key alias="domainUpdated">Domain '%0%' has been updated</key>
<key alias="orEdit">Edit Current Domains</key>
<key alias="domainHelp"><![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
"https://www.example.com/".<br /><br />One-level paths in domains are supported, eg. "example.com/en". However, they
should be avoided. Better use the culture setting above.]]></key>
<key alias="domainUpdated">Domain '%0%' has been updated</key>
<key alias="orEdit">Edit Current Domains</key>
<key alias="inherit">Inherit</key>
<key alias="setLanguage">Culture</key>
<key alias="setLanguageHelp"><![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
@@ -63,8 +63,6 @@
<area alias="auditTrails">
<key alias="atViewingFor">Viewing for</key>
</area>
<area alias="buttons">
<key alias="select">Select</key>
<key alias="selectCurrentFolder">Select current folder</key>
@@ -134,7 +132,7 @@
<key alias="itemChanged">This item has been changed after publication</key>
<key alias="itemNotPublished">This item is not published</key>
<key alias="lastPublished">Last published</key>
<key alias="listViewNoItems" version="7.1.5">There are no items show in the list.</key>
<key alias="listViewNoItems" version="7.1.5">There are no items to show in the list.</key>
<key alias="mediatype">Media Type</key>
<key alias="mediaLinks">Link to media item(s)</key>
<key alias="membergroup">Member Group</key>
@@ -162,8 +160,7 @@
<key alias="uploadClear">Remove file(s)</key>
<key alias="urls">Link to document</key>
<key alias="memberof">Member of group(s)</key>
<key alias="notmemberof">Not a member of group(s)</key>
<key alias="notmemberof">Not a member of group(s)</key>
<key alias="childItems" version="7.0">Child items</key>
<key alias="target" version="7.0">Target</key>
</area>
@@ -175,9 +172,7 @@
<key alias="chooseNode">Where do you want to create the new %0%</key>
<key alias="createUnder">Create an item under</key>
<key alias="updateData">Choose a type and a title</key>
<key alias="noDocumentTypes" version="7.0"><![CDATA[There are no allowed document types available. You must enable these in the settings section under <strong>"document types"</strong>.]]></key>
<key alias="noMediaTypes" version="7.0"><![CDATA[There are no allowed media types available. You must enable these in the settings section under <strong>"media types"</strong>.]]></key>
</area>
<area alias="dashboard">
@@ -250,6 +245,7 @@
<key alias="entername">Enter a name...</key>
<key alias="search">Type to search...</key>
<key alias="filter">Type to filter...</key>
<key alias="enterTags">Type to add tags (press enter after each tag)...</key>
</area>
<area alias="editcontenttype">
@@ -412,7 +408,6 @@
<key alias="width">Width</key>
<key alias="yes">Yes</key>
<key alias="folder">Folder</key>
<key alias="searchResults">Search results</key>
</area>
<area alias="graphicheadline">
@@ -560,11 +555,9 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="greeting4">Happy thunderous Thursday</key>
<key alias="greeting5">Happy funky Friday</key>
<key alias="greeting6">Happy Caturday</key>
<key alias="instruction">log in below</key>
<key alias="instruction">Log in below</key>
<key alias="timeout">Session timed out</key>
<key alias="bottomText"><![CDATA[<p style="text-align:right;">&copy; 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">Umbraco.com</a></p> ]]></key>
<key alias="bottomText"><![CDATA[<p style="text-align:right;">&copy; 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">Umbraco.com</a></p> ]]></key>
</area>
<area alias="main">
<key alias="dashboard">Dashboard</key>
@@ -715,16 +708,16 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="noColors">You have not configured any approved colors</key>
</area>
<area alias="relatedlinks">
<key alias="addExternal">Add external link</key>
<key alias="addInternal">Add internal link</key>
<key alias="addlink">Add</key>
<key alias="enterExternal">enter external link</key>
<key alias="chooseInternal">choose internal page</key>
<key alias="caption">Caption</key>
<key alias="internalPage">Internal page</key>
<key alias="linkurl">URL</key>
<key alias="modeDown">Move Down</key>
<key alias="modeUp">Move Up</key>
<key alias="link">Link</key>
<key alias="newWindow">Open in new window</key>
<key alias="removeLink">Remove link</key>
<key alias="captionPlaceholder">enter the display caption</key>
<key alias="externalLinkPlaceholder">Enter the link</key>
</area>
<area alias="imagecropper">
<key alias="reset">Reset</key>
</area>
<area alias="rollback">
<key alias="currentVersion">Current version</key>
@@ -751,8 +744,8 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="statistics">Statistics</key>
<key alias="translation">Translation</key>
<key alias="users">Users</key>
<key alias="help" version="7.0">Help</key>
<key alias="forms">Forms</key>
<key alias="analytics">Analytics</key>
</area>
<area alias="settings">
@@ -859,6 +852,10 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="addRows">Add rows to your layout</key>
<key alias="addElement"><![CDATA[To start, click the <i class="icon icon-add blue"></i> below and add your first element]]></key>
<key alias="clickToEmbed">Click to embed</key>
<key alias="clickToInsertImage">Click to insert image</key>
<key alias="placeholderImageCaption">Image caption...</key>
<key alias="placeholderWriteHere">Write here...</key>
<key alias="gridLayouts">Grid layouts</key>
<key alias="gridLayoutsDetail">Layouts are the overall work area for the grid editor, usually you only need one or two different layouts</key>
<key alias="addGridLayout">Add grid layout</key>
@@ -1032,12 +1029,11 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="permissionSelectPages">Select pages to modify their permissions</key>
<key alias="searchAllChildren">Search all children</key>
<key alias="startnode">Start Node in Content</key>
<key alias="username">Username</key>
<key alias="username">Name</key>
<key alias="userPermissions">User permissions</key>
<key alias="usertype">User type</key>
<key alias="userTypes">User types</key>
<key alias="writer">Writer</key>
<key alias="yourProfile" version="7.0">Your profile</key>
<key alias="yourHistory" version="7.0">Your recent history</key>
<key alias="sessionExpires" version="7.0">Session expires in</key>
+2 -2
View File
@@ -132,14 +132,14 @@
xdt:Locator="Condition(_defaultNamespace:assemblyIdentity[@name='System.Web.Mvc']])" />
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
<bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Remove"
xdt:Locator="Condition(_defaultNamespace:assemblyIdentity[@name='System.Net.Http']])"/>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Net.Http" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
</dependentAssembly>
<dependentAssembly xdt:Transform="Remove"
@@ -183,7 +183,10 @@ namespace Umbraco.Web.Cache
private static void ClearContentTypeCache(JsonPayload[] payloads)
{
var needsContentRefresh = false;
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
payloads.ForEach(payload =>
{
//clear the cache for each item
@@ -271,7 +274,7 @@ namespace Umbraco.Web.Cache
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(string.Format("{0}{1}", CacheKeys.ContentTypeCacheKey, payload.Id));
//clears the cache associated with the content type properties collection
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(CacheKeys.ContentTypePropertiesCacheKey + payload.Id);
//clears the dictionary object cache of the legacy ContentType
global::umbraco.cms.businesslogic.ContentType.RemoveFromDataTypeCache(payload.Alias);
@@ -120,11 +120,13 @@ namespace Umbraco.Web.Cache
// db data type to store the value against and anytime a datatype changes, this also might change
// we basically need to clear all sorts of runtime caches here because so many things depend upon a data type
RuntimeCacheProvider.Current.Clear(typeof(IContent));
RuntimeCacheProvider.Current.Clear(typeof (IContentType));
RuntimeCacheProvider.Current.Clear(typeof(IContentType));
RuntimeCacheProvider.Current.Clear(typeof(IMedia));
RuntimeCacheProvider.Current.Clear(typeof(IMediaType));
RuntimeCacheProvider.Current.Clear(typeof(IMember));
RuntimeCacheProvider.Current.Clear(typeof(IMemberType));
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
payloads.ForEach(payload =>
{
@@ -152,6 +152,8 @@ namespace Umbraco.Web.Cache
{
if (payloads == null) return;
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
ApplicationContext.Current.ApplicationCache.ClearPartialViewCache();
payloads.ForEach(payload =>
@@ -58,6 +58,8 @@ namespace Umbraco.Web.Cache
private void ClearCache(int id)
{
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
ApplicationContext.Current.ApplicationCache.ClearPartialViewCache();
ApplicationContext.Current.ApplicationCache.
@@ -52,6 +52,9 @@ namespace Umbraco.Web.Cache
private void RemoveFromCache(int id)
{
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
ApplicationContext.Current.ApplicationCache.ClearCacheItem(
string.Format("{0}{1}", CacheKeys.TemplateFrontEndCacheKey, id));
@@ -21,6 +21,7 @@ using Umbraco.Web.Security;
using Umbraco.Web.WebApi;
using Umbraco.Web.WebApi.Filters;
using umbraco.providers;
using Umbraco.Core.Logging;
namespace Umbraco.Web.Editors
{
@@ -102,30 +103,29 @@ namespace Umbraco.Web.Editors
[SetAngularAntiForgeryTokens]
public UserDetail PostLogin(LoginModel loginModel)
{
var http = this.TryGetHttpContext();
if (http.Success == false)
throw new InvalidOperationException("This method requires that an HttpContext be active");
if (UmbracoContext.Security.ValidateBackOfficeCredentials(loginModel.Username, loginModel.Password))
{
var user = Security.GetBackOfficeUser(loginModel.Username);
//TODO: Clean up the int cast!
var ticket = UmbracoContext.Security.PerformLogin(user);
var http = this.TryGetHttpContext();
if (http.Success == false)
{
throw new InvalidOperationException("This method requires that an HttpContext be active");
}
http.Result.AuthenticateCurrentRequest(ticket, false);
var result = Mapper.Map<UserDetail>(user);
//set their remaining seconds
result.SecondsUntilTimeout = ticket.GetRemainingAuthSeconds();
return result;
}
//return BadRequest (400), we don't want to return a 401 because that get's intercepted
// by our angular helper because it thinks that we need to re-perform the request once we are
// authorized and we don't want to return a 403 because angular will show a warning msg indicating
// that the user doesn't have access to perform this function, we just want to return a normal invalid msg.
// that the user doesn't have access to perform this function, we just want to return a normal invalid msg.
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
@@ -141,5 +141,6 @@ namespace Umbraco.Web.Editors
{
return Request.CreateResponse(HttpStatusCode.OK);
}
}
}
+154 -148
View File
@@ -189,170 +189,176 @@ namespace Umbraco.Web.Editors
[MinifyJavaScriptResult(Order = 1)]
public JavaScriptResult ServerVariables()
{
Func<Dictionary<string, object>> getResult = () => new Dictionary<string, object>
{
Func<string> getResult = () =>
{
var defaultVals = new Dictionary<string, object>
{
"umbracoUrls", new Dictionary<string, object>
{
{"legacyTreeJs", Url.Action("LegacyTreeJs", "BackOffice")},
{"manifestAssetList", Url.Action("GetManifestAssetList", "BackOffice")},
{"gridConfig", Url.Action("GetGridConfig", "BackOffice")},
{"serverVarsJs", Url.Action("Application", "BackOffice")},
//API URLs
"umbracoUrls", new Dictionary<string, object>
{
"embedApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<RteEmbedController>(
controller => controller.GetEmbed("", 0, 0))
},
{
"userApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<UserController>(
controller => controller.PostDisableUser(0))
},
{
"contentApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentController>(
controller => controller.PostSave(null))
},
{
"mediaApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MediaController>(
controller => controller.GetRootMedia())
},
{
"imagesApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ImagesController>(
controller => controller.GetBigThumbnail(0))
},
{
"sectionApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<SectionController>(
controller => controller.GetSections())
},
{
"treeApplicationApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ApplicationTreeController>(
controller => controller.GetApplicationTrees(null, null, null))
},
{
"contentTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentTypeController>(
controller => controller.GetAllowedChildren(0))
},
{
"mediaTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MediaTypeController>(
controller => controller.GetAllowedChildren(0))
},
{
"macroApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MacroController>(
controller => controller.GetMacroParameters(0))
},
{
"authenticationApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<AuthenticationController>(
controller => controller.PostLogin(null))
},
{
"currentUserApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<CurrentUserController>(
controller => controller.GetMembershipProviderConfig())
},
{
"legacyApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<LegacyController>(
controller => controller.DeleteLegacyItem(null, null, null))
},
{
"entityApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<EntityController>(
controller => controller.GetById(0, UmbracoEntityTypes.Media))
},
{
"dataTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<DataTypeController>(
controller => controller.GetById(0))
},
{
"dashboardApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<DashboardController>(
controller => controller.GetDashboard(null))
},
{
"logApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<LogController>(
controller => controller.GetEntityLog(0))
},
{
"memberApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MemberController>(
controller => controller.GetByKey(Guid.Empty))
},
{
"packageInstallApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<PackageInstallController>(
controller => controller.Fetch(string.Empty))
},
{
"rteApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<RichTextPreValueController>(
controller => controller.GetConfiguration())
},
{
"stylesheetApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<StylesheetController>(
controller => controller.GetAll())
},
{
"memberTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MemberTypeController>(
controller => controller.GetAllTypes())
},
{
"updateCheckApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<UpdateCheckController>(
controller => controller.GetCheck())
},
{
"tagApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<TagsController>(
controller => controller.GetAllTags(null))
},
{
"memberTreeBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MemberTreeController>(
controller => controller.GetNodes("-1", null))
},
{
"mediaTreeBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MediaTreeController>(
controller => controller.GetNodes("-1", null))
},
{
"contentTreeBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentTreeController>(
controller => controller.GetNodes("-1", null))
},
{
"tagsDataBaseUrl", Url.GetUmbracoApiServiceBaseUrl<TagsDataController>(
controller => controller.GetTags(""))
},
{
"examineMgmtBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ExamineManagementApiController>(
controller => controller.GetIndexerDetails())
},
{
"xmlDataIntegrityBaseUrl", Url.GetUmbracoApiServiceBaseUrl<XmlDataIntegrityController>(
controller => controller.CheckContentXmlTable())
{"legacyTreeJs", Url.Action("LegacyTreeJs", "BackOffice")},
{"manifestAssetList", Url.Action("GetManifestAssetList", "BackOffice")},
{"gridConfig", Url.Action("GetGridConfig", "BackOffice")},
{"serverVarsJs", Url.Action("Application", "BackOffice")},
//API URLs
{
"embedApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<RteEmbedController>(
controller => controller.GetEmbed("", 0, 0))
},
{
"userApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<UserController>(
controller => controller.PostDisableUser(0))
},
{
"contentApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentController>(
controller => controller.PostSave(null))
},
{
"mediaApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MediaController>(
controller => controller.GetRootMedia())
},
{
"imagesApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ImagesController>(
controller => controller.GetBigThumbnail(0))
},
{
"sectionApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<SectionController>(
controller => controller.GetSections())
},
{
"treeApplicationApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ApplicationTreeController>(
controller => controller.GetApplicationTrees(null, null, null))
},
{
"contentTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentTypeController>(
controller => controller.GetAllowedChildren(0))
},
{
"mediaTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MediaTypeController>(
controller => controller.GetAllowedChildren(0))
},
{
"macroApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MacroController>(
controller => controller.GetMacroParameters(0))
},
{
"authenticationApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<AuthenticationController>(
controller => controller.PostLogin(null))
},
{
"currentUserApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<CurrentUserController>(
controller => controller.GetMembershipProviderConfig())
},
{
"legacyApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<LegacyController>(
controller => controller.DeleteLegacyItem(null, null, null))
},
{
"entityApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<EntityController>(
controller => controller.GetById(0, UmbracoEntityTypes.Media))
},
{
"dataTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<DataTypeController>(
controller => controller.GetById(0))
},
{
"dashboardApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<DashboardController>(
controller => controller.GetDashboard(null))
},
{
"logApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<LogController>(
controller => controller.GetEntityLog(0))
},
{
"memberApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MemberController>(
controller => controller.GetByKey(Guid.Empty))
},
{
"packageInstallApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<PackageInstallController>(
controller => controller.Fetch(string.Empty))
},
{
"rteApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<RichTextPreValueController>(
controller => controller.GetConfiguration())
},
{
"stylesheetApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<StylesheetController>(
controller => controller.GetAll())
},
{
"memberTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MemberTypeController>(
controller => controller.GetAllTypes())
},
{
"updateCheckApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<UpdateCheckController>(
controller => controller.GetCheck())
},
{
"tagApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<TagsController>(
controller => controller.GetAllTags(null))
},
{
"memberTreeBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MemberTreeController>(
controller => controller.GetNodes("-1", null))
},
{
"mediaTreeBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MediaTreeController>(
controller => controller.GetNodes("-1", null))
},
{
"contentTreeBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentTreeController>(
controller => controller.GetNodes("-1", null))
},
{
"tagsDataBaseUrl", Url.GetUmbracoApiServiceBaseUrl<TagsDataController>(
controller => controller.GetTags(""))
},
{
"examineMgmtBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ExamineManagementApiController>(
controller => controller.GetIndexerDetails())
},
{
"xmlDataIntegrityBaseUrl", Url.GetUmbracoApiServiceBaseUrl<XmlDataIntegrityController>(
controller => controller.CheckContentXmlTable())
}
}
}
},
{
"umbracoSettings", new Dictionary<string, object>
},
{
{"umbracoPath", GlobalSettings.Path},
{"mediaPath", IOHelper.ResolveUrl(SystemDirectories.Media).TrimEnd('/')},
{"appPluginsPath", IOHelper.ResolveUrl(SystemDirectories.AppPlugins).TrimEnd('/')},
"umbracoSettings", new Dictionary<string, object>
{
"imageFileTypes",
string.Join(",", UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes)
},
{"keepUserLoggedIn", UmbracoConfig.For.UmbracoSettings().Security.KeepUserLoggedIn},
}
},
{
"umbracoPlugins", new Dictionary<string, object>
{"umbracoPath", GlobalSettings.Path},
{"mediaPath", IOHelper.ResolveUrl(SystemDirectories.Media).TrimEnd('/')},
{"appPluginsPath", IOHelper.ResolveUrl(SystemDirectories.AppPlugins).TrimEnd('/')},
{
"imageFileTypes",
string.Join(",", UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes)
},
{"keepUserLoggedIn", UmbracoConfig.For.UmbracoSettings().Security.KeepUserLoggedIn},
}
},
{
{"trees", GetTreePluginsMetaData()}
}
},
{"isDebuggingEnabled", HttpContext.IsDebuggingEnabled},
{"application", GetApplicationState()}
"umbracoPlugins", new Dictionary<string, object>
{
{"trees", GetTreePluginsMetaData()}
}
},
{"isDebuggingEnabled", HttpContext.IsDebuggingEnabled},
{"application", GetApplicationState()}
};
//Parse the variables to a string
return ServerVariablesParser.Parse(defaultVals);
};
//cache the result if debugging is disabled
var result = HttpContext.IsDebuggingEnabled
? getResult()
: ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem<Dictionary<string, object>>(
: ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem<string>(
typeof(BackOfficeController) + "ServerVariables",
() => getResult(),
new TimeSpan(0, 10, 0));
return JavaScript(ServerVariablesParser.Parse(result));
return JavaScript(result);
}
/// <summary>
+11 -69
View File
@@ -28,6 +28,7 @@ using Examine.SearchCriteria;
using Umbraco.Web.Dynamics;
using umbraco;
using System.Text.RegularExpressions;
using Umbraco.Core.Xml;
namespace Umbraco.Web.Editors
{
@@ -146,6 +147,8 @@ namespace Umbraco.Web.Editors
/// <returns></returns>
public EntityBasic GetByQuery(string query, int nodeContextId, UmbracoEntityTypes type)
{
//TODO: Rename this!!! It's a bit misleading, it should be GetByXPath
if (type != UmbracoEntityTypes.Document)
throw new ArgumentException("Get by query is only compatible with enitities of type Document");
@@ -163,76 +166,15 @@ namespace Umbraco.Web.Editors
//PP: wip in progress on the query parser
private string ParseXPathQuery(string query, int id)
{
//no need to parse it
if (!query.StartsWith("$"))
return query;
//get full path
Func<int, IEnumerable<string>> getPath = delegate(int nodeid){
var ent = Services.EntityService.Get(nodeid);
return ent.Path.Split(',').Reverse();
};
//get nearest published item
Func<IEnumerable<string>, int> getClosestPublishedAncestor = (path =>
{
foreach (var _id in path)
return UmbracoXPathPathSyntaxParser.ParseXPathQuery(
xpathExpression: query,
nodeContextId: id,
getPath: nodeid =>
{
var item = Umbraco.TypedContent(int.Parse(_id));
if (item != null)
return item.Id;
}
return -1;
});
var rootXpath = "descendant::*[@id={0}]";
//parseable items:
var vars = new Dictionary<string, Func<string, string>>();
vars.Add("$current", q => {
var _id = getClosestPublishedAncestor(getPath(id));
return q.Replace("$current", string.Format(rootXpath, _id));
});
vars.Add("$parent", q =>
{
//remove the first item in the array if its the current node
//this happens when current is published, but we are looking for its parent specifically
var path = getPath(id);
if(path.ElementAt(0) == id.ToString()){
path = path.Skip(1);
}
var _id = getClosestPublishedAncestor(path);
return q.Replace("$parent", string.Format(rootXpath, _id));
});
vars.Add("$site", q =>
{
var _id = getClosestPublishedAncestor(getPath(id));
return q.Replace("$site", string.Format(rootXpath, _id) + "/ancestor-or-self::*[@level = 1]");
});
vars.Add("$root", q =>
{
return q.Replace("$root", string.Empty);
});
foreach (var varible in vars)
{
if (query.StartsWith(varible.Key))
{
query = varible.Value.Invoke(query);
break;
}
}
return query;
var ent = Services.EntityService.Get(nodeid);
return ent.Path.Split(',').Reverse();
},
publishedContentExists: i => Umbraco.TypedContent(i) != null);
}
public EntityBasic GetById(int id, UmbracoEntityTypes type)
@@ -12,7 +12,8 @@ namespace Umbraco.Web.PropertyEditors
{
_internalPreValues = new Dictionary<string, object>
{
{"showEditButton", "0"}
{"showEditButton", "0"},
{"startNodeId", "-1"}
};
}
@@ -32,6 +33,9 @@ namespace Umbraco.Web.PropertyEditors
{
[PreValueField("showEditButton", "Show edit button (this feature is in preview!)", "boolean")]
public string ShowEditButton { get; set; }
[PreValueField("startNodeId", "Start node", "treepicker")]
public int StartNodeId { get; set; }
}
}
@@ -16,6 +16,42 @@ namespace Umbraco.Web.PropertyEditors
editor.Validators.Add(new IntegerValidator());
return editor;
}
protected override PreValueEditor CreatePreValueEditor()
{
return new IntegerPreValueEditor();
}
/// <summary>
/// A custom pre-value editor class to deal with the legacy way that the pre-value data is stored.
/// </summary>
internal class IntegerPreValueEditor : PreValueEditor
{
public IntegerPreValueEditor()
{
//create the fields
Fields.Add(new PreValueField(new IntegerValidator())
{
Description = "Enter the minimum amount of number to be entered",
Key = "min",
View = "number",
Name = "Minimum"
});
Fields.Add(new PreValueField(new IntegerValidator())
{
Description = "Enter the intervals amount between each step of number to be entered",
Key = "step",
View = "number",
Name = "Step Size"
});
Fields.Add(new PreValueField(new IntegerValidator())
{
Description = "Enter the maximum amount of number to be entered",
Key = "max",
View = "number",
Name = "Maximum"
});
}
}
}
}
@@ -8,9 +8,12 @@ using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Web.Templates;
using System.Linq;
using HtmlAgilityPack;
namespace Umbraco.Web.PropertyEditors.ValueConverters
{
/// <summary>
/// A value converter for TinyMCE that will ensure any macro content is rendered properly even when
/// used dynamically.
@@ -58,18 +61,60 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
return sb.ToString();
}
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
if (source == null) return null;
var sourceString = source.ToString();
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
if (source == null)
{
return null;
}
var sourceString = source.ToString();
// ensures string is parsed for {localLink} and urls are resolved correctly
sourceString = TemplateUtilities.ParseInternalLinks(sourceString, preview);
sourceString = TemplateUtilities.ResolveUrlsFromTextString(sourceString);
sourceString = TemplateUtilities.ResolveUrlsFromTextString(sourceString);
// ensure string is parsed for macros and macros are executed correctly
sourceString = RenderRteMacros(sourceString, preview);
return sourceString;
}
// find and remove the rel attributes used in the Umbraco UI from img tags
var doc = new HtmlDocument();
doc.LoadHtml(sourceString);
if (doc.ParseErrors.Any() == false && doc.DocumentNode != null)
{
// Find all images with rel attribute
var imgNodes = doc.DocumentNode.SelectNodes("//img[@rel]");
if (imgNodes != null)
{
var modified = false;
foreach (var img in imgNodes)
{
var firstOrDefault = img.Attributes.FirstOrDefault(x => x.Name == "rel");
if (firstOrDefault != null)
{
var rel = firstOrDefault.Value;
// Check that the rel attribute is a integer before removing
int nodeId;
if (int.TryParse(rel, out nodeId))
{
img.Attributes.Remove("rel");
modified = true;
}
}
}
if (modified)
{
return doc.DocumentNode.OuterHtml;
}
}
}
return sourceString;
}
}
}
@@ -1,4 +1,7 @@
using Umbraco.Core.Logging;
using System.Linq;
using System.Web;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
namespace Umbraco.Web.Routing
@@ -17,17 +20,22 @@ namespace Umbraco.Web.Routing
{
LogHelper.Debug<ContentFinderByLegacy404>("Looking for a page to handle 404.");
// TODO - replace the whole logic and stop calling into library!
var error404 = global::umbraco.library.GetCurrentNotFoundPageId();
var id = int.Parse(error404);
// TODO - replace the whole logic
var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId(
//TODO: The IContentSection should be ctor injected into this class in v8!
UmbracoConfig.For.UmbracoSettings().Content.Error404Collection.ToArray(),
//TODO: Is there a better way to extract this value? at least we're not relying on singletons here though
pcr.RoutingContext.UmbracoContext.HttpContext.Request.ServerVariables["SERVER_NAME"],
pcr.RoutingContext.UmbracoContext.Application.Services.EntityService,
new PublishedContentQuery(pcr.RoutingContext.UmbracoContext.ContentCache, pcr.RoutingContext.UmbracoContext.MediaCache));
IPublishedContent content = null;
if (id > 0)
if (error404.HasValue)
{
LogHelper.Debug<ContentFinderByLegacy404>("Got id={0}.", () => id);
LogHelper.Debug<ContentFinderByLegacy404>("Got id={0}.", () => error404.Value);
content = pcr.RoutingContext.UmbracoContext.ContentCache.GetById(id);
content = pcr.RoutingContext.UmbracoContext.ContentCache.GetById(error404.Value);
LogHelper.Debug<ContentFinderByLegacy404>(content == null
? "Could not find content with that id."
+183 -61
View File
@@ -4,84 +4,90 @@ using System.Linq;
using System.Web;
using System.Xml;
using System.Reflection;
using umbraco.cms.businesslogic.web;
using Umbraco.Core;
using Umbraco.Core.Logging;
using umbraco.interfaces;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Xml;
namespace Umbraco.Web.Routing
{
// provides internal access to legacy url -- should get rid of it eventually
internal class NotFoundHandlerHelper
{
const string ContextKey = "Umbraco.Web.Routing.NotFoundHandlerHelper.Url";
// provides internal access to legacy url -- should get rid of it eventually
internal class NotFoundHandlerHelper
{
const string ContextKey = "Umbraco.Web.Routing.NotFoundHandlerHelper.Url";
static NotFoundHandlerHelper()
{
InitializeNotFoundHandlers();
}
public static string GetLegacyUrlForNotFoundHandlers()
{
// that's not backward-compatible because when requesting "/foo.aspx"
// 4.9 : url = "foo.aspx"
// 4.10 : url = "/foo"
//return pcr.Uri.AbsolutePath;
public static string GetLegacyUrlForNotFoundHandlers()
{
// that's not backward-compatible because when requesting "/foo.aspx"
// 4.9 : url = "foo.aspx"
// 4.10 : url = "/foo"
//return pcr.Uri.AbsolutePath;
// so we have to run the legacy code for url preparation :-(
// so we have to run the legacy code for url preparation :-(
var httpContext = HttpContext.Current;
var httpContext = HttpContext.Current;
if (httpContext == null)
return "";
if (httpContext == null)
return "";
var url = httpContext.Items[ContextKey] as string;
if (url != null)
return url;
var url = httpContext.Items[ContextKey] as string;
if (url != null)
return url;
// code from requestModule.UmbracoRewrite
var tmp = httpContext.Request.Path.ToLower();
// code from requestModule.UmbracoRewrite
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.
// 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
var root = Core.IO.SystemDirectories.Root.ToLower();
if (!string.IsNullOrEmpty(root) && tmp.StartsWith(root))
tmp = tmp.Substring(root.Length);
tmp = tmp.TrimEnd('/');
if (tmp == "/default.aspx")
tmp = string.Empty;
else if (tmp == root)
tmp = string.Empty;
// code from requestHandler.cleanUrl
var root = Core.IO.SystemDirectories.Root.ToLower();
if (!string.IsNullOrEmpty(root) && tmp.StartsWith(root))
tmp = tmp.Substring(root.Length);
tmp = tmp.TrimEnd('/');
if (tmp == "/default.aspx")
tmp = string.Empty;
else if (tmp == root)
tmp = string.Empty;
// code from UmbracoDefault.Page_PreInit
if (tmp != "" && httpContext.Request["umbPageID"] == null)
{
var tryIntParse = tmp.Replace("/", "").Replace(".aspx", string.Empty);
int result;
if (int.TryParse(tryIntParse, out result))
tmp = tmp.Replace(".aspx", string.Empty);
}
else if (!string.IsNullOrEmpty(httpContext.Request["umbPageID"]))
{
int result;
if (int.TryParse(httpContext.Request["umbPageID"], out result))
{
tmp = httpContext.Request["umbPageID"];
}
}
// code from UmbracoDefault.Page_PreInit
if (tmp != "" && httpContext.Request["umbPageID"] == null)
{
var tryIntParse = tmp.Replace("/", "").Replace(".aspx", string.Empty);
int result;
if (int.TryParse(tryIntParse, out result))
tmp = tmp.Replace(".aspx", string.Empty);
}
else if (!string.IsNullOrEmpty(httpContext.Request["umbPageID"]))
{
int result;
if (int.TryParse(httpContext.Request["umbPageID"], out result))
{
tmp = httpContext.Request["umbPageID"];
}
}
// code from requestHandler.ctor
if (tmp != "")
tmp = tmp.Substring(1);
// code from requestHandler.ctor
if (tmp != "")
tmp = tmp.Substring(1);
httpContext.Items[ContextKey] = tmp;
return tmp;
}
httpContext.Items[ContextKey] = tmp;
return tmp;
}
private static IEnumerable<Type> _customHandlerTypes;
private static Type _customLastChanceHandlerType;
private static Type _customLastChanceHandlerType;
static void InitializeNotFoundHandlers()
{
@@ -175,14 +181,14 @@ namespace Umbraco.Web.Routing
return handlers;
}
public static bool IsNotFoundHandlerEnabled<T>()
{
return _customHandlerTypes.Contains(typeof (T));
}
public static bool IsNotFoundHandlerEnabled<T>()
{
return _customHandlerTypes.Contains(typeof(T));
}
public static INotFoundHandler GetNotFoundLastChanceHandler()
{
if (_customLastChanceHandlerType == null) return null;
public static INotFoundHandler GetNotFoundLastChanceHandler()
{
if (_customLastChanceHandlerType == null) return null;
try
{
@@ -214,5 +220,121 @@ namespace Umbraco.Web.Routing
return finder;
}
/// <summary>
/// Returns the Umbraco page id to use as the Not Found page based on the configured 404 pages and the current request
/// </summary>
/// <param name="error404Collection"></param>
/// <param name="requestServerName">
/// The server name attached to the request, normally would be the source of HttpContext.Current.Request.ServerVariables["SERVER_NAME"]
/// </param>
/// <param name="entityService"></param>
/// <param name="publishedContentQuery"></param>
/// <returns></returns>
internal static int? GetCurrentNotFoundPageId(
IContentErrorPage[] error404Collection,
string requestServerName,
IEntityService entityService,
PublishedContentQuery publishedContentQuery)
{
if (error404Collection.Count() > 1)
{
// try to get the 404 based on current culture (via domain)
IContentErrorPage cultureErr;
//TODO: Remove the dependency on this legacy Domain service,
// in 7.3 the real domain service should be passed in as a parameter.
if (Domain.Exists(requestServerName))
{
var d = Domain.GetDomain(requestServerName);
// test if a 404 page exists with current culture
cultureErr = error404Collection
.FirstOrDefault(x => x.Culture == d.Language.CultureAlias);
if (cultureErr != null)
{
return GetContentIdFromErrorPageConfig(cultureErr, entityService, publishedContentQuery);
}
}
// test if a 404 page exists with current culture thread
cultureErr = error404Collection
.FirstOrDefault(x => x.Culture == System.Threading.Thread.CurrentThread.CurrentUICulture.Name);
if (cultureErr != null)
{
return GetContentIdFromErrorPageConfig(cultureErr, entityService, publishedContentQuery);
}
// there should be a default one!
cultureErr = error404Collection
.FirstOrDefault(x => x.Culture == "default");
if (cultureErr != null)
{
return GetContentIdFromErrorPageConfig(cultureErr, entityService, publishedContentQuery);
}
}
else
{
return GetContentIdFromErrorPageConfig(error404Collection.First(), entityService, publishedContentQuery);
}
return null;
}
/// <summary>
/// Returns the content id based on the configured IContentErrorPage section
/// </summary>
/// <param name="errorPage"></param>
/// <param name="entityService"></param>
/// <param name="publishedContentQuery"></param>
/// <returns></returns>
internal static int? GetContentIdFromErrorPageConfig(IContentErrorPage errorPage, IEntityService entityService, PublishedContentQuery publishedContentQuery)
{
if (errorPage.HasContentId) return errorPage.ContentId;
if (errorPage.HasContentKey)
{
//need to get the Id for the GUID
//TODO: When we start storing GUIDs into the IPublishedContent, then we won't have to look this up
// but until then we need to look it up in the db. For now we've implemented a cached service for
// converting Int -> Guid and vice versa.
var found = entityService.GetIdForKey(errorPage.ContentKey, UmbracoObjectTypes.Document);
if (found)
{
return found.Result;
}
return null;
}
if (errorPage.ContentXPath.IsNullOrWhiteSpace() == false)
{
try
{
//we have an xpath statement to execute
var xpathResult = UmbracoXPathPathSyntaxParser.ParseXPathQuery(
xpathExpression: errorPage.ContentXPath,
nodeContextId: null,
getPath: nodeid =>
{
var ent = entityService.Get(nodeid);
return ent.Path.Split(',').Reverse();
},
publishedContentExists: i => publishedContentQuery.TypedContent(i) != null);
//now we'll try to execute the expression
var nodeResult = publishedContentQuery.TypedContentSingleAtXPath(xpathResult);
if (nodeResult != null)
return nodeResult.Id;
}
catch (Exception ex)
{
LogHelper.Error<NotFoundHandlerHelper>("Could not parse xpath expression: " + errorPage.ContentXPath, ex);
return null;
}
}
return null;
}
}
}
@@ -511,16 +511,35 @@ namespace Umbraco.Web.Security.Providers
{
var member = MemberService.GetByUsername(username);
if (member == null) return false;
if (member == null)
{
LogHelper.Info<UmbracoMembershipProviderBase>(
string.Format(
"Login attempt failed for username {0} from IP address {1}, the user does not exist",
username,
GetCurrentRequestIpAddress()));
return false;
}
if (member.IsApproved == false)
{
LogHelper.Info<UmbracoMembershipProvider<T, TEntity>>("Cannot validate member " + username + " because they are not approved");
LogHelper.Info<UmbracoMembershipProviderBase>(
string.Format(
"Login attempt failed for username {0} from IP address {1}, the user is not approved",
username,
GetCurrentRequestIpAddress()));
return false;
}
if (member.IsLockedOut)
{
LogHelper.Info<UmbracoMembershipProvider<T, TEntity>>("Cannot validate member " + username + " because they are currently locked out");
LogHelper.Info<UmbracoMembershipProviderBase>(
string.Format(
"Login attempt failed for username {0} from IP address {1}, the user is locked",
username,
GetCurrentRequestIpAddress()));
return false;
}
@@ -538,18 +557,39 @@ namespace Umbraco.Web.Security.Providers
{
member.IsLockedOut = true;
member.LastLockoutDate = DateTime.Now;
LogHelper.Info<UmbracoMembershipProvider<T, TEntity>>("Member " + username + " is now locked out, max invalid password attempts exceeded");
LogHelper.Info<UmbracoMembershipProviderBase>(
string.Format(
"Login attempt failed for username {0} from IP address {1}, the user is now locked out, max invalid password attempts exceeded",
username,
GetCurrentRequestIpAddress()));
}
else
{
LogHelper.Info<UmbracoMembershipProviderBase>(
string.Format(
"Login attempt failed for username {0} from IP address {1}",
username,
GetCurrentRequestIpAddress()));
}
}
else
{
member.FailedPasswordAttempts = 0;
member.LastLoginDate = DateTime.Now;
LogHelper.Info<UmbracoMembershipProviderBase>(
string.Format(
"Login attempt succeeded for username {0} from IP address {1}",
username,
GetCurrentRequestIpAddress()));
}
//don't raise events for this! It just sets the member dates, if we do raise events this will
// cause all distributed cache to execute - which will clear out some caches we don't want.
// http://issues.umbraco.org/issue/U4-3451
//TODO: In v8 we aren't going to have an overload to disable events, so we'll need to make a different method
// for this type of thing (i.e. UpdateLastLogin or similar).
MemberService.Save(member, false);
return authenticated;
@@ -8,7 +8,7 @@ namespace Umbraco.Web.UI.JavaScript
{
/// <summary>
/// Could allow developers to add custom variables on startup
/// Allows developers to add custom variables on parsing
/// </summary>
public static event EventHandler<Dictionary<string, object>> Parsing;
@@ -18,6 +18,7 @@ namespace Umbraco.Web.UI.JavaScript
{
var vars = Resources.ServerVariables;
//Raise event for developers to add custom variables
if (Parsing != null)
{
Parsing(null, items);
+5 -6
View File
@@ -76,7 +76,7 @@
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>bin\Release\umbraco.xml</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
@@ -86,7 +86,7 @@
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>none</DebugType>
<DebugType>pdbonly</DebugType>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
@@ -115,9 +115,9 @@
<Reference Include="dotless.Core">
<HintPath>..\packages\dotless.1.4.1.0\lib\dotless.Core.dll</HintPath>
</Reference>
<Reference Include="Examine">
<HintPath>..\packages\Examine.0.1.62.2941\lib\Examine.dll</HintPath>
<Private>True</Private>
<Reference Include="Examine, Version=0.1.63.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Examine.0.1.63.0\lib\Examine.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.6.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -2012,7 +2012,6 @@
</Content>
<Content Include="umbraco.presentation\umbraco\translation\default.aspx" />
<Content Include="umbraco.presentation\umbraco\translation\preview.aspx" />
<Content Include="umbraco.presentation\umbraco\translation\translationTasks.dtd" />
<Content Include="umbraco.presentation\umbraco\translation\xml.aspx" />
<Content Include="umbraco.presentation\umbraco\create\content.ascx">
<SubType>ASPXCodeBehind</SubType>
+1 -1
View File
@@ -3,7 +3,7 @@
<package id="AutoMapper" version="3.0.0" targetFramework="net45" />
<package id="ClientDependency" version="1.8.3.1" targetFramework="net45" />
<package id="dotless" version="1.4.1.0" targetFramework="net45" />
<package id="Examine" version="0.1.62.2941" targetFramework="net45" />
<package id="Examine" version="0.1.63.0" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net40" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Xml;
@@ -14,6 +15,8 @@ using umbraco.interfaces;
using Umbraco.Core.IO;
using umbraco.NodeFactory;
using Umbraco.Core;
using Umbraco.Web;
using Umbraco.Web.Routing;
namespace umbraco {
@@ -317,13 +320,21 @@ namespace umbraco {
{
LogHelper.Info<handle404>(string.Format("NotFound url {0} (from '{1}')", url, HttpContext.Current.Request.UrlReferrer));
// Test if the error404 not child elements
string error404 = umbraco.library.GetCurrentNotFoundPageId();
// Test if the error404 not child elements
var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId(
UmbracoConfig.For.UmbracoSettings().Content.Error404Collection.ToArray(),
HttpContext.Current.Request.ServerVariables["SERVER_NAME"],
ApplicationContext.Current.Services.EntityService,
new PublishedContentQuery(UmbracoContext.Current.ContentCache, UmbracoContext.Current.MediaCache));
if (error404.HasValue)
{
_redirectID = error404.Value;
HttpContext.Current.Response.StatusCode = 404;
return true;
}
_redirectID = int.Parse(error404);
HttpContext.Current.Response.StatusCode = 404;
return true;
return false;
}
catch (Exception err)
{

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