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));
        }
Beispiel #2
0
        public Task <(bool, string)> ValidateCreate(JObject term, JObject taxonomy)
        {
            ContentItem?termContentItem = term.ToObject <ContentItem>();

            if (termContentItem == null)
            {
                throw new InvalidOperationException("You must provide a term");
            }

            if (termContentItem.Content.PageLocation == null)
            {
                return(Task.FromResult((true, string.Empty)));
            }

            if (termContentItem.DisplayText.Trim() != "/")
            {
                return(Task.FromResult((true, string.Empty)));
            }

            JObject?parent = _taxonomyHelper.FindParentTaxonomyTerm(term, taxonomy);

            if (parent == null)
            {
                throw new InvalidOperationException($"Could not find parent taxonomy term for {term}");
            }

            if (parent.ToObject <ContentItem>()?.ContentType == ContentTypes.Taxonomy)
            {
                return(Task.FromResult((true, string.Empty)));
            }

            return(Task.FromResult((false, "'/' is not a valid Title for this page location")));
        }
Beispiel #3
0
        public async Task <IActionResult> EditPost(string taxonomyContentItemId, string taxonomyItemId)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageTaxonomies))
            {
                return(Forbid());
            }

            ContentItem taxonomy;

            var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition("Taxonomy");

            if (!contentTypeDefinition.GetSettings <ContentTypeSettings>().Draftable)
            {
                taxonomy = await _contentManager.GetAsync(taxonomyContentItemId, VersionOptions.Latest);
            }
            else
            {
                taxonomy = await _contentManager.GetAsync(taxonomyContentItemId, VersionOptions.DraftRequired);
            }

            if (taxonomy == null)
            {
                return(NotFound());
            }

            // Look for the target taxonomy item in the hierarchy
            JObject taxonomyItem = FindTaxonomyItem(taxonomy.As <TaxonomyPart>().Content, taxonomyItemId);

            // Couldn't find targeted taxonomy item
            if (taxonomyItem == null)
            {
                return(NotFound());
            }

            var existing = taxonomyItem.ToObject <ContentItem>();

            // Create a new item to take into account the current type definition.
            var contentItem = await _contentManager.NewAsync(existing.ContentType);

            contentItem.Merge(existing);
            contentItem.Weld <TermPart>();
            contentItem.Alter <TermPart>(t => t.TaxonomyContentItemId = taxonomyContentItemId);

            dynamic model = await _contentItemDisplayManager.UpdateEditorAsync(contentItem, _updateModelAccessor.ModelUpdater, false);

            if (!ModelState.IsValid)
            {
                model.TaxonomyContentItemId = taxonomyContentItemId;
                model.TaxonomyItemId        = taxonomyItemId;

                return(View(model));
            }

            //when editing we don't know what the parent id is, so we have to search for it
            var parentTaxonomyTerm = _taxonomyHelper.FindParentTaxonomyTerm(JObject.FromObject(contentItem), JObject.FromObject(taxonomy));

            if (parentTaxonomyTerm == null)
            {
                return(NotFound());
            }

            if (!ValidateTaxonomyTerm(parentTaxonomyTerm, contentItem))
            {
                return(ValidationError($"Another {contentItem.ContentType} already exists with this name.", model, taxonomyContentItemId, taxonomyItemId));
            }

            taxonomyItem.Merge(contentItem.Content, new JsonMergeSettings
            {
                MergeArrayHandling     = MergeArrayHandling.Replace,
                MergeNullValueHandling = MergeNullValueHandling.Merge
            });

            // Merge doesn't copy the properties
            taxonomyItem[nameof(ContentItem.DisplayText)] = contentItem.DisplayText;

            foreach (var validator in _validators)
            {
                (bool validated, string errorMessage) = await validator.ValidateUpdate(JObject.FromObject(contentItem),
                                                                                       JObject.FromObject(taxonomy));

                if (!validated)
                {
                    return(ValidationError(errorMessage, model, taxonomyContentItemId, taxonomyItemId));
                }
            }

            taxonomy.Published = false;
            await _contentManager.PublishAsync(taxonomy);

            //Content item will get published as part of the taxonomy, handler ensure Event Grid is informed of Content Item change
            foreach (var handler in _handlers)
            {
                var updated = await handler.UpdatedAsync(contentItem, taxonomy);

                if (updated)
                {
                    await handler.PublishedAsync(contentItem);
                }
            }

            return(RedirectToAction("Edit", "Admin", new { area = "OrchardCore.Contents", contentItemId = taxonomyContentItemId }));
        }