Compare commits

...

89 Commits

Author SHA1 Message Date
Sebastiaan Jansssen 3e8fb11abd Update to latest modelsbuilder 2018-01-08 08:39:01 +01:00
Shannon 5181988a41 forgot to set the flag 2018-01-08 18:10:27 +11:00
Shannon 5169310258 Makes sure we check for index locking on both a normal boot with empty indexes and a cold boot when that is being forced 2018-01-08 17:57:15 +11:00
Shannon Deminick f987640462 Merge pull request #2370 from abjerner/patch-30
Fixed the xmldoc for UserService.Delete
2018-01-08 14:34:53 +11:00
Anders Bjerner 55e97dad74 Fixed the xmldoc for UserService.Delete 2018-01-06 20:24:02 +01:00
Sebastiaan Jansssen d2f3e162f1 Bump version to 7.7.8 2018-01-04 16:45:00 +01:00
Claus 7404e20a19 Merge pull request #2331 from JackPenney/JackPenney-patch-1
Removed CMS Import keys from hebrew translation
2018-01-04 14:05:43 +01:00
Claus 744ff0cf33 Merge pull request #2328 from akierczynska/patch-3
Update pl.xml
2018-01-04 14:04:47 +01:00
Claus afd0018dd6 Merge pull request #2349 from dallastaylor/remove-console-writeline
Remove Console.Writeline() from IsPublishable().
2018-01-04 13:56:43 +01:00
Shannon Deminick c36aec624b Merge pull request #2367 from umbraco/temp-U4-10756-performance-fix
Doesn't fix the issue but improves performance by ~30%
2018-01-04 23:43:25 +11:00
Claus 1ba86f361a Merge pull request #2368 from umbraco/temp-U4-9268
U4-9268 Hidden preview button reappears after 'save' or 'save and pub…
2018-01-04 12:29:00 +01:00
Shannon e5a21625ea U4-9268 Hidden preview button reappears after 'save' or 'save and publish'. 2018-01-04 21:53:55 +11:00
Sebastiaan Janssen efd3d6937a Merge pull request #2365 from umbraco/temp-U4-10701
U4-10701 Umbraco.MemberHasAccess generates slow query after upgrading…
2018-01-03 15:36:51 +01:00
Niels Hartvig 6d46c2204d Doesn't fix the issue but improves performance by ~30% 2018-01-03 12:54:25 +01:00
Warren Buckley 27b9385df5 Update client build NPM dependancy for gulp-connect to use 5.0.0 as next/latest version required you to use CoffeeScript to compile their src code to use the module/component 2018-01-03 11:08:55 +00:00
Shannon ea6d81f7ac U4-10701 Umbraco.MemberHasAccess generates slow query after upgrading to 7.7.6 2018-01-03 11:47:26 +11:00
Mads Rasmussen f56bd731b7 Merge pull request #2227 from abryukhov/U4-10481
U4-10481 - v7.7.x - RU localization of the last added keys
2017-12-27 13:24:42 +01:00
Mads Rasmussen bee0642417 Merge pull request #2263 from krighi/U4-10323
U4-10323 - FIX - Grid stuck at 12 columns (percentage calculation incorrect)
2017-12-27 13:04:31 +01:00
Mads Rasmussen 43abb08e59 Merge pull request #2305 from marcemarc/temp-u4-10637
Fixes U4-10637 - textarea Macro Parameters hidden in niche circumstances
2017-12-27 11:05:12 +01:00
Mads Rasmussen 17db5709f1 Merge pull request #2339 from bjarnef/dev-v7-U4-10720
U4-10720 - Add documentation to umb-table component
2017-12-27 10:38:43 +01:00
Mads Rasmussen 2fc6d9b7df Merge pull request #2327 from bjarnef/dev-v7-U4-10703
Wrap text in umb-node-preview component
2017-12-27 10:19:23 +01:00
Shannon e4561851a4 modifies some code changes to null check and not to use extension methods that require singleton access. 2017-12-21 17:30:37 +11:00
Shannon Deminick c6daf2e111 Merge pull request #2353 from mitutee/temp-U4-10770
U4-10770
2017-12-21 17:20:19 +11:00
Sebastiaan Janssen 883366f741 Merge pull request #2295 from JacekJMMJ/temp-u4-10626
Temp u4 10626
2017-12-20 16:07:14 +01:00
Claus cac331adbc U4-10640 Multiple Media Picker duplicate image Angular issue in Umbraco 7.7.4 2017-12-20 13:38:07 +01:00
Shannon Deminick 18318ecabf Merge pull request #2354 from umbraco/temp-u4-10764
U4-10764 - workaround broken events
2017-12-20 17:27:42 +11:00
Shannon 6b9ef6df7a fix tests 2017-12-20 17:02:52 +11:00
Shannon Deminick fcaf78ef29 Merge pull request #2355 from umbraco/temp-u4-10774
U4-10774 - leak in CacheRefresherEventHandler
2017-12-20 16:06:41 +11:00
Sebastiaan Janssen 833b4c552c Merge pull request #2350 from umbraco/temp-U4-10686
U4-10686 TypedMediaAtRoot().Descendants() calls SQL
2017-12-19 18:25:23 +01:00
Mads Rasmussen c678b7f6d9 Merge branch 'bjarnef-dev-v7-U4-10639' into dev-v7 2017-12-19 10:40:59 +01:00
Mads Rasmussen e320840a29 fix position of add button in media picker 2017-12-19 10:39:52 +01:00
Stephan b664fc5e94 U4-10774 - leak in CacheRefresherEventHandler 2017-12-19 10:04:33 +01:00
Stephan b87346bee5 U4-10764 - minor fix 2017-12-19 10:01:51 +01:00
Mads Rasmussen 6029306fe9 Merge branch 'dev-v7-U4-10639' of git://github.com/bjarnef/Umbraco-CMS into bjarnef-dev-v7-U4-10639 2017-12-19 09:53:52 +01:00
Stephan f979792290 U4-10764 - workaround broken events 2017-12-18 16:53:58 +01:00
m.kilianovskyi 5f82fc6e20 Merge branch 'dev-v7' into HEAD 2017-12-18 17:51:27 +02:00
m.kilianovskyi b1a0ca98ea U4-10770 Get all permissions for entity instead of explicit only 2017-12-18 17:50:53 +02:00
Ilham Boulghallat f4f99c2922 Merge pull request #2336 from MrCosmo/temp-U4-10722
U4-10722 fix in Dutch localization
2017-12-18 10:32:33 +00:00
Shannon c1b3da869d U4-10686 TypedMediaAtRoot().Descendants() calls SQL 2017-12-15 16:01:20 +11:00
Dallas Taylor e39158d5e5 Remove Console.Writeline() from IsPublishable(). 2017-12-14 22:18:49 -05:00
Shannon ddd9c8ef7d Do a lock check on the index on startup and unlock it if it is, this is a safety check since we are now using the simplefs dir 2017-12-14 19:25:01 +11:00
Shannon 44db4e7a48 updates nuspec and references to use latest Examine 2017-12-14 18:34:48 +11:00
Shannon f44b158c15 When we disable examine indexing on startup with MainDom, also suspend all indexing 2017-12-14 16:19:54 +11:00
Robert 1ff66d0c3a Merge pull request #2345 from umbraco/temp-U4-10735
U4-10735 Examine update to better manage appdomain shutdowns
2017-12-13 10:52:56 +01:00
Robert aba2c2a79e Merge pull request #2346 from umbraco/temp-U4-10738
U4-10738 Deleting a media type folder causes an exception
2017-12-12 16:02:21 +01:00
Robert 9f62dfc087 Merge pull request #2348 from umbraco/temp-U4-10588
U4-10588 Indexed member data is missing fields
2017-12-12 13:40:48 +01:00
Shannon Deminick a21912dc41 Merge pull request #2337 from skttl/U4-10549-rte-memory-usage
Fix for U4-10549 RTE memory usage
2017-12-12 11:53:42 +01:00
Robert 733b4a770f Merge pull request #2347 from umbraco/temp-U4-10587
U4-10587 Email field in InternalMemberIndex seems to be attempted to …
2017-12-12 11:29:10 +01:00
Shannon 2e097b7e46 U4-10588 Indexed member data is missing fields 2017-12-12 11:25:53 +01:00
Shannon e1b6997ef7 U4-10587 Email field in InternalMemberIndex seems to be attempted to being added to the index twice 2017-12-11 15:50:27 +01:00
Sebastiaan Jansssen b6b7b9f433 Bump version to 7.7.7 2017-12-11 13:57:31 +01:00
Shannon 8181f88cb0 Do not keep looking up data to index if the app is shutting down 2017-12-08 09:09:14 +01:00
Claus 3a4865ef7d U4-10738 Deleting a media type folder causes an exception 2017-12-07 13:45:49 +01:00
Shannon 37f6dbfa6b more logging 2017-12-06 15:46:35 +01:00
Shannon 131fea3ba4 updates some proj refs 2017-12-06 15:38:00 +01:00
Shannon b0661218a0 U4-10735 Examine update to better manage appdomain shutdowns 2017-12-06 15:21:38 +01:00
Mikkel Holck Madsen fb99b101d8 Merge pull request #2340 from umbraco/temp-U4-10610
U4-10610 Cannot restore content templates
2017-12-05 13:47:11 +01:00
Claus 0ce7efc978 U4-10610 Cannot restore content templates 2017-12-05 10:19:12 +01:00
Bjarne Fyrstenborg 3b8a2d7d65 Add basic documentation to umbPasswordToggle 2017-11-30 23:48:41 +01:00
Bjarne Fyrstenborg 61b9ab5c7b Fix typo 2017-11-30 23:47:55 +01:00
Bjarne Fyrstenborg cfda04b6ed Add documentation of umb-table component 2017-11-30 23:47:23 +01:00
Mikkel Holck Madsen 11bdfbba19 Merge pull request #2338 from umbraco/temp-u4-10715
U4-10715 - scheduled publishing and LB issue
2017-11-30 10:57:12 +01:00
Stephan 9694831638 U4-10715 - scheduled publishing and LB issue 2017-11-30 08:54:16 +01:00
Søren Kottal a20844b55b Destroy tineMceEditors on $destroy 2017-11-29 12:16:12 +01:00
Marco 158e40d7f6 U4-10722 fix in Dutch localization 2017-11-29 08:25:04 +01:00
Jack Penney 1c4e1db054 Removed CMS Import keys from hebrew translation 2017-11-23 12:28:17 +00:00
Bjarne Fyrstenborg 3c98d9d2e1 Wrap text in umb-node-preview component 2017-11-20 19:18:57 +01:00
bjarnef 8d14a3ef2c added number validation in embed overlay 2017-11-20 12:36:12 +01:00
bjarnef 2f3d9c9509 localize texts 2017-11-20 12:32:09 +01:00
Robert 6e8f3b6e13 Merge pull request #2324 from umbraco/temp-UAASSSCRUM-1254
Added custom RollingFileAppender and changed rollingStyle to "size"
2017-11-17 13:03:48 +01:00
mikkelhm b9cbdbd9a7 Add rename of Appender to csproj 2017-11-17 12:01:32 +01:00
mikkelhm ebf35356a8 Updates the CustomRollingFileAppender to read config settings to control it 2017-11-17 12:00:42 +01:00
akierczynska f3ba1fa7ed Update pl.xml
Adding translations and adjusting pl.xml to en.xml format.
2017-11-15 18:07:31 +00:00
Sebastiaan Janssen 7eca99e249 Bump version to 7.7.6 2017-11-15 15:21:25 +01:00
Sebastiaan Janssen 837bb83d48 Merge remote-tracking branch 'origin/dev-v7.6' into dev-v7 2017-11-15 14:40:19 +01:00
Sebastiaan Janssen 054ac78970 Revert "Position changed from "target" to "center""
This reverts commit c1769aa299.
2017-11-15 14:39:09 +01:00
Robert 5982a868ea Added custom RollingFileAppender and changed rollingStyle to "size"
OpenFile method has been overiden, this means that everytime a log will be opened, it will check the last access time of all existing logs, and delete the ones that haven't been accessed in more than 1 month.

Changing the rollingStyle to "size" will make sure that logs will roll once the maximumFileSize reaches its set limit.
2017-11-14 12:01:11 +01:00
Bjarne Fyrstenborg e72758e04a Ensure box is square when picker is multiple picker 2017-11-06 22:01:35 +01:00
Bjarne Fyrstenborg 9d373c194d Show thumbnails if any images/files has been selected 2017-11-06 21:42:01 +01:00
Bjarne Fyrstenborg 856e123ec2 Oops - remove duplicated disableFolderSelect 2017-11-06 19:23:41 +01:00
Bjarne Fyrstenborg 0b2af6b48f Fix square image in imagepicker prevalue editor. Cleanup and consistency 2017-11-06 19:12:27 +01:00
Marc Goodson 360665c082 Fixes accidental hiding of textarea parameters when inserting a Macro(with those parameters) via the Rich Text Editor Macro button within a grid cell - U4-10637 2017-11-05 10:36:14 +00:00
Alexander Bryukhov ff98b5f321 U4-10481 - v7.7.x - RU localization of the last added keys (grid editor U4-5722) 2017-11-03 12:18:24 +07:00
Jacek Malinowski 92378095a2 U4 10-626. Detecting new Application Url and _umbracoApplicationUrl refresh. 2017-11-02 09:08:46 -07:00
Jacek Malinowski daa0741802 U4-10626 Detecting deplayoment Id change 2017-11-02 07:40:53 -07:00
Stephan eaa8ca5fdc U4-10626 - support resetting UmbracoApplicationUrl 2017-11-02 13:30:45 +01:00
Kaue Righi e0e9823a03 U4-10323 - Grid stuck at 12 columns (percentage calculation incorrect) - fix 2017-10-25 11:40:46 -02:00
Alexander Bryukhov 3a98d63bf1 U4-10481v7.7.2 - RU localization of the last added keys (user section filters & sort) 2017-09-29 15:15:28 +07:00
Alexander Bryukhov ac65af772a U4-10481 - v7.7.2 - RU localization of the last added keys 2017-09-29 13:27:45 +07:00
80 changed files with 1208 additions and 510 deletions
+1 -1
View File
@@ -33,7 +33,7 @@
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
<dependency id="Examine" version="[0.1.88, 1.0.0)" />
<dependency id="Examine" version="[0.1.89, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.5.6, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.8.7, 5.0.0)" />
<dependency id="semver" version="[1.1.2, 3.0.0)" />
+1 -1
View File
@@ -17,7 +17,7 @@
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.7, 4.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.8, 4.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.1, 3.0.0)" />
</dependencies>
-2
View File
@@ -49,11 +49,9 @@
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.7.5")]
[assembly: AssemblyInformationalVersion("7.7.5")]
[assembly: AssemblyFileVersion("7.7.8")]
[assembly: AssemblyInformationalVersion("7.7.8")]
+15 -2
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Threading;
using Umbraco.Core.Configuration;
@@ -260,7 +261,7 @@ namespace Umbraco.Core
/// - http://issues.umbraco.org/issue/U4-5728
/// - http://issues.umbraco.org/issue/U4-5391
/// </remarks>
internal string UmbracoApplicationUrl
public string UmbracoApplicationUrl
{
get
{
@@ -268,9 +269,21 @@ namespace Umbraco.Core
return _umbracoApplicationUrl;
}
}
/// <summary>
/// Resets the url.
/// </summary>
public void ResetUmbracoApplicationUrl()
{
_umbracoApplicationUrl = null;
}
// ReSharper disable once InconsistentNaming
internal string _umbracoApplicationUrl;
internal string _umbracoApplicationUrl;
internal List<string> _umbracoApplicationDomains = new List<string>();
internal string _umbracoApplicationDeploymentId;
private Lazy<bool> _configured;
internal MainDom MainDom { get; private set; }
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.7.5");
private static readonly Version Version = new Version("7.7.8");
/// <summary>
/// Gets the current version of Umbraco.
@@ -76,260 +76,257 @@ namespace Umbraco.Core.Events
{
if (_events == null)
return Enumerable.Empty<IEventDefinition>();
IReadOnlyList<IEventDefinition> events;
switch (filter)
{
case EventDefinitionFilter.All:
return FilterSupersededAndUpdateToLatestEntity(_events);
events = _events;
break;
case EventDefinitionFilter.FirstIn:
var l1 = new OrderedHashSet<IEventDefinition>();
foreach (var e in _events)
{
l1.Add(e);
}
return FilterSupersededAndUpdateToLatestEntity(l1);
events = l1;
break;
case EventDefinitionFilter.LastIn:
var l2 = new OrderedHashSet<IEventDefinition>(keepOldest: false);
foreach (var e in _events)
{
l2.Add(e);
}
return FilterSupersededAndUpdateToLatestEntity(l2);
events = l2;
break;
default:
throw new ArgumentOutOfRangeException("filter", filter, null);
}
return FilterSupersededAndUpdateToLatestEntity(events);
}
private class EventDefinitionTypeData
private class EventDefinitionInfos
{
public IEventDefinition EventDefinition { get; set; }
public Type EventArgType { get; set; }
public SupersedeEventAttribute[] SupersedeAttributes { get; set; }
public Type[] SupersedeTypes { get; set; }
}
/// <summary>
/// This will iterate over the events (latest first) and filter out any events or entities in event args that are included
/// in more recent events that Supersede previous ones. For example, If an Entity has been Saved and then Deleted, we don't want
/// to raise the Saved event (well actually we just don't want to include it in the args for that saved event)
/// </summary>
/// <param name="events"></param>
/// <returns></returns>
private static IEnumerable<IEventDefinition> FilterSupersededAndUpdateToLatestEntity(IReadOnlyList<IEventDefinition> events)
// fixme
// this is way too convoluted, the superceede attribute is used only on DeleteEventargs to specify
// that it superceeds save, publish, move and copy - BUT - publish event args is also used for
// unpublishing and should NOT be superceeded - so really it should not be managed at event args
// level but at event level
//
// what we want is:
// if an entity is deleted, then all Saved, Moved, Copied, Published events prior to this should
// not trigger for the entity - and even though, does it make any sense? making a copy of an entity
// should ... trigger?
//
// not going to refactor it all - we probably want to *always* trigger event but tell people that
// due to scopes, they should not expected eg a saved entity to still be around - however, now,
// going to write a ugly condition to deal with U4-10764
// iterates over the events (latest first) and filter out any events or entities in event args that are included
// in more recent events that Supersede previous ones. For example, If an Entity has been Saved and then Deleted, we don't want
// to raise the Saved event (well actually we just don't want to include it in the args for that saved event)
internal static IEnumerable<IEventDefinition> FilterSupersededAndUpdateToLatestEntity(IReadOnlyList<IEventDefinition> events)
{
//used to keep the 'latest' entity and associated event definition data
var allEntities = new List<Tuple<IEntity, EventDefinitionTypeData>>();
//tracks all CancellableObjectEventArgs instances in the events which is the only type of args we can work with
var cancelableArgs = new List<CancellableObjectEventArgs>();
// keeps the 'latest' entity and associated event data
var entities = new List<Tuple<IEntity, EventDefinitionInfos>>();
// collects the event definitions
// collects the arguments in result, that require their entities to be updated
var result = new List<IEventDefinition>();
var resultArgs = new List<CancellableObjectEventArgs>();
//This will eagerly load all of the event arg types and their attributes so we don't have to continuously look this data up
var allArgTypesWithAttributes = events.Select(x => x.Args.GetType())
// eagerly fetch superceeded arg types for each arg type
var argTypeSuperceeding = events.Select(x => x.Args.GetType())
.Distinct()
.ToDictionary(x => x, x => x.GetCustomAttributes<SupersedeEventAttribute>(false).ToArray());
//Iterate all events and collect the actual entities in them and relates them to their corresponding EventDefinitionTypeData
//we'll process the list in reverse because events are added in the order they are raised and we want to filter out
//any entities from event args that are not longer relevant
//(i.e. if an item is Deleted after it's Saved, we won't include the item in the Saved args)
.ToDictionary(x => x, x => x.GetCustomAttributes<SupersedeEventAttribute>(false).Select(y => y.SupersededEventArgsType).ToArray());
// iterate over all events and filter
//
// process the list in reverse, because events are added in the order they are raised and we want to keep
// the latest (most recent) entities and filter out what is not relevant anymore (too old), eg if an entity
// is Deleted after being Saved, we want to filter out the Saved event
for (var index = events.Count - 1; index >= 0; index--)
{
var eventDefinition = events[index];
var def = events[index];
var argType = eventDefinition.Args.GetType();
var attributes = allArgTypesWithAttributes[eventDefinition.Args.GetType()];
var meta = new EventDefinitionTypeData
var infos = new EventDefinitionInfos
{
EventDefinition = eventDefinition,
EventArgType = argType,
SupersedeAttributes = attributes
EventDefinition = def,
SupersedeTypes = argTypeSuperceeding[def.Args.GetType()]
};
var args = eventDefinition.Args as CancellableObjectEventArgs;
if (args != null)
var args = def.Args as CancellableObjectEventArgs;
if (args == null)
{
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
if (list == null)
// not a cancellable event arg, include event definition in result
result.Add(def);
}
else
{
// event object can either be a single object or an enumerable of objects
// try to get as an enumerable, get null if it's not
var eventObjects = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
if (eventObjects == null)
{
//extract the event object
var obj = args.EventObject as IEntity;
if (obj != null)
// single object, cast as an IEntity
// if cannot cast, cannot filter, nothing - just include event definition in result
var eventEntity = args.EventObject as IEntity;
if (eventEntity == null)
{
//Now check if this entity already exists in other event args that supersede this current event arg type
if (IsFiltered(obj, meta, allEntities) == false)
{
//if it's not filtered we can adde these args to the response
cancelableArgs.Add(args);
result.Add(eventDefinition);
//track the entity
allEntities.Add(Tuple.Create(obj, meta));
}
result.Add(def);
continue;
}
else
// look for this entity in superceding event args
// found = must be removed (ie not added), else track
if (IsSuperceeded(eventEntity, infos, entities) == false)
{
//Can't retrieve the entity so cant' filter or inspect, just add to the output
result.Add(eventDefinition);
// track
entities.Add(Tuple.Create(eventEntity, infos));
// track result arguments
// include event definition in result
resultArgs.Add(args);
result.Add(def);
}
}
else
{
// enumerable of objects
var toRemove = new List<IEntity>();
foreach (var entity in list)
foreach (var eventObject in eventObjects)
{
//extract the event object
var obj = entity as IEntity;
if (obj != null)
{
//Now check if this entity already exists in other event args that supersede this current event arg type
if (IsFiltered(obj, meta, allEntities))
{
//track it to be removed
toRemove.Add(obj);
}
else
{
//track the entity, it's not filtered
allEntities.Add(Tuple.Create(obj, meta));
}
}
// extract the event object, cast as an IEntity
// if cannot cast, cannot filter, nothing to do - just leave it in the list & continue
var eventEntity = eventObject as IEntity;
if (eventEntity == null)
continue;
// look for this entity in superceding event args
// found = must be removed, else track
if (IsSuperceeded(eventEntity, infos, entities))
toRemove.Add(eventEntity);
else
{
//we don't need to do anything here, we can't cast to IEntity so we cannot filter, so it will just remain in the list
}
entities.Add(Tuple.Create(eventEntity, infos));
}
//remove anything that has been filtered
// remove superceded entities
foreach (var entity in toRemove)
{
list.Remove(entity);
}
eventObjects.Remove(entity);
//track the event and include in the response if there's still entities remaining in the list
if (list.Count > 0)
// if there are still entities in the list, keep the event definition
if (eventObjects.Count > 0)
{
if (toRemove.Count > 0)
{
//re-assign if the items have changed
args.EventObject = list;
// re-assign if changed
args.EventObject = eventObjects;
}
cancelableArgs.Add(args);
result.Add(eventDefinition);
// track result arguments
// include event definition in result
resultArgs.Add(args);
result.Add(def);
}
}
}
else
{
//it's not a cancelable event arg so we just include it in the result
result.Add(eventDefinition);
}
}
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
UpdateToLatestEntities(allEntities, cancelableArgs);
// go over all args in result, and update them with the latest instanceof each entity
UpdateToLatestEntities(entities, resultArgs);
//we need to reverse the result since we've been adding by latest added events first!
// reverse, since we processed the list in reverse
result.Reverse();
return result;
}
private static void UpdateToLatestEntities(IEnumerable<Tuple<IEntity, EventDefinitionTypeData>> allEntities, IEnumerable<CancellableObjectEventArgs> cancelableArgs)
// edits event args to use the latest instance of each entity
private static void UpdateToLatestEntities(IEnumerable<Tuple<IEntity, EventDefinitionInfos>> entities, IEnumerable<CancellableObjectEventArgs> args)
{
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
// get the latest entities
// ordered hash set + keepOldest will keep the latest inserted entity (in case of duplicates)
var latestEntities = new OrderedHashSet<IEntity>(keepOldest: true);
foreach (var entity in allEntities.OrderByDescending(entity => entity.Item1.UpdateDate))
{
foreach (var entity in entities.OrderByDescending(entity => entity.Item1.UpdateDate))
latestEntities.Add(entity.Item1);
}
foreach (var args in cancelableArgs)
foreach (var arg in args)
{
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
if (list == null)
// event object can either be a single object or an enumerable of objects
// try to get as an enumerable, get null if it's not
var eventObjects = TypeHelper.CreateGenericEnumerableFromObject(arg.EventObject);
if (eventObjects == null)
{
//try to find the args entity in the latest entity - based on the equality operators, this will
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, args.EventObject));
// single object
// look for a more recent entity for that object, and replace if any
// works by "equalling" entities ie the more recent one "equals" this one (though different object)
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, arg.EventObject));
if (foundEntity != null)
{
args.EventObject = foundEntity;
}
arg.EventObject = foundEntity;
}
else
{
// enumerable of objects
// same as above but for each object
var updated = false;
for (int i = 0; i < list.Count; i++)
for (var i = 0; i < eventObjects.Count; i++)
{
//try to find the args entity in the latest entity - based on the equality operators, this will
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, list[i]));
if (foundEntity != null)
{
list[i] = foundEntity;
updated = true;
}
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, eventObjects[i]));
if (foundEntity == null) continue;
eventObjects[i] = foundEntity;
updated = true;
}
if (updated)
{
args.EventObject = list;
}
arg.EventObject = eventObjects;
}
}
}
/// <summary>
/// This will check against all of the processed entity/events (allEntities) to see if this entity already exists in
/// event args that supersede the event args being passed in and if so returns true.
/// </summary>
/// <param name="entity"></param>
/// <param name="eventDef"></param>
/// <param name="allEntities"></param>
/// <returns></returns>
private static bool IsFiltered(
IEntity entity,
EventDefinitionTypeData eventDef,
List<Tuple<IEntity, EventDefinitionTypeData>> allEntities)
// determines if a given entity, appearing in a given event definition, should be filtered out,
// considering the entities that have already been visited - an entity is filtered out if it
// appears in another even definition, which superceedes this event definition.
private static bool IsSuperceeded(IEntity entity, EventDefinitionInfos infos, List<Tuple<IEntity, EventDefinitionInfos>> entities)
{
var argType = eventDef.EventDefinition.Args.GetType();
//var argType = meta.EventArgsType;
var argType = infos.EventDefinition.Args.GetType();
//check if the entity is found in any processed event data that could possible supersede this one
var foundByEntity = allEntities
.Where(x => x.Item2.SupersedeAttributes.Length > 0
//if it's the same arg type than it cannot supersede
&& x.Item2.EventArgType != argType
&& Equals(x.Item1, entity))
// look for other instances of the same entity, coming from an event args that supercedes other event args,
// ie is marked with the attribute, and is not this event args (cannot supersede itself)
var superceeding = entities
.Where(x => x.Item2.SupersedeTypes.Length > 0 // has the attribute
&& x.Item2.EventDefinition.Args.GetType() != argType // is not the same
&& Equals(x.Item1, entity)) // same entity
.ToArray();
//no args have been processed with this entity so it should not be filtered
if (foundByEntity.Length == 0)
// first time we see this entity = not filtered
if (superceeding.Length == 0)
return false;
// fixme see notes above
// delete event args does NOT superceedes 'unpublished' event
if (argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition.EventName == "UnPublished")
return false;
// found occurences, need to determine if this event args is superceded
if (argType.IsGenericType)
{
var supercededBy = foundByEntity
.FirstOrDefault(x =>
x.Item2.SupersedeAttributes.Any(y =>
//if the attribute type is a generic type def then compare with the generic type def of the event arg
(y.SupersededEventArgsType.IsGenericTypeDefinition && y.SupersededEventArgsType == argType.GetGenericTypeDefinition())
//if the attribute type is not a generic type def then compare with the normal type of the event arg
|| (y.SupersededEventArgsType.IsGenericTypeDefinition == false && y.SupersededEventArgsType == argType)));
// generic, must compare type arguments
var supercededBy = superceeding.FirstOrDefault(x =>
x.Item2.SupersedeTypes.Any(y =>
// superceeding a generic type which has the same generic type definition
// fixme no matter the generic type parameters? could be different?
y.IsGenericTypeDefinition && y == argType.GetGenericTypeDefinition()
// or superceeding a non-generic type which is ... fixme how is this ever possible? argType *is* generic?
|| y.IsGenericTypeDefinition == false && y == argType));
return supercededBy != null;
}
else
{
var supercededBy = foundByEntity
.FirstOrDefault(x =>
x.Item2.SupersedeAttributes.Any(y =>
//since the event arg type is not a generic type, then we just compare type 1:1
y.SupersededEventArgsType == argType));
// non-generic, can compare types 1:1
var supercededBy = superceeding.FirstOrDefault(x =>
x.Item2.SupersedeTypes.Any(y => y == argType));
return supercededBy != null;
}
}
@@ -0,0 +1,95 @@
using System;
using System.IO;
using log4net.Appender;
using log4net.Util;
namespace Umbraco.Core.Logging
{
/// <summary>
/// This class will do the exact same thing as the RollingFileAppender that comes from log4net
/// With the extension, that it is able to do automatic cleanup of the logfiles in the directory where logging happens
///
/// By specifying the properties MaxLogFileDays and BaseFilePattern, the files will automaticly get deleted when
/// the logger is configured(typically when the app starts). To utilize this appender swap out the type of the rollingFile appender
/// that ships with Umbraco, to be Umbraco.Core.Logging.RollingFileCleanupAppender, and add the maxLogFileDays and baseFilePattern elements
/// to the configuration i.e.:
///
/// <example>
/// <appender name="rollingFile" type="Log4netAwesomeness.CustomRollingFileAppender, Log4netAwesomeness">
/// <file type="log4net.Util.PatternString" value="App_Data\Logs\UmbracoTraceLog.%property{log4net:HostName}.txt" />
/// <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
/// <appendToFile value="true" />
/// <rollingStyle value="Date" />
/// <maximumFileSize value="5MB" />
/// <maxLogFileDays value="5"/>
/// <basefilePattern value="UmbracoTraceLog.*.txt.*"/>
/// <layout type="log4net.Layout.PatternLayout">
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
/// </layout>
/// <layout type="log4net.Layout.PatternLayout">
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
/// </layout>
/// <encoding value="utf-8" />
/// </appender>
/// </example>
/// </summary>
public class RollingFileCleanupAppender : RollingFileAppender
{
public int MaxLogFileDays { get; set; }
public string BaseFilePattern { get; set; }
/// <summary>
/// This override will delete logs older than the specified amount of days
/// </summary>
/// <param name="fileName"></param>
/// <param name="append"></param>
protected override void OpenFile(string fileName, bool append)
{
bool cleanup = true;
// Validate settings and input
if (MaxLogFileDays <= 0)
{
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'MaxLogFileDays' needs to be a positive integer, aborting cleanup");
cleanup = false;
}
if (string.IsNullOrWhiteSpace(BaseFilePattern))
{
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'BaseFilePattern' is empty, aborting cleanup");
cleanup = false;
}
// grab the directory we are logging to, as this is were we will search for older logfiles
var logFolder = Path.GetDirectoryName(fileName);
if (Directory.Exists(logFolder) == false)
{
LogLog.Warn(typeof(RollingFileCleanupAppender), string.Format("Directory '{0}' for logfiles does not exist, aborting cleanup", logFolder));
cleanup = false;
}
// If everything is validated, we can do the actual cleanup
if (cleanup)
{
Cleanup(logFolder);
}
base.OpenFile(fileName, append);
}
private void Cleanup(string directoryPath)
{
// only take files that matches the pattern we are using i.e. UmbracoTraceLog.*.txt.*
string[] logFiles = Directory.GetFiles(directoryPath, BaseFilePattern);
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Found {0} files that matches the baseFilePattern: '{1}'", logFiles.Length, BaseFilePattern));
foreach (var logFile in logFiles)
{
DateTime lastAccessTime = System.IO.File.GetLastWriteTimeUtc(logFile);
// take the value from the config file
if (lastAccessTime < DateTime.Now.AddDays(-MaxLogFileDays))
{
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Deleting file {0} as its lastAccessTime is older than {1} days speficied by MaxLogFileDays", logFile, MaxLogFileDays));
base.DeleteFile(logFile);
}
}
}
}
}
@@ -188,7 +188,7 @@ namespace Umbraco.Core.Models
Language,
/// <summary>
/// Document
/// Document Blueprint
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.DocumentBlueprint, typeof(IContent))]
[FriendlyName("DocumentBlueprint")]
@@ -183,17 +183,17 @@ namespace Umbraco.Core.Persistence.Repositories
}
public IEnumerable<IMemberGroup> GetMemberGroupsForMember(string username)
{
var sql = new Sql()
{
var sql = new Sql()
.Select("un.*")
.From("umbracoNode AS un")
.InnerJoin("cmsMember2MemberGroup")
.On("un.id = cmsMember2MemberGroup.MemberGroup")
.LeftJoin("(SELECT umbracoNode.id, cmsMember.LoginName FROM umbracoNode INNER JOIN cmsMember ON umbracoNode.id = cmsMember.nodeId) AS member")
.On("member.id = cmsMember2MemberGroup.Member")
.Where("un.nodeObjectType=@objectType", new {objectType = NodeObjectTypeId })
.Where("member.LoginName=@loginName", new {loginName = username});
.On("cmsMember2MemberGroup.MemberGroup = un.id")
.InnerJoin("cmsMember")
.On("cmsMember.nodeId = cmsMember2MemberGroup.Member")
.Where("un.nodeObjectType=@objectType", new { objectType = NodeObjectTypeId })
.Where("cmsMember.LoginName=@loginName", new { loginName = username });
return Database.Fetch<NodeDto>(sql)
.DistinctBy(dto => dto.NodeId)
.Select(x => _modelFactory.BuildEntity(x));
+4 -5
View File
@@ -993,8 +993,7 @@ namespace Umbraco.Core.Services
FROM umbracoNode
JOIN cmsDocument ON umbracoNode.id=cmsDocument.nodeId AND cmsDocument.published=@0
WHERE umbracoNode.trashed=@1 AND umbracoNode.id IN (@2)",
true, false, ids);
Console.WriteLine(sql.SQL);
true, false, ids);
var x = uow.Database.Fetch<int>(sql);
return ids.Length == x.Count;
}
@@ -2007,7 +2006,7 @@ namespace Umbraco.Core.Services
}
return true;
}
}
/// <summary>
/// Sorts a collection of <see cref="IContent"/> objects by updating the SortOrder according
@@ -2029,7 +2028,7 @@ namespace Umbraco.Core.Services
using (new WriteLock(Locker))
{
var allContent = GetByIds(ids).ToDictionary(x => x.Id, x => x);
var items = ids.Select(x => allContent[x]);
var items = ids.Select(x => allContent[x]);
using (var uow = UowProvider.GetUnitOfWork())
{
@@ -2839,4 +2838,4 @@ namespace Umbraco.Core.Services
#endregion
}
}
}
@@ -377,7 +377,7 @@ namespace Umbraco.Core.Services
repo.Delete(container);
uow.Commit();
deleteEventArgs.CanCancel = false;
uow.Events.Dispatch(DeletedMediaTypeContainer, this, deleteEventArgs);
uow.Events.Dispatch(DeletedMediaTypeContainer, this, deleteEventArgs, "DeletedMediaTypeContainer");
return OperationStatus.Success(evtMsgs);
//TODO: Audit trail ?
+3 -3
View File
@@ -228,9 +228,9 @@ namespace Umbraco.Core.Services
}
/// <summary>
/// Deletes an <see cref="IUser"/>
/// Disables an <see cref="IUser"/>
/// </summary>
/// <param name="membershipUser"><see cref="IUser"/> to Delete</param>
/// <param name="membershipUser"><see cref="IUser"/> to disable</param>
public void Delete(IUser membershipUser)
{
//disable
@@ -712,7 +712,7 @@ namespace Umbraco.Core.Services
/// <param name="id">Id of the User to retrieve</param>
/// <returns><see cref="IProfile"/></returns>
public IProfile GetProfileById(int id)
{
{
//This is called a TON. Go get the full user from cache which should already be IProfile
var fullUser = GetUserById(id);
var asProfile = fullUser as IProfile;
+21 -3
View File
@@ -3,6 +3,7 @@ using System.Web;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Core.Sync
@@ -46,8 +47,20 @@ namespace Umbraco.Core.Sync
// settings: for unit tests only
internal static void EnsureApplicationUrl(ApplicationContext appContext, HttpRequestBase request = null, IUmbracoSettingsSection settings = null)
{
bool newApplicationUrl = false;
if (request != null)
{
var applicationUrl = GetApplicationUrlFromRequest(request);
newApplicationUrl = !appContext._umbracoApplicationDomains.Contains(applicationUrl);
if (newApplicationUrl)
{
appContext._umbracoApplicationDomains.Add(applicationUrl);
LogHelper.Info(typeof(ApplicationUrlHelper), $"New ApplicationUrl detected: {applicationUrl}");
}
}
// if initialized, return
if (appContext._umbracoApplicationUrl != null) return;
if (appContext._umbracoApplicationUrl != null && !newApplicationUrl) return;
var logger = appContext.ProfilingLogger.Logger;
@@ -132,6 +145,12 @@ namespace Umbraco.Core.Sync
{
var logger = appContext.ProfilingLogger.Logger;
appContext._umbracoApplicationUrl = GetApplicationUrlFromRequest(request);
logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (UmbracoModule request)");
}
private static string GetApplicationUrlFromRequest(HttpRequestBase request)
{
// if (HTTP and SSL not required) or (HTTPS and SSL required),
// use ports from request
// otherwise,
@@ -147,8 +166,7 @@ namespace Umbraco.Core.Sync
var ssl = useSsl ? "s" : ""; // force, whatever the first request
var url = "http" + ssl + "://" + request.ServerVariables["SERVER_NAME"] + port + IOHelper.ResolveUrl(SystemDirectories.Umbraco);
appContext._umbracoApplicationUrl = url.TrimEnd('/');
logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (UmbracoModule request)");
return url.TrimEnd('/');
}
}
}
+4
View File
@@ -117,6 +117,8 @@ namespace Umbraco.Core
{
case UmbracoObjectTypes.Document:
return Document;
case UmbracoObjectTypes.DocumentBlueprint:
return DocumentBluePrint;
case UmbracoObjectTypes.Media:
return Media;
case UmbracoObjectTypes.Member:
@@ -161,6 +163,8 @@ namespace Umbraco.Core
{
case Document:
return UmbracoObjectTypes.Document;
case DocumentBluePrint:
return UmbracoObjectTypes.DocumentBlueprint;
case Media:
return UmbracoObjectTypes.Media;
case Member:
+2 -10
View File
@@ -39,22 +39,18 @@
<ItemGroup>
<Reference Include="AutoMapper, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.2\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ImageProcessor, Version=2.5.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ImageProcessor.2.5.6\lib\net45\ImageProcessor.dll</HintPath>
@@ -67,11 +63,9 @@
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Owin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Owin.2.2.1\lib\net45\Microsoft.AspNet.Identity.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin, Version=3.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
@@ -87,17 +81,16 @@
</Reference>
<Reference Include="MiniProfiler, Version=2.1.0.0, Culture=neutral, PublicKeyToken=b44f9351044011a3, processorArchitecture=MSIL">
<HintPath>..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Semver, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\semver.1.1.2\lib\net45\Semver.dll</HintPath>
@@ -109,11 +102,9 @@
<Reference Include="System.Data.Entity" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Drawing" />
@@ -366,6 +357,7 @@
<Compile Include="HashGenerator.cs" />
<Compile Include="IEmailSender.cs" />
<Compile Include="IHttpContextAccessor.cs" />
<Compile Include="Logging\RollingFileCleanupAppender.cs" />
<Compile Include="Models\EntityBase\EntityPath.cs" />
<Compile Include="Models\EntityBase\IDeletableEntity.cs" />
<Compile Include="Models\IUserControl.cs" />
@@ -40,34 +40,27 @@
<ItemGroup>
<Reference Include="BenchmarkDotNet, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.0.9.9\lib\net45\BenchmarkDotNet.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="BenchmarkDotNet.Core, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Core.0.9.9\lib\net45\BenchmarkDotNet.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="BenchmarkDotNet.Diagnostics.Windows, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Diagnostics.Windows.0.9.9\lib\net45\BenchmarkDotNet.Diagnostics.Windows.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.9.9\lib\net45\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Diagnostics.Tracing.TraceEvent, Version=1.0.41.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.41\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Moq, Version=4.1.1309.919, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.1.1309.0919\lib\net40\Moq.dll</HintPath>
@@ -75,27 +68,22 @@
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Numerics" />
<Reference Include="System.Reflection.Metadata, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.3.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.0.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -116,6 +104,7 @@
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
<None Include="_TraceEventProgrammersGuide.docx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
@@ -132,8 +121,8 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
<Content Include="TraceEvent.ReadMe.txt" />
<Content Include="TraceEvent.ReleaseNotes.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
@@ -3,10 +3,13 @@ using System.Collections.Generic;
using System.Linq;
using Moq;
using NUnit.Framework;
using umbraco.cms.businesslogic;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
@@ -99,7 +102,7 @@ namespace Umbraco.Tests.Scoping
DoDeleteForContent += OnDoThingFail;
DoForTestArgs += OnDoThingFail;
DoForTestArgs2 += OnDoThingFail;
var contentType = MockedContentTypes.CreateBasicContentType();
var content1 = MockedContent.CreateBasicContent(contentType);
@@ -114,10 +117,10 @@ namespace Umbraco.Tests.Scoping
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
//content1 will be filtered from the args
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(new[]{ content1 , content3}));
scope.Events.Dispatch(DoDeleteForContent, this, new DeleteEventArgs<IContent>(content1));
scope.Events.Dispatch(DoDeleteForContent, this, new DeleteEventArgs<IContent>(content1), "DoDeleteForContent");
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
//this entire event will be filtered
scope.Events.Dispatch(DoForTestArgs, this, new TestEventArgs(content1));
@@ -141,15 +144,36 @@ namespace Umbraco.Tests.Scoping
}
}
[Test]
public void SupersededEvents2()
{
var contentService = Mock.Of<IContentService>();
var content = Mock.Of<IContent>();
var l1 = new List<IEventDefinition>
{
new EventDefinition<IContentService, PublishEventArgs<IContent>>(Test_UnPublished, contentService, new PublishEventArgs<IContent>(new [] { content }), "UnPublished"),
new EventDefinition<IContentService, DeleteEventArgs<IContent>>(Test_Deleted, contentService, new DeleteEventArgs<IContent>(new [] { content }), "Deleted")
};
var l2 = new OrderedHashSet<IEventDefinition>(keepOldest: false);
foreach (var e in l1)
l2.Add(e);
var l3 = ScopeEventDispatcherBase.FilterSupersededAndUpdateToLatestEntity(l2);
// see U4-10764
Assert.AreEqual(2, l3.Count());
}
/// <summary>
/// This will test that when we track events that before we Get the events we normalize all of the
/// event entities to be the latest one (most current) found amongst the event so that there is
/// event entities to be the latest one (most current) found amongst the event so that there is
/// no 'stale' entities in any of the args
/// </summary>
[Test]
public void LatestEntities()
{
DoSaveForContent += OnDoThingFail;
DoSaveForContent += OnDoThingFail;
var now = DateTime.Now;
var contentType = MockedContentTypes.CreateBasicContentType();
@@ -165,7 +189,7 @@ namespace Umbraco.Tests.Scoping
var scopeProvider = new ScopeProvider(Mock.Of<IDatabaseFactory2>());
using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher()))
{
{
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content1));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content2));
scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs<IContent>(content3));
@@ -173,7 +197,7 @@ namespace Umbraco.Tests.Scoping
// events have been queued
var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray();
Assert.AreEqual(3, events.Length);
foreach (var t in events)
{
var args = (SaveEventArgs<IContent>)t.Args;
@@ -212,7 +236,7 @@ namespace Umbraco.Tests.Scoping
// events have been queued
var events = scope.Events.GetEvents(EventDefinitionFilter.FirstIn).ToArray();
Assert.AreEqual(1, events.Length);
Assert.AreEqual(1, events.Length);
Assert.AreEqual(content1, ((SaveEventArgs<IContent>) events[0].Args).SavedEntities.First());
Assert.IsTrue(object.ReferenceEquals(content1, ((SaveEventArgs<IContent>)events[0].Args).SavedEntities.First()));
Assert.AreEqual(content1.UpdateDate, ((SaveEventArgs<IContent>) events[0].Args).SavedEntities.First().UpdateDate);
@@ -350,6 +374,9 @@ namespace Umbraco.Tests.Scoping
public static event TypedEventHandler<ScopeEventDispatcherTests, SaveEventArgs<decimal>> DoThing3;
public static event TypedEventHandler<IContentService, PublishEventArgs<IContent>> Test_UnPublished;
public static event TypedEventHandler<IContentService, DeleteEventArgs<IContent>> Test_Deleted;
public class TestEventArgs : CancellableObjectEventArgs
{
public TestEventArgs(object eventObject) : base(eventObject)
+2 -2
View File
@@ -62,8 +62,8 @@
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
+1 -1
View File
@@ -2,7 +2,7 @@
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
<package id="Log4Net.Async" version="2.0.4" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
+1 -1
View File
@@ -26,7 +26,7 @@
"cssnano": "^3.7.6",
"gulp": "^3.9.1",
"gulp-concat": "^2.6.0",
"gulp-connect": "^5.0.0",
"gulp-connect": "5.0.0",
"gulp-less": "^3.1.0",
"gulp-ngdocs": "^0.3.0",
"gulp-open": "^2.0.0",
@@ -366,6 +366,9 @@ angular.module("umbraco.directives")
// element might still be there even after the modal has been hidden.
scope.$on('$destroy', function () {
unsubscribe();
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
tinyMceEditor.destroy()
}
});
});
@@ -77,7 +77,7 @@
@param {string} icon (<code>binding</code>): The node icon.
@param {string} name (<code>binding</code>): The node name.
@param {boolean} published (<code>binding</code>): The node pusblished state.
@param {boolean} published (<code>binding</code>): The node published state.
@param {string} description (<code>binding</code>): A short description.
@param {boolean} sortable (<code>binding</code>): Will add a move cursor on the node preview. Can used in combination with ui-sortable.
@param {boolean} allowRemove (<code>binding</code>): Show/Hide the remove button.
@@ -1,4 +1,15 @@
(function () {
/**
@ngdoc directive
@name umbraco.directives.directive:umbPasswordToggle
@restrict E
@scope
@description
<strong>Added in Umbraco v. 7.7.4:</strong> Use this directive to render a password toggle.
**/
(function () {
'use strict';
// comes from https://codepen.io/jakob-e/pen/eNBQaP
@@ -1,3 +1,114 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbTable
@restrict E
@scope
@description
<strong>Added in Umbraco v. 7.4:</strong> Use this directive to render a data table.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.TableController as vm">
<umb-table
ng-if="items"
items="vm.items"
item-properties="vm.options.includeProperties"
allow-select-all="vm.allowSelectAll"
on-select="vm.selectItem"
on-click="vm.clickItem"
on-select-all="vm.selectAll"
on-selected-all="vm.isSelectedAll"
on-sorting-direction="vm.isSortDirection"
on-sort="vm.sort">
</umb-table>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.items = [
{
"icon": "icon-document",
"name": "My node 1",
"published": true,
"description": "A short description of my node",
"author": "Author 1"
},
{
"icon": "icon-document",
"name": "My node 2",
"published": true,
"description": "A short description of my node",
"author": "Author 2"
}
];
vm.options = {
includeProperties: [
{ alias: "description", header: "Description" },
{ alias: "author", header: "Author" }
]
};
vm.selectItem = selectItem;
vm.clickItem = clickItem;
vm.selectAll = selectAll;
vm.isSelectedAll = isSelectedAll;
vm.isSortDirection = isSortDirection;
vm.sort = sort;
function selectAll($event) {
alert("select all");
}
function isSelectedAll() {
}
function clickItem(item) {
alert("click node");
}
function selectItem(selectedItem, $index, $event) {
alert("select node");
}
function isSortDirection(col, direction) {
}
function sort(field, allow, isSystem) {
}
}
angular.module("umbraco").controller("My.TableController", Controller);
})();
</pre>
@param {string} icon (<code>binding</code>): The node icon.
@param {string} name (<code>binding</code>): The node name.
@param {string} published (<code>binding</code>): The node published state.
@param {function} onSelect (<code>expression</code>): Callback function when the row is selected.
@param {function} onClick (<code>expression</code>): Callback function when the "Name" column link is clicked.
@param {function} onSelectAll (<code>expression</code>): Callback function when selecting all items.
@param {function} onSelectedAll (<code>expression</code>): Callback function when all items are selected.
@param {function} onSortingDirection (<code>expression</code>): Callback function when sorting direction is changed.
@param {function} onSort (<code>expression</code>): Callback function when sorting items.
**/
(function () {
'use strict';
@@ -535,7 +535,7 @@
color: @gray-3;
}
.umb-grid .umb-cell-rte textarea {
.umb-grid .umb-cell-rte textarea.mceNoEditor {
display: none !important;
}
@@ -37,6 +37,7 @@
.umb-node-preview__content {
flex: 1 1 auto;
margin-right: 25px;
overflow: hidden;
}
.umb-node-preview__name {
@@ -50,6 +51,13 @@
color: @gray-3;
}
.umb-node-preview__name,
.umb-node-preview__description {
/*text-overflow: ellipsis;
overflow: hidden;*/
word-wrap: break-word;
}
.umb-node-preview__actions {
flex: 0 0 auto;
display: flex;
@@ -281,6 +281,12 @@ ul.color-picker li a {
display: block;
}
.umb-sortable-thumbnails .umb-sortable-thumbnails__wrapper {
width: 120px;
height: 114px;
overflow: hidden;
}
.umb-sortable-thumbnails .umb-sortable-thumbnails__actions {
position: absolute;
bottom: 10px;
@@ -308,6 +314,7 @@ ul.color-picker li a {
justify-content: center;
align-items: center;
margin-left: 5px;
text-decoration: none;
}
.umb-sortable-thumbnails .umb-sortable-thumbnails__action.-red {
@@ -2,7 +2,7 @@
<umb-control-group label="@general_url">
<input id="url" class="umb-editor input-block-level" type="text" style="margin-bottom: 10px;" ng-model="model.embed.url" ng-keyup="$event.keyCode == 13 ? vm.showPreview() : null" required />
<input type="button" ng-click="vm.showPreview()" class="btn" localize="value" value="@general_retrieve" />
<input type="button" ng-click="vm.showPreview()" class="btn" value="@general_retrieve" localize="value" />
</umb-control-group>
<umb-control-group>
@@ -12,15 +12,15 @@
<div ng-show="model.embed.supportsDimensions">
<umb-control-group label="@general_width">
<input type="text" ng-model="model.embed.width" on-blur="vm.changeSize('width')" />
<input type="number" pattern="[0-9]*" min="0" ng-model="model.embed.width" on-blur="vm.changeSize('width')" />
</umb-control-group>
<umb-control-group label="@general_height">
<input type="text" ng-model="model.embed.height" on-blur="vm.changeSize('height')" />
<input type="number" pattern="[0-9]*" min="0" ng-model="model.embed.height" on-blur="vm.changeSize('height')" />
</umb-control-group>
<umb-control-group label="@general_constrain">
<input id="constrain" type="checkbox" ng-model="model.embed.constrain" />
<input id="constrain" type="checkbox" ng-model="model.embed.constrain" />
</umb-control-group>
</div>
@@ -36,7 +36,7 @@
<umb-overlay
ng-if="vm.childNodeSelectorOverlay.show"
model="vm.childNodeSelectorOverlay"
position="center"
position="target"
view="vm.childNodeSelectorOverlay.view">
</umb-overlay>
@@ -1,20 +1,25 @@
function imageFilePickerController($scope) {
$scope.pick = function() {
$scope.mediaPickerDialog = {};
$scope.mediaPickerDialog.view = "mediapicker";
$scope.mediaPickerDialog.show = true;
$scope.mediaPickerDialog.submit = function(model) {
$scope.model.value = model.selectedImages[0].image;
$scope.mediaPickerDialog.show = false;
$scope.mediaPickerDialog = null;
$scope.add = function() {
$scope.mediaPickerOverlay = {
view: "mediapicker",
disableFolderSelect: true,
onlyImages: true,
show: true,
submit: function (model) {
$scope.model.value = model.selectedImages[0].image;
$scope.mediaPickerOverlay.show = false;
$scope.mediaPickerOverlay = null;
},
close: function () {
$scope.mediaPickerOverlay.show = false;
$scope.mediaPickerOverlay = null;
}
};
};
$scope.mediaPickerDialog.close = function(oldModel) {
$scope.mediaPickerDialog.show = false;
$scope.mediaPickerDialog = null;
};
$scope.remove = function () {
$scope.model.value = null;
};
}
@@ -1,19 +1,28 @@
<div ng-controller="Umbraco.PrevalueEditors.ImageFilePickerController" class="umb-editor umb-mediapicker">
<ul class="umb-sortable-thumbnails">
<li>
<img ng-src="{{model.value}}" alt="" ng-show="model.value">
<a href class="picked-image" ng-click="model.value = null" ng-show="model.value"><i class="icon icon-delete"></i></a>
<ul class="umb-sortable-thumbnails" ng-if="model.value">
<li class="umb-sortable-thumbnails__wrapper">
<img ng-src="{{model.value}}" alt="">
<div class="umb-sortable-thumbnails__actions">
<!--<a class="umb-sortable-thumbnails__action" href="" ng-click="goToItem(image)">
<i class="icon icon-edit"></i>
</a>-->
<a class="umb-sortable-thumbnails__action -red" href="" ng-click="remove()">
<i class="icon icon-delete"></i>
</a>
</div>
</li>
</ul>
<a href ng-click="pick()" class="umb-mediapicker add-link" ng-hide="model.value">
<a href="#" class="add-link" ng-click="add()" ng-class="{'add-link-square': !model.value }" ng-hide="model.value" prevent-default>
<i class="icon icon-add large"></i>
</a>
<umb-overlay
ng-if="mediaPickerDialog.show"
model="mediaPickerDialog"
view="mediaPickerDialog.view"
ng-if="mediaPickerOverlay.show"
model="mediaPickerOverlay"
view="mediaPickerOverlay.view"
position="right">
</umb-overlay>
@@ -640,16 +640,16 @@ angular.module("umbraco")
var clear = true;
//settings indicator shortcut
if ( ($scope.model.config.items.config && $scope.model.config.items.config.length > 0) || ($scope.model.config.items.styles && $scope.model.config.items.styles.length > 0)) {
if (($scope.model.config.items.config && $scope.model.config.items.config.length > 0) || ($scope.model.config.items.styles && $scope.model.config.items.styles.length > 0)) {
$scope.hasSettings = true;
}
//ensure the grid has a column value set,
//if nothing is found, set it to 12
if ($scope.model.config.items.columns && angular.isString($scope.model.config.items.columns)) {
$scope.model.config.items.columns = parseInt($scope.model.config.items.columns);
} else {
if (!$scope.model.config.items.columns){
$scope.model.config.items.columns = 12;
} else if (angular.isString($scope.model.config.items.columns)) {
$scope.model.config.items.columns = parseInt($scope.model.config.items.columns);
}
if ($scope.model.value && $scope.model.value.sections && $scope.model.value.sections.length > 0 && $scope.model.value.sections[0].rows && $scope.model.value.sections[0].rows.length > 0) {
@@ -299,7 +299,7 @@
ng-if="editorOverlay.show"
model="editorOverlay"
view="editorOverlay.view"
position="center">
position="target">
</umb-overlay>
<umb-overlay
@@ -19,6 +19,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
$scope.images = [];
$scope.ids = [];
$scope.isMultiPicker = multiPicker;
if ($scope.model.value) {
var ids = $scope.model.value.split(',');
@@ -2,10 +2,10 @@
<p ng-if="(images|filter:{trashed:true}).length == 1"><localize key="mediaPicker_pickedTrashedItem"></localize></p>
<p ng-if="(images|filter:{trashed:true}).length > 1"><localize key="mediaPicker_pickedTrashedItems"></localize></p>
<div class="flex error">
<ul ui-sortable="sortableOptions" ng-model="images" class="umb-sortable-thumbnails">
<li style="width: 120px; height: 100px; overflow: hidden;" ng-repeat="image in images">
<li class="umb-sortable-thumbnails__wrapper" ng-repeat="image in images track by $index">
<!-- IMAGE -->
<img ng-class="{'trashed': image.trashed}" ng-src="{{image.thumbnail}}" alt="" ng-show="image.thumbnail" title="{{image.trashed ? 'Trashed: ' + image.name : image.name}}" />
@@ -30,11 +30,12 @@
</div>
</li>
<li style="border: none;">
<a href="#" class="add-link" ng-click="add()" ng-class="{'add-link-square': (images.length === 0 || isMultiPicker)}" ng-if="showAdd()" prevent-default>
<i class="icon icon-add large"></i>
</a>
</li>
</ul>
<a href="#" class="add-link" ng-click="add()" ng-class="{'add-link-square': images.length === 0}" ng-if="showAdd()" prevent-default>
<i class="icon icon-add large"></i>
</a>
</div>
<umb-overlay
@@ -374,6 +374,9 @@ angular.module("umbraco")
// element might still be there even after the modal has been hidden.
$scope.$on('$destroy', function () {
unsubscribe();
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
tinyMceEditor.destroy()
}
});
});
});
+6 -8
View File
@@ -127,11 +127,10 @@
<Reference Include="dotless.Core, Version=1.5.2.0, Culture=neutral, PublicKeyToken=96b446c9e63eae34, processorArchitecture=MSIL">
<HintPath>..\packages\dotless.1.5.2\lib\dotless.Core.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="ImageProcessor, Version=2.5.6.0, Culture=neutral, processorArchitecture=MSIL">
@@ -144,7 +143,6 @@
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
</Reference>
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core">
@@ -335,8 +333,8 @@
<Name>umbraco.providers</Name>
</ProjectReference>
<Reference Include="System.Xml.Linq" />
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.7.99, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.7\lib\Umbraco.ModelsBuilder.dll</HintPath>
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.8.100, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.8\lib\Umbraco.ModelsBuilder.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -1026,9 +1024,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7750</DevelopmentServerPort>
<DevelopmentServerPort>7780</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7750</IISUrl>
<IISUrl>http://localhost:7780</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
+12 -1
View File
@@ -422,7 +422,7 @@
<key alias="showPageOnSend">Hvilken side skal vises etter at skjemaet er sendt</key>
<key alias="size">Størrelse</key>
<key alias="sort">Sorter</key>
<key alias="submit">Submit</key> <!-- TODO: Translate this -->
<key alias="submit">Send</key>
<key alias="type">Type</key>
<key alias="typeToSearch">Søk...</key>
<key alias="up">Opp</key>
@@ -439,6 +439,17 @@
<key alias="yes">Ja</key>
<key alias="folder">Mappe</key>
<key alias="searchResults">Søkeresultater</key>
<key alias="reorder">Sorter</key>
<key alias="reorderDone">Avslutt sortering</key>
<key alias="preview">Eksempel</key>
<key alias="changePassword">Bytt passord</key>
<key alias="to">til</key>
<key alias="listView">Listevisning</key>
<key alias="saving">Lagrer...</key>
<key alias="current">nåværende</key>
<key alias="embed">Innbygging</key>
<key alias="retrieve">Hent</key>
<key alias="selected">valgt</key>
</area>
<area alias="graphicheadline">
<key alias="backgroundcolor">Bakgrunnsfarge</key>
+2 -2
View File
@@ -4,7 +4,7 @@
<package id="ClientDependency" version="1.9.2" targetFramework="net45" />
<package id="ClientDependency-Mvc5" version="1.8.0.0" targetFramework="net45" />
<package id="dotless" version="1.5.2" targetFramework="net45" />
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
<package id="ImageProcessor.Web" version="4.8.7" targetFramework="net45" />
<package id="ImageProcessor.Web.Config" version="2.3.1" targetFramework="net45" />
@@ -37,5 +37,5 @@
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
<package id="System.Reflection.Metadata" version="1.0.21" targetFramework="net45" />
<package id="Umbraco.ModelsBuilder" version="3.0.7" targetFramework="net45" />
<package id="Umbraco.ModelsBuilder" version="3.0.8" targetFramework="net45" />
</packages>
@@ -586,7 +586,6 @@
<key alias="sort">Sortér</key>
<key alias="status">Status</key>
<key alias="submit">Indsend</key>
<!-- TODO: Translate this -->
<key alias="type">Type</key>
<key alias="typeToSearch">Skriv for at søge...</key>
<key alias="up">Op</key>
@@ -612,6 +611,7 @@
<key alias="saving">Gemmer...</key>
<key alias="current">nuværende</key>
<key alias="embed">Indlejring</key>
<key alias="retrieve">Hent</key>
<key alias="selected">valgt</key>
</area>
@@ -637,6 +637,7 @@
<key alias="saving">Saving...</key>
<key alias="current">current</key>
<key alias="embed">Embed</key>
<key alias="retrieve">Retrieve</key>
<key alias="selected">selected</key>
</area>
@@ -637,6 +637,7 @@
<key alias="saving">Saving...</key>
<key alias="current">current</key>
<key alias="embed">Embed</key>
<key alias="retrieve">Retrieve</key>
<key alias="selected">selected</key>
</area>
<area alias="colors">
@@ -32,11 +32,6 @@
<key alias="sort">מיין</key>
<key alias="translate">תרגם</key>
<key alias="update">עדכן</key>
<key alias="DeleteCMSImportAction">מחק</key>
<key alias="ExecuteCMSImportWizardAction">בצע</key>
<key alias="ScheduleCMSImportWizardAction">תזמן</key>
<key alias="StartCMSImportWizardAction">ייבא נתונים</key>
<key alias="StartCMSImportChildDefinitionAction">צור הגדרות ילדים</key>
<key alias="LastRunInfoAction">יומן משימות מתוזמנות</key>
</area>
<area alias="assignDomain">
@@ -452,7 +452,7 @@
<key alias="email">Email</key>
<key alias="error">Fout</key>
<key alias="findDocument">Vind</key>
<key alias="height">Hogte</key>
<key alias="height">Hoogte</key>
<key alias="help">Help</key>
<key alias="icon">Icoon</key>
<key alias="import">Import</key>
+90 -14
View File
@@ -12,9 +12,11 @@
<key alias="copy">Kopiuj</key>
<key alias="create">Utwórz</key>
<key alias="createPackage">Stwórz zbiór</key>
<key alias="createGroup">Stwórz grupę</key>
<key alias="delete">Usuń</key>
<key alias="disable">Deaktywuj</key>
<key alias="emptyTrashcan">Opróżnij kosz</key>
<key alias="enable">Aktywuj</key>
<key alias="exportDocumentType">Eksportuj typ dokumentu</key>
<key alias="importDocumentType">Importuj typ dokumentu</key>
<key alias="importPackage">Importuj zbiór</key>
@@ -27,16 +29,49 @@
<key alias="unpublish">Cofnij publikację</key>
<key alias="refreshNode">Odśwież węzeł</key>
<key alias="republish">Opublikuj ponownie całą stronę</key>
<key alias="rename" version="7.3.0">Zmień nazwę</key>
<key alias="restore" version="7.3.0">Przywróć</key>
<key alias="SetPermissionsForThePage">Ustaw uprawnienia dla strony %0%</key>
<key alias="chooseWhereToMove">Wybierz dokąd przenieść</key>
<key alias="toInTheTreeStructureBelow">W strukturze drzewa poniżej</key>
<key alias="rights">Uprawnienia</key>
<key alias="rollback">Cofnij</key>
<key alias="sendtopublish">Wyślij do publikacji</key>
<key alias="sendToTranslate">Wyślij do tłumaczenia</key>
<key alias="setGroup">Ustaw grupę</key>
<key alias="sort">Sortuj</key>
<key alias="translate">Przetłumacz</key>
<key alias="update">Aktualizuj</key>
<key alias="setPermissions">Ustaw uprawnienia</key>
<key alias="unlock">Odblokuj</key>
<key alias="createblueprint">Stwórz Szablon Zawartości</key>
</area>
<area alias="actionCategories">
<key alias="content">Zawartość</key>
<key alias="administration">Administracja</key>
<key alias="structure">Struktura</key>
<key alias="other">Inne</key>
</area>
<area alias="actionDescriptions">
<key alias="assignDomain">Zezwól na dostęp do przydzielenia języka i hostów</key>
<key alias="auditTrail">Zezwól na dostęp do wglądu w historię logów węzła</key>
<key alias="browse">Zezwól na dostęp do widoku węzła</key>
<key alias="changeDocType">Zezwól na dostęp do zmiany typu dokumentu dla węzła</key>
<key alias="copy">Zezwól na dostęp do skopiowania węzła</key>
<key alias="create">Zezwól na dostęp do stworzenia węzłów</key>
<key alias="delete">Zezwól na dostęp do usunięcia węzłóws</key>
<key alias="move">Zezwól na dostęp do przeniesienia węzła</key>
<key alias="protect">Zezwól na dostęp do ustawienia i zmiany publicznego dostępu węzła</key>
<key alias="publish">Zezwól na dostęp do publikacji węzła</key>
<key alias="rights">Zezwól na dostęp do zmiany uprawnień węzła</key>
<key alias="rollback">Zezwól na dostęp do cofnięcia węzła do poprzedniego stanu</key>
<key alias="sendtopublish">Zezwól na dostęp do wysłania węzła do akceptacji przed publikacją</key>
<key alias="sendToTranslate">Zezwól na dostęp do wysłania węzła do tłumaczenia</key>
<key alias="sort">Zezwól na dostęp do zmiany kolejności sortowania węzłów</key>
<key alias="translate">Zezwól na dostęp do tłumaczenia węzła</key>
<key alias="update">Zezwól na dostęp do zapisania węzła</key>
<key alias="createblueprint">Zezwól na dostęp do utworzenia Szablonu Zawartości</key>
</area>
<area alias="assignDomain">
<key alias="permissionDenied">Brak odpowiednich uprawnień</key>
<key alias="addNew">Dodaj nową domenę</key>
@@ -50,14 +85,18 @@
<key alias="domainDeleted">Domena '%0%' została skasowana</key>
<key alias="domainExists">Domena '%0%' jest aktualnie przypisana</key>
<key alias="domainUpdated">Domena '%0%' została zaktualizowana</key>
<key alias="domainHelp"><![CDATA[Poprawne domeny to: "example.com", "www.example.com", "example.com:8080" lub
"https://www.example.com/". Wspierane są jednopoziomowe ścieżki domen, np. "example.com/en" jednakże powinno się ich unikać.
Preferowane jest użycie powyższych ustawień języka.]]></key>
<key alias="orEdit">Edycja aktualnych domen</key>
<key alias="orEdit">Edytuj Aktualne Domeny</key>
<key alias="domainHelp">
<![CDATA[Poprawne domeny to: "example.com", "www.example.com", "example.com:8080" lub
"https://www.example.com/". Wspierane są jednopoziomowe ścieżki domen, np. "example.com/en" jednakże powinno się ich unikać.
Preferowane jest użycie powyższych ustawień języka.]]>
</key>
<key alias="inherit">Odziedziczona</key>
<key alias="setLanguage">Język</key>
<key alias="setLanguageHelp"><![CDATA[Wybierz język dla węzła,<br /> lub wybierz dziedziczenie języka z węzła rodzica. Zostanie to zastosowane<br />
także do obecnego węzła, o ile poniższa domena również do niego należy.]]></key>
<key alias="setLanguageHelp">
<![CDATA[Wybierz język dla węzła,<br /> lub wybierz dziedziczenie języka z węzła rodzica. Zostanie to zastosowane<br />
także do obecnego węzła, o ile poniższa domena również do niego należy.]]>
</key>
<key alias="setDomains">Domeny</key>
</area>
<area alias="auditTrails">
@@ -96,6 +135,7 @@ także do obecnego węzła, o ile poniższa domena również do niego należy.]]
<key alias="styleShow">Pokaż style</key>
<key alias="tableInsert">Wstaw tabelę</key>
<key alias="generateModels">Wygeneruj modele</key>
<key alias="saveAndGenerateModels">Zapisz i wygeneruj modele</key>
<key alias="undo">Cofnij</key>
<key alias="redo">Powtórz</key>
</area>
@@ -139,6 +179,8 @@ także do obecnego węzła, o ile poniższa domena również do niego należy.]]
<key alias="lastPublished">Opublikowane</key>
<key alias="noItemsToShow">Nie ma żadnych elementów do wyświetlenia</key>
<key alias="listViewNoItems" version="7.1.5">Nie ma żadnych elementów do wyświetlenia w liście.</key>
<key alias="listViewNoContent">Nie dodano żadnej zawartości</key>
<key alias="listViewNoMembers">Nie dodano żadnych członków</key>
<key alias="mediatype">Typ mediów</key>
<key alias="mediaLinks">Link do elementu(ów) mediów</key>
<key alias="membergroup">Członek grupy</key>
@@ -173,16 +215,30 @@ także do obecnego węzła, o ile poniższa domena również do niego należy.]]
<key alias="target" version="7.0">Cel</key>
<key alias="scheduledPublishServerTime">Oznacza to następującą godzinę na serwerze:</key>
<key alias="scheduledPublishDocumentation"><![CDATA[<a href="https://our.umbraco.org/documentation/Getting-Started/Data/Scheduled-Publishing/#timezones" target="_blank">Co to oznacza?</a>]]></key>
<key alias="nestedContentDeleteItem">Czy na pewno chcesz usunąć ten element?</key>
<key alias="nestedContentEditorNotSupported">Właściwość %0% używa edytora %1%, który nie jest wspierany przez Nested Content.</key>
<key alias="addTextBox">Dodaj kolejne pole tekstowe</key>
<key alias="removeTextBox">Usuń te pole tekstowe</key>
<key alias="contentRoot">Korzeń zawartości</key>
</area>
<area alias="blueprints">
<key alias="createBlueprintFrom">Stwórz nowy Szablon Zawartości z '%0%'</key>
<key alias="blankBlueprint">Pusty</key>
<key alias="selectBlueprint">Wybierz Szablon Zawartości</key>
<key alias="createdBlueprintHeading">Szablon Zawartości został stworzony</key>
<key alias="createdBlueprintMessage">Szablon Zawartości został stworzony z '%0%'</key>
<key alias="duplicateBlueprintMessage">Szablon Zawartości o tej samej nazwie już istnieje</key>
<key alias="blueprintDescription">Szablon Zawartości to predefiniowana zawartość, którą edytor może wybrać, aby użyć jej jako podstawę do stworzenia nowej zawartości</key>
</area>
<area alias="media">
<key alias="clickToUpload">Kliknij, aby załadować plik</key>
<key alias="dropFilesHere">Przerzuć swoje pliki tutaj...</key>
<key alias="urls">Link do mediów</key>
<key alias="urls">Link do mediów</key>
<key alias="orClickHereToUpload">lub kliknij tutaj, aby wybrać pliki</key>
<key alias="onlyAllowedFiles">Jedyne dozwolone typy plików to</key>
<key alias="disallowedFileType">Nie można załadować pliku, typ pliku nie jest akceptowany</key>
<key alias="maxFileSize">Maksymalny rozmiar pliku to</key>
<key alias="mediaRoot">Korzeń mediów</key>
</area>
<area alias="member">
<key alias="createNewMember">Stwórz nowego członka</key>
@@ -191,6 +247,7 @@ także do obecnego węzła, o ile poniższa domena również do niego należy.]]
<area alias="create">
<key alias="chooseNode">Gdzie chcesz stworzyć nowy %0%?</key>
<key alias="createUnder">Utwórz w</key>
<key alias="createContentBlueprint">Wybierz typ dokumentu, dla którego chcesz stworzyć szablon zawartości</key>
<key alias="updateData">Wybierz rodzaj oraz tytuł</key>
<key alias="noDocumentTypes" version="7.0"><![CDATA[Brak dostępnych dozwolonych typów dokumentów. Należy włączyć je w ustawieniach sekcji pod <strong>"typy dokumentów"</strong>.]]></key>
<key alias="noMediaTypes" version="7.0"><![CDATA[Brak dostępnych dozwolonych typów mediów. Należy włączyć je w ustawieniach sekcji pod <strong>"typy mediów"</strong>.]]></key>
@@ -249,6 +306,8 @@ także do obecnego węzła, o ile poniższa domena również do niego należy.]]
<key alias="copiedItemOfItems">Skopiowano %0% z %1% elementów</key>
</area>
<area alias="defaultdialogs">
<key alias="nodeNameLinkPicker">Tytuł linku</key>
<key alias="urlLinkPicker">Link</key>
<key alias="anchorInsert">Nazwa</key>
<key alias="assignDomain">Zarządzaj nazwami hostów</key>
<key alias="closeThisWindow">Zamknij to okno</key>
@@ -276,6 +335,9 @@ także do obecnego węzła, o ile poniższa domena również do niego należy.]]
<key alias="macroDoesNotHaveProperties">To makro nie posiada żadnych właściwości, które można edytować</key>
<key alias="paste">Wklej</key>
<key alias="permissionsEdit">Edytuj Uprawnienia dla</key>
<key alias="permissionsSet">Ustaw uprawnienia dla</key>
<key alias="permissionsSetForGroup">Ustaw uprawnienia dla %0% dla grupy użytkownika %1%</key>
<key alias="permissionsHelp">Wybierz grupy użytkowników, dla których chcesz ustawić uprawnienia</key>
<key alias="recycleBinDeleting">Zawartość kosza jest teraz usuwana. Proszę nie zamykać tego okna do momentu zakończenia procesu.</key>
<key alias="recycleBinIsEmpty">Zawartość kosza została usunięta</key>
<key alias="recycleBinWarning">Usunięcie elementów z kosza powoduje ich trwałe i nieodwracalne skasowanie</key>
@@ -288,10 +350,14 @@ także do obecnego węzła, o ile poniższa domena również do niego należy.]]
<key alias="siterepublishHelp">Cache strony zostanie odświeżone. Cała zawartość opublikowana będzie aktualna, lecz nieopublikowana zawartość pozostanie niewidoczna</key>
<key alias="tableColumns">Liczba kolumn</key>
<key alias="tableRows">Liczba wierszy</key>
<key alias="templateContentAreaHelp"><![CDATA[<strong>Ustaw zastępczy ID</strong> Ustawiając ID na tym elemencie możesz później łączyć treść z podrzędnych szablonów,
ustawiając dowiązanie do tego ID na elemencie <code>&lt;asp:treści /&gt;</code>]]></key>
<key alias="templateContentPlaceHolderHelp"><![CDATA[<strong>Wybierz zastępczy ID</strong> z poniższej listy. Możesz wybierać tylko
spośród ID na szablonie nadrzędnym tego formularza.]]></key>
<key alias="templateContentAreaHelp">
<![CDATA[<strong>Ustaw zastępczy ID</strong> Ustawiając ID na tym elemencie możesz później łączyć treść z podrzędnych szablonów,
ustawiając dowiązanie do tego ID na elemencie <code>&lt;asp:treści /&gt;</code>]]>
</key>
<key alias="templateContentPlaceHolderHelp">
<![CDATA[<strong>Wybierz zastępczy ID</strong> z poniższej listy. Możesz wybierać tylko
spośród ID na szablonie nadrzędnym tego formularza.]]>
</key>
<key alias="thumbnailimageclickfororiginal">Kliknij na obrazie, aby zobaczyć go w pełnym rozmiarze</key>
<key alias="treepicker">Wybierz element</key>
<key alias="viewCacheItem">Podgląd elementów Cache</key>
@@ -303,14 +369,19 @@ także do obecnego węzła, o ile poniższa domena również do niego należy.]]
<key alias="openInNewWindow">Otwórz zlinkowany dokument w nowym oknie lub zakładce</key>
<key alias="linkToMedia">Link do mediów</key>
<key alias="linkToFile">Link do plików</key>
<key alias="selectContentStartNode">Wybierz węzeł początkowy zawartości</key>
<key alias="selectMedia">Wybierz media</key>
<key alias="selectIcon">Wybierz ikonę</key>
<key alias="selectItem">Wybierz element</key>
<key alias="selectLink">Wybierz link</key>
<key alias="selectMacro">Wybierz makro</key>
<key alias="selectContent">Wybierz zawartość</key>
<key alias="selectMediaStartNode">Wybierz węzeł początkowy mediów</key>
<key alias="selectMember">Wybierz członka</key>
<key alias="selectMemberGroup">Wybierz członka grupy</key>
<key alias="selectNode">Wybierz węzeł</key>
<key alias="selectSections">Wybierz sekcje</key>
<key alias="selectUsers">Wybierz użytkowników</key>
<key alias="noIconsFound">Nie znaleziono ikon</key>
<key alias="noMacroParams">Te makro nie ma żadnych właściwości</key>
<key alias="noMacros">Brak dostępnych makro do wstawienia</key>
@@ -325,9 +396,11 @@ także do obecnego węzła, o ile poniższa domena również do niego należy.]]
<key alias="selectSnippet">Wybierz snippet</key>
</area>
<area alias="dictionaryItem">
<key alias="description"><![CDATA[
Edytuj różne wersje językowe dla elementu słownika '<em>%0%</em>' poniżej.<br/>
Możesz dodać dodatkowe języki w menu "Języki" po lewej stronie.]]></key>
<key alias="description">
<![CDATA[
Edytuj różne wersje językowe dla elementu słownika '<em>%0%</em>' poniżej.<br/>
Możesz dodać dodatkowe języki w menu "Języki" po lewej stronie.]]>
</key>
<key alias="displayName">Nazwa języka</key>
<key alias="changeKey">Edytuj klucz elementu słownika.</key>
<key alias="changeKeyError">
@@ -342,12 +415,15 @@ Możesz dodać dodatkowe języki w menu "Języki" po lewej stronie.]]></key>
<key alias="confirmPassword">Potwierdź hasło</key>
<key alias="nameentity">Nazwij %0%...</key>
<key alias="entername">Wpisz nazwę...</key>
<key alias="enteremail">Wpisz adres e-mail...</key>
<key alias="enterusername">Wpisz nazwę użytkownika...</key>
<key alias="label">Etykieta...</key>
<key alias="enterDescription">Wpisz opis...</key>
<key alias="search">Wpisz, aby wyszukać...</key>
<key alias="filter">Wpisz, aby filtrować...</key>
<key alias="enterTags">Wpisz, aby dodać tagi (naciśnij enter po każdym tagu)...</key>
<key alias="email">Wpisz adres e-mail</key>
<key alias="enterMessage">Wpisz wiadomość...</key>
<key alias="usernameHint">Twoja nazwa użytkownika to przeważnie Twój adres e-mail</key>
</area>
<area alias="editcontenttype">
+23 -7
View File
@@ -153,6 +153,7 @@
<key alias="listNumeric">Нумерованный список</key>
<key alias="macroInsert">Вставить макрос</key>
<key alias="pictureInsert">Вставить изображение</key>
<key alias="redo">Повторить</key>
<key alias="relations">Править связи</key>
<key alias="returnToList">Вернуться к списку</key>
<key alias="save">Сохранить</key>
@@ -168,6 +169,7 @@
<key alias="styleChoose">Выбрать стиль</key>
<key alias="styleShow">Показать стили</key>
<key alias="tableInsert">Вставить таблицу</key>
<key alias="undo">Отменить</key>
</area>
<area alias="changeDocType">
<key alias="changeDocTypeInstruction">Чтобы сменить тип документа для выбранного узла, сначала выберите тип из списка разрешенных для данного расположения.</key>
@@ -375,6 +377,7 @@
<key alias="macroContainerSettings">Свойства макроса</key>
<key alias="macroDoesNotHaveProperties">Этот макрос не имеет редактируемых свойств</key>
<key alias="nodeNameLinkPicker">Заголовок ссылки</key>
<key alias="noIconsFound">Ни одной пиктограммы не найдено</key>
<key alias="paste">Вставить</key>
<key alias="permissionsEdit">Изменить разрешения для</key>
<key alias="permissionsSet">Установить разрешения для</key>
@@ -596,6 +599,7 @@
<key alias="new">Новый</key>
<key alias="next">След</key>
<key alias="no">Нет</key>
<key alias="noItemsInList">Здесь пока нет элементов</key>
<key alias="of">из</key>
<key alias="off">Выкл</key>
<key alias="ok">Ok</key>
@@ -696,6 +700,8 @@
<key alias="chooseExtra">Выбрать дополнительно</key>
<key alias="chooseDefault">Выбрать по-умолчанию</key>
<key alias="areAdded">добавлены</key>
<key alias="maxItemsDescription">Оставьте пустым или задайте 0 для снятия лимита</key>
<key alias="maxItems">Максимальное количество</key>
</area>
<area alias="headers">
<key alias="page">Страница</key>
@@ -1049,7 +1055,7 @@
<area alias="packager">
<key alias="chooseLocalPackageText"><![CDATA[
Выберите файл пакета на своем компьютере, нажав на кнопку 'Обзор'<br />
и указав на нужный файл. Пакеты Umbraco обычно являются архивами с расширением ".umb" или ".zip".
и указав на нужный файл. Пакеты Umbraco обычно являются архивами с расширением '.zip'.
]]></key>
<key alias="dropHere">Перетащите сюда</key>
<key alias="orClickHereToUpload">или нажмите здесь для выбора файла пакета</key>
@@ -1215,12 +1221,12 @@
</area>
<area alias="relatedlinks">
<key alias="caption">Заголовок</key>
<key alias="captionPlaceholder">Укажите заголовок</key>
<key alias="captionPlaceholder">Укажите заголовок ссылки</key>
<key alias="chooseInternal">выбрать страницу сайта</key>
<key alias="enterExternal">указать внешнюю ссылку</key>
<key alias="externalLinkPlaceholder">Укажите ссылку</key>
<key alias="link">Ссылка</key>
<key alias="newWindow">В новом окне</key>
<key alias="newWindow">Открыть в новом окне</key>
</area>
<area alias="renamecontainer">
<key alias="renamed">Переименована</key>
@@ -1393,8 +1399,6 @@
<key alias="disableUserSuccess">'%0%' сейчас заблокирован</key>
<key alias="disableUserError">При блокировке пользователя произошла ошибка</key>
<key alias="setUserGroupOnUsersSuccess">Группы пользователей установлены</key>
<key alias="deleteUserGroupsSuccess">Удалено %0% групп пользователей</key>
<key alias="deleteUserGroupSuccess">'%0%' была удалена</key>
<key alias="unlockUsersSuccess">Разблокировано %0% пользователей</key>
<key alias="unlockUsersError">При разблокировке пользователей произошла ошибка</key>
<key alias="unlockUserSuccess">'%0%' сейчас разблокирован</key>
@@ -1517,8 +1521,8 @@
<key alias="fallbackField">Поле замены</key>
<key alias="addDefaultValue">Добавить значение по-умолчанию</key>
<key alias="defaultValue">Значение по-умолчанию</key>
<key alias="alternativeField">Альтернативное поле</key>
<key alias="alternativeText">Текст по-умолчанию</key>
<key alias="alternativeField">Поле замены</key>
<key alias="alternativeText">Значение по-умолчанию</key>
<key alias="casing">Регистр</key>
<key alias="chooseField">Выбрать поле</key>
<key alias="convertLineBreaks">Преобразовать переводы строк</key>
@@ -1715,11 +1719,22 @@
<key alias="profile">Профиль</key>
<key alias="resetPassword">Сбросить пароль</key>
<key alias="searchAllChildren">Поиск всех дочерних документов</key>
<key alias="selectUserGroups">Выбрать группы пользователей</key>
<key alias="sendInvite">Отправить приглашение</key>
<key alias="sessionExpires" version="7.0">Сессия истекает через</key>
<key alias="sectionsHelp">Разделы, доступные пользователю</key>
<key alias="noStartNode">Начальный узел не задан</key>
<key alias="noStartNodes">Начальные узлы не заданы</key>
<key alias="sortNameAscending">Имя (А-Я)</key>
<key alias="sortNameDescending">Имя (Я-А)</key>
<key alias="sortCreateDateDescending">Сначала новые</key>
<key alias="sortCreateDateAscending">Сначала старые</key>
<key alias="sortLastLoginDateDescending">Недавно зашедшие</key>
<key alias="stateActive">Активные</key>
<key alias="stateAll">Все</key>
<key alias="stateDisabled">Отключенные</key>
<key alias="stateLockedOut">Заблокированные</key>
<key alias="stateInvited">Приглашенные</key>
<key alias="startnode">Начальный узел содержимого</key>
<key alias="startnodehelp">Можно ограничить доступ к дереву содержимого (какой-либо его части), задав начальный узел</key>
<key alias="startnodes">Начальные узлы содержимого</key>
@@ -1736,6 +1751,7 @@
<key alias="userInvitedSuccessHelp">Новому пользователю было отправлено приглашение, в котором содержатся инструкции для входа в панель Umbraco.</key>
<key alias="userinviteWelcomeMessage">Здравствуйте и добро пожаловать в Umbraco! Все будет готово в течении пары минут, нам лишь нужно задать Ваш пароль для входа и добавить аватар.</key>
<key alias="userinviteAvatarMessage">Загрузите изображение, это поможет другим пользователям идентифицировать Вас.</key>
<key alias="userManagement">Управление пользователями</key>
<key alias="userPermissions">Разрешения для пользователя</key>
<key alias="writer">Автор</key>
<key alias="yourHistory" version="7.0">Ваша недавняя история</key>
+12 -3
View File
@@ -411,7 +411,7 @@
<key alias="showPageOnSend">Vilken sida skall visas när formuläret är skickat</key>
<key alias="size">Storlek</key>
<key alias="sort">Sortera</key>
<key alias="submit">Submit</key> <!-- TODO: Translate this -->
<key alias="submit">Skicka</key>
<key alias="type">Skriv</key>
<key alias="typeToSearch">Skriv för att söka...</key>
<key alias="up">Upp</key>
@@ -426,8 +426,17 @@
<key alias="width">Bredd</key>
<key alias="view">Titta på</key>
<key alias="yes">Ja</key>
<key alias="reorder">Reorder</key>
<key alias="reorderDone">I am done reordering</key>
<key alias="reorder">Sortera</key>
<key alias="reorderDone">Avsluta sortering</key>
<key alias="preview">Förhandsvisning</key>
<key alias="changePassword">Ändra lösenord</key>
<key alias="to">till</key>
<key alias="listView">Listvy</key>
<key alias="saving">Sparar...</key>
<key alias="current">nuvarande</key>
<key alias="embed">Inbäddning</key>
<key alias="retrieve">Hämta</key>
<key alias="selected">valgt</key>
</area>
<area alias="graphicheadline">
<key alias="backgroundcolor">Bakgrundsfärg</key>
@@ -805,13 +805,13 @@ namespace Umbraco.Web.Cache
/// <summary>
/// Used to cache all found event handlers
/// </summary>
private static readonly ConcurrentDictionary<IEventDefinition, MethodInfo> FoundHandlers = new ConcurrentDictionary<IEventDefinition, MethodInfo>();
private static readonly ConcurrentDictionary<string, MethodInfo> FoundHandlers = new ConcurrentDictionary<string, MethodInfo>();
internal static MethodInfo FindHandler(IEventDefinition eventDefinition)
{
var name = eventDefinition.Sender.GetType().Name + "_" + eventDefinition.EventName;
return FoundHandlers.GetOrAdd(eventDefinition, _ => CandidateHandlers.Value.FirstOrDefault(x => x.Name == name));
return FoundHandlers.GetOrAdd(name, n => CandidateHandlers.Value.FirstOrDefault(x => x.Name == n));
}
}
}
@@ -532,6 +532,7 @@ namespace Umbraco.Web.Editors
/// <returns></returns>
[FileUploadCleanupFilter]
[ContentPostValidate]
[OutgoingEditorModelEvent]
public ContentItemDisplay PostSave(
[ModelBinder(typeof(ContentItemBinder))]
ContentItemSave contentItem)
@@ -847,6 +848,7 @@ namespace Umbraco.Web.Editors
/// <param name="id"></param>
/// <returns></returns>
[EnsureUserPermissionForContent("id", 'U')]
[OutgoingEditorModelEvent]
public ContentItemDisplay PostUnPublish(int id)
{
var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id));
@@ -464,6 +464,7 @@ namespace Umbraco.Web.Editors
/// <returns></returns>
[FileUploadCleanupFilter]
[MediaPostValidate]
[OutgoingEditorModelEvent]
public MediaItemDisplay PostSave(
[ModelBinder(typeof(MediaItemBinder))]
MediaItemSave contentItem)
+2 -1
View File
@@ -256,6 +256,7 @@ namespace Umbraco.Web.Editors
/// </summary>
/// <returns></returns>
[FileUploadCleanupFilter]
[OutgoingEditorModelEvent]
public MemberDisplay PostSave(
[ModelBinder(typeof(MemberBinder))]
MemberSave contentItem)
@@ -555,7 +556,7 @@ namespace Umbraco.Web.Editors
var builtInAliases = Constants.Conventions.Member.GetStandardPropertyTypeStubs().Select(x => x.Key).ToArray();
foreach (var p in contentItem.PersistedContent.Properties)
{
var valueMapped = currProps.SingleOrDefault(x => x.Alias == p.Alias);
var valueMapped = currProps.FirstOrDefault(x => x.Alias == p.Alias);
if (builtInAliases.Contains(p.Alias) == false && valueMapped != null)
{
p.Value = valueMapped.Value;
+208
View File
@@ -0,0 +1,208 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Examine;
using Examine.Config;
using Examine.LuceneEngine;
using Examine.LuceneEngine.Providers;
using Examine.Providers;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Umbraco.Core;
using Umbraco.Core.Logging;
using UmbracoExamine;
namespace Umbraco.Web
{
/// <summary>
/// Used to configure Examine during startup for the web application
/// </summary>
internal class ExamineStartup
{
private readonly List<BaseIndexProvider> _indexesToRebuild = new List<BaseIndexProvider>();
private readonly ApplicationContext _appCtx;
private readonly ProfilingLogger _profilingLogger;
private static bool _isConfigured = false;
//this is used if we are not the MainDom, in which case we need to ensure that if indexes need rebuilding that this
//doesn't occur since that should only occur when we are MainDom
private bool _disableExamineIndexing = false;
public ExamineStartup(ApplicationContext appCtx)
{
_appCtx = appCtx;
_profilingLogger = appCtx.ProfilingLogger;
}
/// <summary>
/// Called during the initialize operation of the boot manager process
/// </summary>
public void Initialize()
{
//We want to manage Examine's appdomain shutdown sequence ourselves so first we'll disable Examine's default behavior
//and then we'll use MainDom to control Examine's shutdown
ExamineManager.DisableDefaultHostingEnvironmentRegistration();
//we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain
//terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock
//which simply checks the existence of the lock file
DirectoryTracker.DefaultLockFactory = d =>
{
var simpleFsLockFactory = new NoPrefixSimpleFsLockFactory(d);
return simpleFsLockFactory;
};
//This is basically a hack for this item: http://issues.umbraco.org/issue/U4-5976
// when Examine initializes it will try to rebuild if the indexes are empty, however in many cases not all of Examine's
// event handlers will be assigned during bootup when the rebuilding starts which is a problem. So with the examine 0.1.58.2941 build
// it has an event we can subscribe to in order to cancel this rebuilding process, but what we'll do is cancel it and postpone the rebuilding until the
// boot process has completed. It's a hack but it works.
ExamineManager.Instance.BuildingEmptyIndexOnStartup += OnInstanceOnBuildingEmptyIndexOnStartup;
//let's deal with shutting down Examine with MainDom
var examineShutdownRegistered = _appCtx.MainDom.Register(() =>
{
using (_profilingLogger.TraceDuration<ExamineStartup>("Examine shutting down"))
{
//Due to the way Examine's own IRegisteredObject works, we'll first run it with immediate=false and then true so that
//it's correct subroutines are executed (otherwise we'd have to run this logic manually ourselves)
ExamineManager.Instance.Stop(false);
ExamineManager.Instance.Stop(true);
}
});
if (examineShutdownRegistered)
{
_profilingLogger.Logger.Debug<ExamineStartup>("Examine shutdown registered with MainDom");
}
else
{
_profilingLogger.Logger.Debug<ExamineStartup>("Examine shutdown not registered, this appdomain is not the MainDom");
//if we could not register the shutdown examine ourselves, it means we are not maindom! in this case all of examine should be disabled
//from indexing anything on startup!!
_disableExamineIndexing = true;
Suspendable.ExamineEvents.SuspendIndexers();
}
}
/// <summary>
/// Called during the Complete operation of the boot manager process
/// </summary>
public void Complete()
{
EnsureUnlockedAndConfigured();
//Ok, now that everything is complete we'll check if we've stored any references to index that need rebuilding and run them
// (see the initialize method for notes) - we'll ensure we remove the event handler too in case examine manager doesn't actually
// initialize during startup, in which case we want it to rebuild the indexes itself.
ExamineManager.Instance.BuildingEmptyIndexOnStartup -= OnInstanceOnBuildingEmptyIndexOnStartup;
//don't do anything if we have disabled this
if (_disableExamineIndexing == false)
{
foreach (var indexer in _indexesToRebuild)
{
indexer.RebuildIndex();
}
}
}
/// <summary>
/// Called to perform the rebuilding indexes on startup if the indexes don't exist
/// </summary>
public void RebuildIndexes()
{
//don't do anything if we have disabled this
if (_disableExamineIndexing) return;
EnsureUnlockedAndConfigured();
//If the developer has explicitly opted out of rebuilding indexes on startup then we
// should adhere to that and not do it, this means that if they are load balancing things will be
// out of sync if they are auto-scaling but there's not much we can do about that.
if (ExamineSettings.Instance.RebuildOnAppStart == false) return;
foreach (var indexer in GetIndexesForColdBoot())
{
indexer.RebuildIndex();
}
}
/// <summary>
/// The method used to create indexes on a cold boot
/// </summary>
/// <remarks>
/// A cold boot is when the server determines it will not (or cannot) process instructions in the cache table and
/// will rebuild it's own caches itself.
/// </remarks>
public IEnumerable<BaseIndexProvider> GetIndexesForColdBoot()
{
// NOTE: This is IMPORTANT! ... we don't want to rebuild any index that is already flagged to be re-indexed
// on startup based on our _indexesToRebuild variable and how Examine auto-rebuilds when indexes are empty.
// This callback is used above for the DatabaseServerMessenger startup options.
// all indexes
IEnumerable<BaseIndexProvider> indexes = ExamineManager.Instance.IndexProviderCollection;
// except those that are already flagged
// and are processed in Complete()
if (_indexesToRebuild.Any())
indexes = indexes.Except(_indexesToRebuild);
// return
foreach (var index in indexes)
yield return index;
}
/// <summary>
/// Must be called to configure each index and ensure it's unlocked before any indexing occurs
/// </summary>
/// <remarks>
/// Indexing rebuilding can occur on a normal boot if the indexes are empty or on a cold boot by the database server messenger. Before
/// either of these happens, we need to configure the indexes.
/// </remarks>
private void EnsureUnlockedAndConfigured()
{
if (_isConfigured) return;
_isConfigured = true;
foreach (var luceneIndexer in ExamineManager.Instance.IndexProviderCollection.OfType<LuceneIndexer>())
{
//We now need to disable waiting for indexing for Examine so that the appdomain is shutdown immediately and doesn't wait for pending
//indexing operations. We used to wait for indexing operations to complete but this can cause more problems than that is worth because
//that could end up halting shutdown for a very long time causing overlapping appdomains and many other problems.
luceneIndexer.WaitForIndexQueueOnShutdown = false;
//we should check if the index is locked ... it shouldn't be! We are using simple fs lock now and we are also ensuring that
//the indexes are not operational unless MainDom is true so if _disableExamineIndexing is false then we should be in charge
if (_disableExamineIndexing == false)
{
var dir = luceneIndexer.GetLuceneDirectory();
if (IndexWriter.IsLocked(dir))
{
_profilingLogger.Logger.Info<ExamineStartup>("Forcing index " + luceneIndexer.IndexSetName + " to be unlocked since it was left in a locked state");
IndexWriter.Unlock(dir);
}
}
}
}
private void OnInstanceOnBuildingEmptyIndexOnStartup(object sender, BuildingEmptyIndexOnStartupEventArgs args)
{
//store the indexer that needs rebuilding because it's empty for when the boot process
// is complete and cancel this current event so the rebuild process doesn't start right now.
args.Cancel = true;
_indexesToRebuild.Add((BaseIndexProvider)args.Indexer);
//check if the index is rebuilding due to an error and log it
if (args.IsHealthy == false)
{
var baseIndex = args.Indexer as BaseIndexProvider;
var name = baseIndex != null ? baseIndex.Name : "[UKNOWN]";
_profilingLogger.Logger.Error<ExamineStartup>(string.Format("The index {0} is rebuilding due to being unreadable/corrupt", name), args.UnhealthyException);
}
}
}
}
@@ -52,7 +52,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(display => display.Alias, expression => expression.Ignore())
.ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(applicationContext.Services.TextService)))
.ForMember(display => display.AllowedActions, expression => expression.ResolveUsing(
new ActionButtonsResolver(new Lazy<IUserService>(() => applicationContext.Services.UserService))))
new ActionButtonsResolver(new Lazy<IUserService>(() => applicationContext.Services.UserService), new Lazy<IContentService>(() => applicationContext.Services.ContentService))))
.AfterMap((content, display) => AfterMap(content, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService,
applicationContext.Services.ContentTypeService));
@@ -219,10 +219,14 @@ namespace Umbraco.Web.Models.Mapping
private class ActionButtonsResolver : ValueResolver<IContent, IEnumerable<string>>
{
private readonly Lazy<IUserService> _userService;
private readonly Lazy<IContentService> _contentService;
public ActionButtonsResolver(Lazy<IUserService> userService)
public ActionButtonsResolver(Lazy<IUserService> userService, Lazy<IContentService> contentService)
{
if (userService == null) throw new ArgumentNullException("userService");
if (contentService == null) throw new ArgumentNullException("contentService");
_userService = userService;
_contentService = contentService;
}
protected override IEnumerable<string> ResolveCore(IContent source)
@@ -234,14 +238,21 @@ namespace Umbraco.Web.Models.Mapping
}
var svc = _userService.Value;
var permissions = svc.GetPermissions(
string path;
if (source.HasIdentity)
path = source.Path;
else
{
var parent = _contentService.Value.GetById(source.ParentId);
path = parent == null ? "-1" : parent.Path;
}
var permissions = svc.GetPermissionsForPath(
//TODO: This is certainly not ideal usage here - perhaps the best way to deal with this in the future is
// with the IUmbracoContextAccessor. In the meantime, if used outside of a web app this will throw a null
// refrence exception :(
UmbracoContext.Current.Security.CurrentUser,
// Here we need to do a special check since this could be new content, in which case we need to get the permissions
// from the parent, not the existing one otherwise permissions would be coming from the root since Id is 0.
source.HasIdentity ? source.Id : source.ParentId)
path)
.GetAllPermissions();
return permissions;
@@ -74,11 +74,47 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
public virtual IEnumerable<IPublishedContent> GetAtRoot(UmbracoContext umbracoContext, bool preview)
{
//TODO: We should be able to look these ids first in Examine!
var searchProvider = GetSearchProviderSafe();
if (searchProvider != null)
{
try
{
// first check in Examine for the cache values
// +(+parentID:-1) +__IndexType:media
var criteria = searchProvider.CreateSearchCriteria("media");
var filter = criteria.ParentId(-1).Not().Field(UmbracoContentIndexer.IndexPathFieldName, "-1,-21,".MultipleCharacterWildcard());
var result = searchProvider.Search(filter.Compile());
if (result != null)
return result.Select(x => CreateFromCacheValues(ConvertFromSearchResult(x)));
}
catch (Exception ex)
{
if (ex is FileNotFoundException)
{
//Currently examine is throwing FileNotFound exceptions when we have a loadbalanced filestore and a node is published in umbraco
//See this thread: http://examine.cdodeplex.com/discussions/264341
//Catch the exception here for the time being, and just fallback to GetMedia
//TODO: Need to fix examine in LB scenarios!
LogHelper.Error<PublishedMediaCache>("Could not load data from Examine index for media", ex);
}
else if (ex is AlreadyClosedException)
{
//If the app domain is shutting down and the site is under heavy load the index reader will be closed and it really cannot
//be re-opened since the app domain is shutting down. In this case we have no option but to try to load the data from the db.
LogHelper.Error<PublishedMediaCache>("Could not load data from Examine index for media, the app domain is most likely in a shutdown state", ex);
}
else throw;
}
}
//something went wrong, fetch from the db
var rootMedia = _applicationContext.Services.MediaService.GetRootMedia();
return rootMedia.Select(m => GetUmbracoMedia(m.Id));
}
return rootMedia.Select(m => CreateFromCacheValues(ConvertFromIMedia(m)));
}
public virtual IPublishedContent GetSingleByXPath(UmbracoContext umbracoContext, bool preview, string xpath, XPathVariable[] vars)
{
+1 -1
View File
@@ -230,7 +230,7 @@ namespace Umbraco.Web
{
// todo: in v8, implement in a more efficient way
var legacyXml = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema;
var xpath = legacyXml ? "//node [@key=$guid]" : "//* [@isDoc and @key=$guid]";
var xpath = legacyXml ? "//node [@key=$guid]" : "//* [@key=$guid]";
var doc = cache.GetSingleByXPath(xpath, new XPathVariable("guid", id.ToString()));
return doc;
}
@@ -86,7 +86,16 @@ namespace Umbraco.Web.Scheduling
finally
{
if (tempContext != null)
{
// because we created an http context and assigned it to UmbracoContext,
// the batched messenger does batch instructions, but since there is no
// request, we need to explicitely tell it to flush the batch of instrs.
var batchedMessenger = ServerMessengerResolver.Current.Messenger as BatchedDatabaseServerMessenger;
if (batchedMessenger != null)
batchedMessenger.FlushBatch();
tempContext.Dispose(); // nulls the ThreadStatic context
}
}
return true; // repeat
+3 -4
View File
@@ -112,8 +112,8 @@
<Reference Include="dotless.Core, Version=1.5.2.0, Culture=neutral, PublicKeyToken=96b446c9e63eae34, processorArchitecture=MSIL">
<HintPath>..\packages\dotless.1.5.2\lib\dotless.Core.dll</HintPath>
</Reference>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
@@ -121,11 +121,9 @@
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="MarkdownSharp, Version=1.14.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Markdown.1.14.7\lib\net45\MarkdownSharp.dll</HintPath>
@@ -333,6 +331,7 @@
<Compile Include="Editors\UserGroupEditorAuthorizationHelper.cs" />
<Compile Include="Editors\UserGroupsController.cs" />
<Compile Include="Editors\UserGroupValidateAttribute.cs" />
<Compile Include="ExamineStartup.cs" />
<Compile Include="Extensions\UdiExtensions.cs" />
<Compile Include="HealthCheck\Checks\Config\AbstractConfigCheck.cs" />
<Compile Include="HealthCheck\Checks\Config\AcceptableConfiguration.cs" />
+1 -10
View File
@@ -97,17 +97,8 @@ namespace Umbraco.Web.WebApi.Binders
if (member == null)
{
throw new InvalidOperationException("Could not find member with key " + key);
}
}
var standardProps = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
//remove all membership properties, these values are set with the membership provider.
var exclude = standardProps.Select(x => x.Value.Alias).ToArray();
foreach (var remove in exclude)
{
member.Properties.Remove(remove);
}
return member;
}
+17 -89
View File
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Configuration;
using System.Web.Http;
@@ -11,10 +10,7 @@ using System.Web.Http.Dispatcher;
using System.Web.Mvc;
using System.Web.Routing;
using ClientDependency.Core.Config;
using Examine;
using Examine.Config;
using Examine.Providers;
using umbraco;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Dictionary;
@@ -27,25 +23,18 @@ using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Core.Sync;
using Umbraco.Web.Dictionary;
using Umbraco.Web.Install;
using Umbraco.Web.Macros;
using Umbraco.Web.Media;
using Umbraco.Web.Media.ThumbnailProviders;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
using Umbraco.Web.PropertyEditors;
using Umbraco.Web.PropertyEditors.ValueConverters;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
using Umbraco.Web.Scheduling;
using Umbraco.Web.UI.JavaScript;
using Umbraco.Web.WebApi;
using umbraco.BusinessLogic;
using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Web.Editors;
@@ -64,8 +53,9 @@ namespace Umbraco.Web
public class WebBootManager : CoreBootManager
{
private readonly bool _isForTesting;
//NOTE: see the Initialize method for what this is used for
private static readonly List<BaseIndexProvider> IndexesToRebuild = new List<BaseIndexProvider>();
//needs to be static because we have the public static method GetIndexesForColdBoot
private static ExamineStartup _examineStartup;
public WebBootManager(UmbracoApplicationBase umbracoApplication)
: base(umbracoApplication)
@@ -109,15 +99,11 @@ namespace Umbraco.Web
/// <returns></returns>
public override IBootManager Initialize()
{
//This is basically a hack for this item: http://issues.umbraco.org/issue/U4-5976
// when Examine initializes it will try to rebuild if the indexes are empty, however in many cases not all of Examine's
// event handlers will be assigned during bootup when the rebuilding starts which is a problem. So with the examine 0.1.58.2941 build
// it has an event we can subscribe to in order to cancel this rebuilding process, but what we'll do is cancel it and postpone the rebuilding until the
// boot process has completed. It's a hack but it works.
ExamineManager.Instance.BuildingEmptyIndexOnStartup += OnInstanceOnBuildingEmptyIndexOnStartup;
base.Initialize();
_examineStartup = new ExamineStartup(ApplicationContext);
_examineStartup.Initialize();
// Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK]
ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency";
ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings;
@@ -214,25 +200,15 @@ namespace Umbraco.Web
//Now, startup all of our legacy startup handler
ApplicationEventsResolver.Current.InstantiateLegacyStartupHandlers();
//Ok, now that everything is complete we'll check if we've stored any references to index that need rebuilding and run them
// (see the initialize method for notes) - we'll ensure we remove the event handler too in case examine manager doesn't actually
// initialize during startup, in which case we want it to rebuild the indexes itself.
ExamineManager.Instance.BuildingEmptyIndexOnStartup -= OnInstanceOnBuildingEmptyIndexOnStartup;
if (IndexesToRebuild.Any())
{
foreach (var indexer in IndexesToRebuild)
{
indexer.RebuildIndex();
}
}
_examineStartup.Complete();
//Now ensure webapi is initialized after everything
GlobalConfiguration.Configuration.EnsureInitialized();
return this;
}
internal static void ConfigureGlobalFilters()
{
@@ -377,11 +353,11 @@ namespace Umbraco.Web
{
base.InitializeResolvers();
SearchableTreeResolver.Current = new SearchableTreeResolver(ServiceProvider, LoggerResolver.Current.Logger, ApplicationContext.Services.ApplicationTreeService, () => PluginManager.ResolveSearchableTrees());
SearchableTreeResolver.Current = new SearchableTreeResolver(ServiceProvider, LoggerResolver.Current.Logger, ApplicationContext.Services.ApplicationTreeService, () => PluginManager.ResolveSearchableTrees());
XsltExtensionsResolver.Current = new XsltExtensionsResolver(ServiceProvider, LoggerResolver.Current.Logger, () => PluginManager.ResolveXsltExtensions());
EditorValidationResolver.Current= new EditorValidationResolver(ServiceProvider, LoggerResolver.Current.Logger, () => PluginManager.ResolveTypes<IEditorValidator>());
EditorValidationResolver.Current = new EditorValidationResolver(ServiceProvider, LoggerResolver.Current.Logger, () => PluginManager.ResolveTypes<IEditorValidator>());
//set the default RenderMvcController
DefaultRenderMvcControllerResolver.Current = new DefaultRenderMvcControllerResolver(typeof(RenderMvcController));
@@ -421,23 +397,6 @@ namespace Umbraco.Web
}
else
{
//We are using a custom action here so we can check the examine settings value first, we don't want to
// put that check into the CreateIndexesOnColdBoot method because developers may choose to use this
// method directly and they will be in charge of this check if they need it
Action rebuildIndexes = () =>
{
//If the developer has explicitly opted out of rebuilding indexes on startup then we
// should adhere to that and not do it, this means that if they are load balancing things will be
// out of sync if they are auto-scaling but there's not much we can do about that.
if (ExamineSettings.Instance.RebuildOnAppStart == false) return;
foreach (var indexer in GetIndexesForColdBoot())
{
indexer.RebuildIndex();
}
};
ServerMessengerResolver.Current.SetServerMessenger(new BatchedDatabaseServerMessenger(
ApplicationContext,
true,
@@ -453,7 +412,7 @@ namespace Umbraco.Web
//rebuild indexes if the server is not synced
// NOTE: This will rebuild ALL indexes including the members, if developers want to target specific
// indexes then they can adjust this logic themselves.
rebuildIndexes
() => _examineStartup.RebuildIndexes()
}
}));
}
@@ -489,9 +448,9 @@ namespace Umbraco.Web
// add all known factories, devs can then modify this list on application
// startup either by binding to events or in their own global.asax
new[]
{
typeof (RenderControllerFactory)
});
{
typeof (RenderControllerFactory)
});
UrlProviderResolver.Current = new UrlProviderResolver(
ServiceProvider, LoggerResolver.Current.Logger,
@@ -559,42 +518,11 @@ namespace Umbraco.Web
/// <remarks>
/// A cold boot is when the server determines it will not (or cannot) process instructions in the cache table and
/// will rebuild it's own caches itself.
/// TODO: Does this method need to exist? Is it used publicly elsewhere (i.e. outside of core?)
/// </remarks>
public static IEnumerable<BaseIndexProvider> GetIndexesForColdBoot()
{
// NOTE: This is IMPORTANT! ... we don't want to rebuild any index that is already flagged to be re-indexed
// on startup based on our _indexesToRebuild variable and how Examine auto-rebuilds when indexes are empty.
// This callback is used above for the DatabaseServerMessenger startup options.
// all indexes
IEnumerable<BaseIndexProvider> indexes = ExamineManager.Instance.IndexProviderCollection;
// except those that are already flagged
// and are processed in Complete()
if (IndexesToRebuild.Any())
indexes = indexes.Except(IndexesToRebuild);
// return
foreach (var index in indexes)
yield return index;
}
private void OnInstanceOnBuildingEmptyIndexOnStartup(object sender, BuildingEmptyIndexOnStartupEventArgs args)
{
//store the indexer that needs rebuilding because it's empty for when the boot process
// is complete and cancel this current event so the rebuild process doesn't start right now.
args.Cancel = true;
IndexesToRebuild.Add((BaseIndexProvider)args.Indexer);
//check if the index is rebuilding due to an error and log it
if (args.IsHealthy == false)
{
var baseIndex = args.Indexer as BaseIndexProvider;
var name = baseIndex != null ? baseIndex.Name : "[UKNOWN]";
ProfilingLogger.Logger.Error<WebBootManager>(string.Format("The index {0} is rebuilding due to being unreadable/corrupt", name), args.UnhealthyException);
}
return _examineStartup.GetIndexesForColdBoot();
}
}
}
@@ -8,7 +8,9 @@ using Examine;
using Examine.LuceneEngine;
using Examine.LuceneEngine.Providers;
using Examine.Providers;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Web.Search;
@@ -189,20 +191,39 @@ namespace Umbraco.Web.WebServices
{
indexer.RebuildIndex();
}
catch (LockObtainFailedException)
{
//this will occur if the index is locked (which it should defo not be!) so in this case we'll forcibly unlock it and try again
try
{
IndexWriter.Unlock(indexer.GetLuceneDirectory());
indexer.RebuildIndex();
}
catch (Exception e)
{
return HandleException(e, indexer);
}
}
catch (Exception ex)
{
//ensure it's not listening
indexer.IndexOperationComplete -= Indexer_IndexOperationComplete;
LogHelper.Error<ExamineManagementApiController>("An error occurred rebuilding index", ex);
var response = Request.CreateResponse(HttpStatusCode.Conflict);
response.Content = new StringContent(string.Format("The index could not be rebuilt at this time, most likely there is another thread currently writing to the index. Error: {0}", ex));
response.ReasonPhrase = "Could Not Rebuild";
return response;
return HandleException(ex, indexer);
}
}
return msg;
}
private HttpResponseMessage HandleException(Exception ex, LuceneIndexer indexer)
{
//ensure it's not listening
indexer.IndexOperationComplete -= Indexer_IndexOperationComplete;
LogHelper.Error<ExamineManagementApiController>("An error occurred rebuilding index", ex);
var response = Request.CreateResponse(HttpStatusCode.Conflict);
response.Content = new StringContent(string.Format("The index could not be rebuilt at this time, most likely there is another thread currently writing to the index. Error: {0}", ex));
response.ReasonPhrase = "Could Not Rebuild";
return response;
}
//static listener so it's not GC'd
private static void Indexer_IndexOperationComplete(object sender, EventArgs e)
{
+1 -1
View File
@@ -3,7 +3,7 @@
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.2" targetFramework="net45" />
<package id="dotless" version="1.5.2" targetFramework="net45" />
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="Markdown" version="1.14.7" targetFramework="net45" />
+8 -3
View File
@@ -150,7 +150,7 @@ namespace UmbracoExamine
{
//By default, we will be using the UmbracoDataService
//generally this would only need to be set differently for unit testing
DataService = new UmbracoDataService();
DataService = CreateDefaultUmbracoDataService();
}
DataService.LogService.LogLevel = LoggingLevel.Normal;
@@ -206,10 +206,15 @@ namespace UmbracoExamine
}
}
}
}
#endregion
protected virtual IDataService CreateDefaultUmbracoDataService()
{
return new UmbracoDataService();
}
/// <summary>
/// Used to aquire the internal searcher
/// </summary>
@@ -13,10 +13,12 @@ namespace UmbracoExamine.Config
/// </summary>
public static class IndexSetExtensions
{
internal static IIndexCriteria ToIndexCriteria(this IndexSet set, IDataService svc,
StaticFieldCollection indexFieldPolicies)
internal static IIndexCriteria ToIndexCriteria(this IndexSet set,
IDataService svc,
StaticFieldCollection indexFieldPolicies,
IEnumerable<IndexField> additionalUserFields = null)
{
return new LazyIndexCriteria(set, svc, indexFieldPolicies);
return new LazyIndexCriteria(set, svc, indexFieldPolicies, additionalUserFields);
}
/// <summary>
+17 -3
View File
@@ -12,7 +12,8 @@ namespace UmbracoExamine.Config
public LazyIndexCriteria(
IndexSet set,
IDataService svc,
StaticFieldCollection indexFieldPolicies)
StaticFieldCollection indexFieldPolicies,
IEnumerable<IndexField> additionalUserFields = null)
{
if (set == null) throw new ArgumentNullException("set");
if (indexFieldPolicies == null) throw new ArgumentNullException("indexFieldPolicies");
@@ -21,7 +22,7 @@ namespace UmbracoExamine.Config
_lazyCriteria = new Lazy<IIndexCriteria>(() =>
{
var attributeFields = set.IndexAttributeFields.Cast<IIndexField>().ToArray();
var userFields = set.IndexUserFields.Cast<IIndexField>().ToArray();
var userFields = set.IndexUserFields.Cast<IIndexField>().ToList();
var includeNodeTypes = set.IncludeNodeTypes.Cast<IIndexField>().Select(x => x.Name).ToArray();
var excludeNodeTypes = set.ExcludeNodeTypes.Cast<IIndexField>().Select(x => x.Name).ToArray();
var parentId = set.IndexParentId;
@@ -44,7 +45,7 @@ namespace UmbracoExamine.Config
}
fields.Add(field);
}
userFields = fields.ToArray();
userFields = fields.ToList();
}
//if there are no attribute fields defined, we'll populate them from the data source (include them all)
@@ -68,6 +69,19 @@ namespace UmbracoExamine.Config
attributeFields = fields.ToArray();
}
//merge in the additional user fields if any are defined
if (additionalUserFields != null)
{
foreach (var field in additionalUserFields)
{
var f = field; //copy local
if (userFields.Any(x => x.Name == f.Name) == false)
{
userFields.Add(f);
}
}
}
return new IndexCriteria(
attributeFields,
@@ -13,7 +13,7 @@ namespace UmbracoExamine.DataServices
{
public class UmbracoContentService : IContentService
{
private readonly ApplicationContext _applicationContext;
protected ApplicationContext ApplicationContext { get; private set; }
public UmbracoContentService()
: this(ApplicationContext.Current)
@@ -21,7 +21,7 @@ namespace UmbracoExamine.DataServices
public UmbracoContentService(ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
ApplicationContext = applicationContext;
}
/// <summary>
@@ -60,11 +60,11 @@ namespace UmbracoExamine.DataServices
using (var scope = ApplicationContext.Current.ScopeProvider.CreateScope())
{
var xmlContent = XDocument.Parse("<content></content>");
var rootContent = _applicationContext.Services.ContentService.GetRootContent();
var rootContent = ApplicationContext.Services.ContentService.GetRootContent();
foreach (var c in rootContent)
{
// not sure this uses the database, but better be save
xmlContent.Root.Add(c.ToDeepXml(_applicationContext.Services.PackagingService));
xmlContent.Root.Add(c.ToDeepXml(ApplicationContext.Services.PackagingService));
}
var result = ((IEnumerable)xmlContent.XPathEvaluate(xpath)).Cast<XElement>();
scope.Complete();
@@ -82,7 +82,7 @@ namespace UmbracoExamine.DataServices
{
using (var scope = ApplicationContext.Current.ScopeProvider.CreateScope())
{
var ret = _applicationContext.Services.PublicAccessService.IsProtected(path.EnsureEndsWith("," + nodeId));
var ret = ApplicationContext.Services.PublicAccessService.IsProtected(path.EnsureEndsWith("," + nodeId));
scope.Complete();
return ret;
}
@@ -93,14 +93,26 @@ namespace UmbracoExamine.DataServices
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetAllUserPropertyNames()
public virtual IEnumerable<string> GetAllUserPropertyNames()
{
using (var scope = ApplicationContext.Current.ScopeProvider.CreateScope())
{
try
{
var result = _applicationContext.DatabaseContext.Database.Fetch<string>("select distinct alias from cmsPropertyType order by alias");
scope.Complete();
{
//only return the property type aliases for media and content
var result = ApplicationContext.DatabaseContext.Database.Fetch<string>(
@"select distinct cmsPropertyType.alias from cmsPropertyType
inner join cmsContentType on cmsContentType.nodeId = cmsPropertyType.contentTypeId
inner join umbracoNode on umbracoNode.id = cmsContentType.nodeId
where umbracoNode.nodeObjectType = @contentNodeObjectType OR umbracoNode.nodeObjectType = @mediaNodeObjectType
order by alias", new
{
contentNodeObjectType = Constants.ObjectTypes.DocumentType,
mediaNodeObjectType = Constants.ObjectTypes.MediaType
});
scope.Complete();
return result;
}
catch (Exception ex)
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Logging;
namespace UmbracoExamine.DataServices
{
public class UmbracoMemberContentService : UmbracoContentService
{
public override IEnumerable<string> GetAllUserPropertyNames()
{
using (var scope = ApplicationContext.Current.ScopeProvider.CreateScope())
{
try
{
//only return the property type aliases for members
var result = ApplicationContext.DatabaseContext.Database.Fetch<string>(
@"select distinct cmsPropertyType.alias from cmsPropertyType
inner join cmsContentType on cmsContentType.nodeId = cmsPropertyType.contentTypeId
inner join umbracoNode on umbracoNode.id = cmsContentType.nodeId
where umbracoNode.nodeObjectType = @nodeObjectType
order by alias", new {nodeObjectType = Constants.ObjectTypes.MemberType});
scope.Complete();
return result;
}
catch (Exception ex)
{
LogHelper.Error<UmbracoMemberContentService>("EXCEPTION OCCURRED reading GetAllUserPropertyNames", ex);
return Enumerable.Empty<string>();
}
}
}
}
}
@@ -0,0 +1,10 @@
namespace UmbracoExamine.DataServices
{
public class UmbracoMemberDataService : UmbracoDataService
{
public UmbracoMemberDataService()
{
ContentService = new UmbracoMemberContentService();
}
}
}
@@ -0,0 +1,26 @@
using System.IO;
using Examine;
using Examine.LuceneEngine;
using Lucene.Net.Store;
namespace UmbracoExamine
{
/// <summary>
/// A custom <see cref="SimpleFSLockFactory"/> that ensures a prefixless lock prefix
/// </summary>
/// <remarks>
/// This is a work around for the Lucene APIs. By default Lucene will use a null prefix however when we set a custom
/// lock factory the null prefix is overwritten.
/// </remarks>
public class NoPrefixSimpleFsLockFactory : SimpleFSLockFactory
{
public NoPrefixSimpleFsLockFactory(DirectoryInfo lockDir) : base(lockDir)
{
}
public override void SetLockPrefix(string lockPrefix)
{
base.SetLockPrefix(null);
}
}
}
+7 -3
View File
@@ -410,7 +410,11 @@ namespace UmbracoExamine
{
if (SupportedTypes.Contains(type) == false)
return;
//if the app is shutting down do not continue
if (IsCancellationRequested)
return;
var pageIndex = 0;
DataService.LogService.AddInfoLog(-1, string.Format("PerformIndexAll - Start data queries - {0}", type));
@@ -530,7 +534,7 @@ namespace UmbracoExamine
content, notPublished).WhereNotNull(), type);
pageIndex++;
} while (currentPageSize == PageSize);
} while (currentPageSize == PageSize && IsCancellationRequested == false); //do not continue if app is shutting down
}
break;
@@ -628,7 +632,7 @@ namespace UmbracoExamine
AddNodesToIndex(xElements, type);
pageIndex++;
} while (more);
} while (more && IsCancellationRequested == false); //don't continue if the app is shutting down
}
internal static IEnumerable<XElement> GetSerializedContent(
+5 -4
View File
@@ -82,16 +82,14 @@
<AssemblyOriginatorKeyFile>..\Solution Items\TheFARM-Public.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
@@ -119,6 +117,8 @@
<Compile Include="DataServices\UmbracoDataService.cs" />
<Compile Include="DataServices\UmbracoContentService.cs" />
<Compile Include="DataServices\UmbracoMediaService.cs" />
<Compile Include="DataServices\UmbracoMemberContentService.cs" />
<Compile Include="DataServices\UmbracoMemberDataService.cs" />
<Compile Include="DeletePolicyTracker.cs" />
<Compile Include="ExamineHelper.cs" />
<Compile Include="IndexTypes.cs" />
@@ -134,6 +134,7 @@
<Compile Include="LocalStorage\MultiIndexLockFactory.cs" />
<Compile Include="LocalStorage\MultiIndexOutput.cs" />
<Compile Include="LoggingLevel.cs" />
<Compile Include="NoPrefixSimpleFsLockFactory.cs" />
<Compile Include="StaticField.cs" />
<Compile Include="StaticFieldCollection.cs" />
<Compile Include="UmbracoMemberIndexer.cs" />
+26 -27
View File
@@ -19,6 +19,8 @@ using Lucene.Net.Analysis;
namespace UmbracoExamine
{
/// <summary>
/// Custom indexer for members
/// </summary>
@@ -101,6 +103,11 @@ namespace UmbracoExamine
_memberTypeService = memberTypeService;
}
protected override IDataService CreateDefaultUmbracoDataService()
{
return new UmbracoMemberDataService();
}
/// <summary>
/// Ensures that the'_searchEmail' is added to the user fields so that it is indexed - without having to modify the config
/// </summary>
@@ -108,34 +115,26 @@ namespace UmbracoExamine
/// <returns></returns>
protected override IIndexCriteria GetIndexerData(IndexSet indexSet)
{
var indexerData = base.GetIndexerData(indexSet);
if (CanInitialize())
{
//If the fields are missing a custom _searchEmail, then add it
if (indexerData.UserFields.Any(x => x.Name == "_searchEmail") == false)
//Add a custom _searchEmail to the index criteria no matter what is in config
var field = new IndexField { Name = "_searchEmail" };
StaticField policy;
if (IndexFieldPolicies.TryGetValue("_searchEmail", out policy))
{
var field = new IndexField { Name = "_searchEmail" };
StaticField policy;
if (IndexFieldPolicies.TryGetValue("_searchEmail", out policy))
{
field.Type = policy.Type;
field.EnableSorting = policy.EnableSorting;
}
return new IndexCriteria(
indexerData.StandardFields,
indexerData.UserFields.Concat(new[] { field }),
indexerData.IncludeNodeTypes,
indexerData.ExcludeNodeTypes,
indexerData.ParentNodeId
);
field.Type = policy.Type;
field.EnableSorting = policy.EnableSorting;
}
}
return indexerData;
return indexSet.ToIndexCriteria(DataService, IndexFieldPolicies,
//add additional explicit fields
new []{field});
}
else
{
return base.GetIndexerData(indexSet);
}
}
/// <summary>
@@ -198,7 +197,7 @@ namespace UmbracoExamine
AddNodesToIndex(GetSerializedMembers(members), type);
pageIndex++;
} while (members.Length == pageSize);
} while (members.Length == pageSize && IsCancellationRequested == false); //don't continue if the app is shutting down
}
}
else
@@ -212,7 +211,7 @@ namespace UmbracoExamine
AddNodesToIndex(GetSerializedMembers(members), type);
pageIndex++;
} while (members.Length == pageSize);
} while (members.Length == pageSize && IsCancellationRequested == false); //don't continue if the app is shutting down
}
}
}
@@ -233,8 +232,8 @@ namespace UmbracoExamine
protected override XDocument GetXDocument(string xPath, string type)
{
throw new NotSupportedException();
}
}
/// <summary>
/// Add the special __key and _searchEmail fields
/// </summary>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
</packages>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Examine" version="0.1.88" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
@@ -45,8 +45,8 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Examine, Version=0.1.88.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.88\lib\net45\Examine.dll</HintPath>
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89\lib\net45\Examine.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
@@ -54,11 +54,9 @@
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
@@ -108,11 +108,9 @@
<ItemGroup>
<Reference Include="AutoMapper, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
@@ -122,11 +120,9 @@
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
@@ -145,27 +141,21 @@
</Reference>
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml">
<Name>System.XML</Name>
-4
View File
@@ -108,15 +108,12 @@
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.9.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.2\lib\net45\ClientDependency.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
@@ -168,7 +165,6 @@
<Reference Include="System.Xml.Linq" />
<Reference Include="TidyNet, Version=1.0.0.0, Culture=neutral">
<HintPath>..\packages\Tidy.Net.1.0.0\lib\TidyNet.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -70,7 +70,6 @@
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.9.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.2\lib\net45\ClientDependency.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
@@ -70,10 +70,10 @@
<ItemGroup>
<Reference Include="Microsoft.ApplicationBlocks.Data, Version=1.0.1559.20655, Culture=neutral">
<HintPath>..\packages\Microsoft.ApplicationBlocks.Data.1.0.1559.20655\lib\Microsoft.ApplicationBlocks.Data.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
@@ -116,7 +116,6 @@
</ProjectReference>
<Reference Include="ClientDependency.Core, Version=1.9.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.2\lib\net45\ClientDependency.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System">
<Name>System</Name>