public async Task <TaxonomyValidationResult> Validate(TaxonomyPart part) { if (part.TermContentType != ContentTypes.PageLocation) { return(new TaxonomyValidationResult(true, null)); } List <string> errors = new List <string>(); //make sure nothing has moved that has associated pages anywhere down the tree List <ContentItem> allPages = await _contentItemsService.GetActive(ContentTypes.Page); JArray?terms = _taxonomyHelper.GetAllTerms(JObject.FromObject(part.ContentItem)); if (terms != null) { foreach (JObject term in terms) { dynamic?originalParent = _taxonomyHelper.FindParentTaxonomyTerm(term, JObject.FromObject(part.ContentItem)); dynamic?newParent = _taxonomyHelper.FindParentTaxonomyTerm(term, JObject.FromObject(part)); if (originalParent == null || newParent == null) { throw new InvalidOperationException($"Could not find {(originalParent == null ? "original" : "new")} parent taxonomy term for {term}"); } if (newParent?.ContentItemId != null && newParent?.ContentItemId != originalParent?.ContentItemId) { //find all child terms down the taxonomy tree var childTermsFromTree = _taxonomyHelper.GetAllTerms(term); if (allPages.Any(x => (string)x.Content.Page.PageLocations.TermContentItemIds[0] == (string)term["ContentItemId"] ! || childTermsFromTree.Any(t => (string)t["ContentItemId"] ! == (string)x.Content.Page.PageLocations.TermContentItemIds[0]))) { errors.Add("You cannot move a Page Location which has associated Pages linked to it, or any of its children."); } foreach (var validator in _validators) { (bool validated, string errorMessage) = await validator.ValidateUpdate(term, JObject.FromObject(part)); if (!validated) { errors.Add(errorMessage); } } //make sure display text doesn't clash with any other term at this level JArray parentTerms = _taxonomyHelper.GetTerms(JObject.FromObject(newParent)); if (parentTerms?.Any(x => (string)x["ContentItemId"] ! != (string)term["ContentItemId"] ! && (string)x["DisplayText"] ! == (string)term["DisplayText"] !) ?? false) { errors.Add("Terms at the same hierarchical position must have unique titles."); } } } } return(new TaxonomyValidationResult(!errors.Any(), errors)); }
public async Task <(bool, string)> ValidateUpdate(JObject term, JObject taxonomy) { if (!term.ContainsKey("PageLocation")) { return(true, string.Empty); } List <ContentItem> allPages = await _contentItemsService.GetActive(ContentTypes.Page); //find all child terms down the taxonomy tree var childTermsFromTree = _taxonomyHelper.GetAllTerms(term); if (allPages.Any(x => (string)x.Content.Page.PageLocations.TermContentItemIds[0] == (string)term["ContentItemId"] ! || childTermsFromTree.Any(t => (string)t["ContentItemId"] ! == (string)x.Content.Page.PageLocations.TermContentItemIds[0]))) { return(false, "Page Locations with pages associated to them or any of their children cannot be changed or deleted."); } return(true, string.Empty); }
public override async Task MutateOnClone(JObject content, ICloneContext context) { string?urlName = (string?)content[nameof(PageLocationPart.UrlName)]; string?fullUrl = (string?)content[nameof(PageLocationPart.FullUrl)]; if (string.IsNullOrWhiteSpace(urlName) || string.IsNullOrWhiteSpace(fullUrl)) { throw new InvalidOperationException($"Cannot mutate {nameof(PageLocationPart)} if {nameof(PageLocationPart.UrlName)} or {nameof(PageLocationPart.FullUrl)} are missing."); } List <ContentItem> pages = await _contentItemsService.GetActive(ContentTypes.Page); string urlSearchFragment = _generator.GenerateUrlSearchFragment(fullUrl); IEnumerable <ContentItem> existingClones = pages.Where(x => ((string)x.Content[nameof(PageLocationPart)][nameof(PageLocationPart.FullUrl)]).Contains(urlSearchFragment)); var result = _generator.GenerateClonedPageLocationProperties(urlName, fullUrl, existingClones); content[nameof(PageLocationPart.UrlName)] = result.UrlName; content[nameof(PageLocationPart.FullUrl)] = result.FullUrl; content[nameof(PageLocationPart.DefaultPageForLocation)] = false; content[nameof(PageLocationPart.RedirectLocations)] = null; }
public async Task <bool> UpdatedAsync(ContentItem term, ContentItem taxonomy) { if (term.ContentType != ContentTypes.PageLocation) { return(true); } List <ContentItem> allPages = await _contentItemsService.GetActive(ContentTypes.Page); List <ContentItem> associatedPages = allPages.Where(x => x.Content.Page.PageLocations.TermContentItemIds[0] == term.ContentItemId).ToList(); var groups = associatedPages.GroupBy(x => x.ContentItemId); foreach (var group in groups) { var pages = group.ToList(); foreach (var page in pages) { //rebuild the Full URL to ensure it matches the current state of the term var pageUrlName = page.As <PageLocationPart>().UrlName; var termUrl = _taxonomyHelper.BuildTermUrl(JObject.FromObject(term), JObject.FromObject(taxonomy)); var fullUrl = string.IsNullOrWhiteSpace(termUrl) ? $"/{pageUrlName}" : $"/{termUrl}/{pageUrlName}"; page.Alter <PageLocationPart>(part => part.FullUrl = fullUrl); _session.Save(page); } try { if (pages.Count > 1) { var publishedPage = pages.Single(x => x.Published); var draftPage = pages.Single(x => x.Latest); if (!await _syncOrchestrator.Update(publishedPage, draftPage)) { _session.Cancel(); } } else { var page = pages.Single(); if (page.Published && !await _syncOrchestrator.Publish(page)) { _session.Cancel(); } else if (!page.Published && !await _syncOrchestrator.SaveDraft(page)) { _session.Cancel(); } } } catch (Exception) { _session.Cancel(); return(false); } } return(true); }