{{ variant.language.name }}
{{ variant.state }}
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
index b8df84ad25..85cb96864e 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
@@ -1415,8 +1415,8 @@ To manage your website, simply open the Umbraco back office and start adding con
An error occurred while unlocking the user
Member was exported to file
An error occurred while exporting the member
-
Validation failed for mandatory language '%0%'
-
Validation failed for language '%0%'
+
Cannot publish the document since the required '%0%' is not published
+
Validation failed for language '%0%'
Uses CSS syntax ex: h1, .redHeader, .blueTex
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs
index 691938c771..4f8051640a 100644
--- a/src/Umbraco.Web/Editors/ContentController.cs
+++ b/src/Umbraco.Web/Editors/ContentController.cs
@@ -631,21 +631,12 @@ namespace Umbraco.Web.Editors
wasCancelled = sendResult == false;
}
else
- {
- //publish the item and check if it worked, if not we will show a diff msg below
- contentItem.PersistedContent.TryPublishValues(contentItem.Culture); //we are not checking for a return value here because we've already pre-validated the property values
-
- //check if we are publishing other variants and validate them
+ {
+ //check if we are publishing other variants and validate them
var allLangs = Services.LocalizationService.GetAllLanguages().ToDictionary(x => x.IsoCode, x => x, StringComparer.InvariantCultureIgnoreCase);
var variantsToValidate = contentItem.PublishVariations.Where(x => !x.Culture.InvariantEquals(contentItem.Culture)).ToList();
- foreach (var publishVariation in variantsToValidate)
- {
- if (!contentItem.PersistedContent.TryPublishValues(publishVariation.Culture))
- {
- var errMsg = Services.TextService.Localize("speechBubbles/contentLangValidationError", new[] {allLangs[publishVariation.Culture].CultureName});
- ModelState.AddModelError("publish_variant_" + publishVariation.Culture + "_", errMsg);
- }
- }
+
+ var canPublish = true;
//validate any mandatory variants that are not in the list
var mandatoryLangs = Mapper.Map
, IEnumerable>(allLangs.Values)
@@ -653,16 +644,51 @@ namespace Umbraco.Web.Editors
.Where(x => !x.IsoCode.InvariantEquals(contentItem.Culture)) //don't include the current variant
.Where(x => x.Mandatory);
foreach (var lang in mandatoryLangs)
- {
- if (contentItem.PersistedContent.Validate(lang.IsoCode).Length > 0)
- {
- var errMsg = Services.TextService.Localize("speechBubbles/contentReqLangValidationError", new[]{allLangs[lang.IsoCode].CultureName});
- ModelState.AddModelError("publish_variant_" + lang.Id + "_", errMsg);
+ {
+ //cannot continue publishing since a required language that is not currently being published isn't published
+ if (!contentItem.PersistedContent.IsCulturePublished(lang.IsoCode))
+ {
+ var errMsg = Services.TextService.Localize("speechBubbles/contentReqCulturePublishError", new[] { allLangs[lang.IsoCode].CultureName });
+ ModelState.AddModelError("publish_variant_" + lang.Id + "_", errMsg);
+ canPublish = false;
}
}
-
- publishStatus = Services.ContentService.SaveAndPublish(contentItem.PersistedContent, Security.CurrentUser.Id);
- wasCancelled = publishStatus.Result == PublishResultType.FailedCancelledByEvent;
+
+ if (canPublish)
+ {
+ //validate all variants to be published
+ foreach (var publishVariation in variantsToValidate)
+ {
+ var invalid = contentItem.PersistedContent.Validate(publishVariation.Culture).Any();
+ if (invalid)
+ {
+ var errMsg = Services.TextService.Localize("speechBubbles/contentCultureValidationError", new[] { allLangs[publishVariation.Culture].CultureName });
+ ModelState.AddModelError("publish_variant_" + publishVariation.Culture + "_", errMsg);
+ canPublish = false;
+ }
+ }
+ }
+
+ if (canPublish)
+ {
+ //set all publish values for the variant we are publishing and those variants flagged for publishing
+ //we are not checking for a return value here because we've already pre-validated the property values.
+ contentItem.PersistedContent.TryPublishValues(contentItem.Culture);
+ foreach (var publishVariation in variantsToValidate)
+ {
+ contentItem.PersistedContent.TryPublishValues(publishVariation.Culture);
+ }
+
+ publishStatus = Services.ContentService.SaveAndPublish(contentItem.PersistedContent, Security.CurrentUser.Id);
+ wasCancelled = publishStatus.Result == PublishResultType.FailedCancelledByEvent;
+ }
+ else
+ {
+ //can only save
+ var saveResult = Services.ContentService.Save(contentItem.PersistedContent, Security.CurrentUser.Id);
+ publishStatus = new PublishResult(PublishResultType.Failed, null, contentItem.PersistedContent);
+ wasCancelled = saveResult.Result == OperationResultType.FailedCancelledByEvent;
+ }
}
//get the updated model
@@ -907,20 +933,21 @@ namespace Umbraco.Web.Editors
///
/// Unpublishes a node with a given Id and returns the unpublished entity
///
- ///
+ /// The content id to unpublish
+ /// The culture variant for the content id to unpublish, if none specified will unpublish all variants of the content
///
[EnsureUserPermissionForContent("id", 'U')]
[OutgoingEditorModelEvent]
- public ContentItemDisplay PostUnPublish(int id)
+ public ContentItemDisplay PostUnPublish(int id, string culture = null)
{
var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id));
if (foundContent == null)
HandleContentNotFound(id);
- var unpublishResult = Services.ContentService.Unpublish(foundContent, Security.CurrentUser.Id);
+ var unpublishResult = Services.ContentService.Unpublish(foundContent, culture:culture, userId: Security.CurrentUser.Id);
- var content = MapToDisplay(foundContent);
+ var content = MapToDisplay(foundContent, culture);
if (unpublishResult.Success == false)
{
diff --git a/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs b/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs
index 26b4332bca..e0b2746aa2 100644
--- a/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs
+++ b/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs
@@ -35,7 +35,7 @@ namespace Umbraco.Web.Models.Mapping
Mandatory = x.Mandatory,
Name = source.GetName(x.IsoCode),
Exists = source.IsCultureAvailable(x.IsoCode), // segments ??
- PublishedState = source.PublishedState.ToString(),
+ PublishedState = (source.IsCulturePublished(x.IsoCode) ? PublishedState.Published : PublishedState.Unpublished).ToString(),
IsEdited = source.IsCultureEdited(x.IsoCode)
//Segment = ?? We'll need to populate this one day when we support segments
}).ToList();
diff --git a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
index 5b0ca2ee1b..fa5fc452db 100644
--- a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
+++ b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
@@ -12,14 +12,16 @@ namespace Umbraco.Web.Scheduling
private readonly IRuntimeState _runtime;
private readonly IContentService _contentService;
private readonly ILogger _logger;
+ private readonly IUserService _userService;
public ScheduledPublishing(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds,
- IRuntimeState runtime, IContentService contentService, ILogger logger)
+ IRuntimeState runtime, IContentService contentService, ILogger logger, IUserService userService)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_runtime = runtime;
_contentService = contentService;
_logger = logger;
+ _userService = userService;
}
public override bool PerformRun()
@@ -57,7 +59,7 @@ namespace Umbraco.Web.Scheduling
// fixme context & events during scheduled publishing?
// in v7 we create an UmbracoContext and an HttpContext, and cache instructions
// are batched, and we have to explicitely flush them, how is it going to work here?
- var publisher = new ScheduledPublisher(_contentService, _logger);
+ var publisher = new ScheduledPublisher(_contentService, _logger, _userService);
var count = publisher.CheckPendingAndProcess();
}
catch (Exception e)
diff --git a/src/Umbraco.Web/Scheduling/SchedulerComponent.cs b/src/Umbraco.Web/Scheduling/SchedulerComponent.cs
index 3cadb1d43e..68f6d008e2 100644
--- a/src/Umbraco.Web/Scheduling/SchedulerComponent.cs
+++ b/src/Umbraco.Web/Scheduling/SchedulerComponent.cs
@@ -26,6 +26,7 @@ namespace Umbraco.Web.Scheduling
{
private IRuntimeState _runtime;
private IContentService _contentService;
+ private IUserService _userService;
private IAuditService _auditService;
private ILogger _logger;
private ProfilingLogger _proflog;
@@ -44,12 +45,13 @@ namespace Umbraco.Web.Scheduling
private IBackgroundTask[] _tasks;
public void Initialize(IRuntimeState runtime,
- IContentService contentService, IAuditService auditService,
+ IContentService contentService, IAuditService auditService, IUserService userService,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IScopeProvider scopeProvider, ILogger logger, ProfilingLogger proflog)
{
_runtime = runtime;
_contentService = contentService;
+ _userService = userService;
_auditService = auditService;
_scopeProvider = scopeProvider;
_logger = logger;
@@ -116,7 +118,7 @@ namespace Umbraco.Web.Scheduling
{
// scheduled publishing/unpublishing
// install on all, will only run on non-slaves servers
- var task = new ScheduledPublishing(_publishingRunner, 60000, 60000, _runtime, _contentService, _logger);
+ var task = new ScheduledPublishing(_publishingRunner, 60000, 60000, _runtime, _contentService, _logger, _userService);
_publishingRunner.TryAdd(task);
return task;
}
diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs
index ad190fe8ed..a68cd720fd 100644
--- a/src/Umbraco.Web/Trees/ContentTreeController.cs
+++ b/src/Umbraco.Web/Trees/ContentTreeController.cs
@@ -71,10 +71,13 @@ namespace Umbraco.Web.Trees
else
{
var documentEntity = (IDocumentEntitySlim) entity;
- if (!documentEntity.Published)
+
+ //fixme we need these statuses per variant but to do that we need to fix the issues listed in IDocumentEntitySlim
+ if (!documentEntity.Published)
node.SetNotPublishedStyle();
- if (documentEntity.Edited)
- node.SetHasUnpublishedVersionStyle();
+ //if (documentEntity.Edited)
+ // node.SetHasUnpublishedVersionStyle();
+
node.AdditionalData.Add("contentType", documentEntity.ContentTypeAlias);
}
diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs
index 0c0308a471..e56eae81e8 100644
--- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs
+++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs
@@ -222,14 +222,13 @@ namespace Umbraco.Web.Trees
if (!culture.IsNullOrWhiteSpace())
{
foreach (var e in result)
- {
- if (e.AdditionalData.TryGetValue("CultureNames", out var cultureNames)
- && cultureNames is IDictionary cnd)
+ {
+ if (e is IDocumentEntitySlim doc)
{
- if (cnd.TryGetValue(culture, out var name))
+ if (doc.CultureNames.TryGetValue(culture, out var name))
{
e.Name = name;
- }
+ }
}
}
}