public IHttpActionResult FindContentReferencesByUrl(SearchByUrlRequest request)
        {
            if (string.IsNullOrWhiteSpace(request?.TargetUrl) || !Uri.TryCreate(request.TargetUrl, UriKind.Absolute, out Uri uri))
            {
                return(BadRequest($"A valid {nameof(request.TargetUrl)} must be provided. Ensure that the Url you are using is absolute"));
            }

            IPublishedContent content = _ReferenceFinderContentService.TypedContent(uri);
            var references            = _ReferenceFinderService.FindContentWithReferences(content.Id);

            return(Json(new SearchResult(references)));
        }
Example #2
0
        private void FindContentWithReferencesToContent_Recursive(int contentId, IPublishedContent content, Dictionary <int, IPublishedContent> haveReferences, HashSet <int> contentSearched)
        {
            if (contentSearched.Contains(content.Id))
            {
                return;
            }

            contentSearched.Add(content.Id);

            //loop through all properties with a value
            foreach (var property in content.Properties.Where(p => p.HasValue))
            {
                var type             = property.GetType();
                var propertyTypeProp = type.GetField("PropertyType");

                //if we fail to determine the type of the property, skip and keep looping
                if (propertyTypeProp == null)
                {
                    continue;
                }

                var propertyType            = propertyTypeProp.GetValue(property);
                var propertyTypeType        = propertyType.GetType();
                var propertyEditorAliasProp = propertyTypeType.GetProperty("PropertyEditorAlias");

                //if we fail to determine the alias of the property's editor, skip and keep looping
                if (propertyEditorAliasProp == null)
                {
                    continue;
                }

                var propertyEditorAlias = propertyEditorAliasProp.GetValue(propertyType)?.ToString();

                Regex contentPickerPattern = new Regex(@"Umbraco\.ContentPicker", RegexOptions.Compiled);
                Regex mediaPickerPattern   = new Regex(@"Umbraco\.MediaPicker", RegexOptions.Compiled);

                bool isContentPicker = contentPickerPattern.IsMatch(propertyEditorAlias ?? "");
                bool isMediaPicker   = mediaPickerPattern.IsMatch(propertyEditorAlias ?? "");

                // we only care about content and media picker properties atm
                if (!isContentPicker && !isMediaPicker)
                {
                    continue;
                }

                if (isContentPicker)
                {
                    //try to parse the property value as an int. single ints are used for a single content/media item
                    if (int.TryParse(property.Value.ToString(), out int propertyContentId))
                    {
                        if (contentId == propertyContentId && !haveReferences.ContainsKey(content.Id))
                        {
                            //this property contains a reference to the id we are searching for, therefore we store the id of the content indicating where the content is referenced
                            haveReferences.Add(content.Id, content);
                            break;
                        }

                        //this property does not contain a reference to the id we are searching for, therefore we need to search each property
                        var innerContent = _ContentService.TypedContent(propertyContentId);
                        FindContentWithReferencesToContent_Recursive(contentId, innerContent, haveReferences, contentSearched);
                        continue;
                    }

                    //property value was not an int, therefore check if it is a collection of IPublishedContents. an array of IPublishedContents are used for multiple content/media items
                    IPublishedContent[] publishedContentCollection = (property.Value as IEnumerable <IPublishedContent>)?.ToArray();

                    if (publishedContentCollection != null && publishedContentCollection.Any())
                    {
                        //loop through each id and check if it matches the id we are searching for
                        foreach (var publishedContent in publishedContentCollection)
                        {
                            if (publishedContent.Id == contentId && !haveReferences.ContainsKey(content.Id))
                            {
                                //this property contains a reference to the id we are searching for, therefore we store the id of the content indicating where the content is referenced
                                haveReferences.Add(content.Id, content);
                                break;
                            }

                            FindContentWithReferencesToContent_Recursive(contentId, publishedContent, haveReferences, contentSearched);
                        }
                    }

                    //property value was not a collection of IPublishedContents, therefore check if it is a collection of ints. an array of ints are used for multiple content/media items
                    int[] publishedContentIdCollection = (property.Value as IEnumerable <int>)?.ToArray();

                    if (publishedContentIdCollection != null && publishedContentIdCollection.Any())
                    {
                        //loop through each id and check if it matches the id we are searching for
                        foreach (var id in publishedContentIdCollection)
                        {
                            if (id == contentId && !haveReferences.ContainsKey(content.Id))
                            {
                                //this property contains a reference to the id we are searching for, therefore we store the id of the content indicating where the content is referenced
                                haveReferences.Add(content.Id, content);
                                break;
                            }

                            var listContent = _ContentService.TypedContent(propertyContentId);
                            FindContentWithReferencesToContent_Recursive(contentId, listContent, haveReferences, contentSearched);
                        }
                    }
                }

                if (!isMediaPicker)
                {
                    continue;
                }

                //try to parse the property value as an int. single ints are used for a single content/media item
                if (int.TryParse(property.Value.ToString(), out int propertyMediaId))
                {
                    if (contentId != propertyMediaId || haveReferences.ContainsKey(content.Id))
                    {
                        continue;
                    }

                    //this property contains a reference to the id we are searching for, therefore we store the id of the content indicating where the content is referenced
                    haveReferences.Add(content.Id, content);
                }

                //property value was not an int, therefore check if it is a collection of ints. an array of ints are used for multiple content/media items
                IPublishedContent[] publishedMediaCollection = (property.Value as IEnumerable <IPublishedContent>)?.ToArray();

                if (publishedMediaCollection != null && publishedMediaCollection.Any())
                {
                    //loop through each id and check if it matches the id we are searching for
                    foreach (var publishedMedia in publishedMediaCollection)
                    {
                        if (publishedMedia.Id != contentId || haveReferences.ContainsKey(content.Id))
                        {
                            continue;
                        }

                        //this property contains a reference to the id we are searching for, therefore we store the id of the content indicating where the content is referenced
                        haveReferences.Add(content.Id, content);
                    }
                }
            }

            foreach (var child in content.Children)
            {
                FindContentWithReferencesToContent_Recursive(contentId, child, haveReferences, contentSearched);
            }
        }