/// <summary> /// Returns a paged result of media items known to be of a "Folder" type /// </summary> /// <param name="id"></param> /// <param name="pageNumber"></param> /// <param name="pageSize"></param> /// <returns></returns> public PagedResult <ContentItemBasic <ContentPropertyBasic> > GetChildFolders(int id, int pageNumber = 1, int pageSize = 1000) { //Suggested convention for folder mediatypes - we can make this more or less complicated as long as we document it... //if you create a media type, which has an alias that ends with ...Folder then its a folder: ex: "secureFolder", "bannerFolder", "Folder" var folderTypes = _mediaTypeService .GetAll() .Where(x => x.Alias.EndsWith("Folder")) .Select(x => x.Id) .ToArray(); if (folderTypes.Length == 0) { return(new PagedResult <ContentItemBasic <ContentPropertyBasic> >(0, pageNumber, pageSize)); } long total; var children = _mediaService.GetPagedChildren(id, pageNumber - 1, pageSize, out total, //lookup these content types _sqlContext.Query <IMedia>().Where(x => folderTypes.Contains(x.ContentTypeId)), Ordering.By("Name", Direction.Ascending)); return(new PagedResult <ContentItemBasic <ContentPropertyBasic> >(total, pageNumber, pageSize) { Items = children.Select(_umbracoMapper.Map <IMedia, ContentItemBasic <ContentPropertyBasic> >) }); }
public void Get_Paged_Children_With_Media_Type_Filter() { var mediaService = ServiceContext.MediaService; var mediaType1 = MockedContentTypes.CreateImageMediaType("Image2"); ServiceContext.MediaTypeService.Save(mediaType1); var mediaType2 = MockedContentTypes.CreateImageMediaType("Image3"); ServiceContext.MediaTypeService.Save(mediaType2); for (int i = 0; i < 10; i++) { var m1 = MockedMedia.CreateMediaImage(mediaType1, -1); mediaService.Save(m1); var m2 = MockedMedia.CreateMediaImage(mediaType2, -1); mediaService.Save(m2); } long total; var result = ServiceContext.MediaService.GetPagedChildren(-1, 0, 11, out total, SqlContext.Query <IMedia>().Where(x => new[] { mediaType1.Id, mediaType2.Id }.Contains(x.ContentTypeId)), Ordering.By("SortOrder", Direction.Ascending)); Assert.AreEqual(11, result.Count()); Assert.AreEqual(20, total); result = ServiceContext.MediaService.GetPagedChildren(-1, 1, 11, out total, SqlContext.Query <IMedia>().Where(x => new[] { mediaType1.Id, mediaType2.Id }.Contains(x.ContentTypeId)), Ordering.By("SortOrder", Direction.Ascending)); Assert.AreEqual(9, result.Count()); Assert.AreEqual(20, total); }
public void GetPagedResultsByQuery_CustomPropertySort() { var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { var repository = CreateRepository((IScopeAccessor)provider, out _); var query = scope.SqlContext.Query <IContent>().Where(x => x.Name.Contains("Text")); try { scope.Database.AsUmbracoDatabase().EnableSqlTrace = true; scope.Database.AsUmbracoDatabase().EnableSqlCount = true; var result = repository.GetPage(query, 0, 2, out var totalRecords, null, Ordering.By("title", isCustomField: true)); Assert.AreEqual(3, totalRecords); Assert.AreEqual(2, result.Count()); result = repository.GetPage(query, 1, 2, out totalRecords, null, Ordering.By("title", isCustomField: true)); Assert.AreEqual(1, result.Count()); } finally { scope.Database.AsUmbracoDatabase().EnableSqlTrace = false; scope.Database.AsUmbracoDatabase().EnableSqlCount = false; } } }
private void RefreshContentOfContentTypes(int[] contentTypeIds) { const int pageSize = 500; var page = 0; var total = long.MaxValue; while (page * pageSize < total) { var contentToRefresh = _services.ContentService.GetPagedOfTypes( //Re-index all content of these types contentTypeIds, page++, pageSize, out total, null, //order by shallowest to deepest, this allows us to check it's published state without checking every item Ordering.By("Path", Direction.Ascending)); //track which Ids have their paths are published var publishChecked = new Dictionary <int, bool>(); foreach (var c in contentToRefresh) { var isPublished = false; if (c.Published) { if (!publishChecked.TryGetValue(c.ParentId, out isPublished)) { //nothing by parent id, so query the service and cache the result for the next child to check against isPublished = _services.ContentService.IsPathPublished(c); publishChecked[c.Id] = isPublished; } } ReIndexForContent(c, isPublished); } } }
/// <summary> /// Get paged child entities by id /// </summary> /// <param name="id"></param> /// <param name="type"></param> /// <param name="pageNumber"></param> /// <param name="pageSize"></param> /// <param name="orderBy"></param> /// <param name="orderDirection"></param> /// <param name="filter"></param> /// <returns></returns> public PagedResult <EntityBasic> GetPagedChildren( int id, UmbracoEntityTypes type, int pageNumber, int pageSize, string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "") { if (pageNumber <= 0) { throw new HttpResponseException(HttpStatusCode.NotFound); } if (pageSize <= 0) { throw new HttpResponseException(HttpStatusCode.NotFound); } var objectType = ConvertToObjectType(type); if (objectType.HasValue) { var entities = Services.EntityService.GetPagedChildren(id, objectType.Value, pageNumber - 1, pageSize, out var totalRecords, filter.IsNullOrWhiteSpace() ? null : SqlContext.Query <IUmbracoEntity>().Where(x => x.Name.Contains(filter)), Ordering.By(orderBy, orderDirection)); if (totalRecords == 0) { return(new PagedResult <EntityBasic>(0, 0, 0)); } var pagedResult = new PagedResult <EntityBasic>(totalRecords, pageNumber, pageSize) { Items = entities.Select(entity => Mapper.Map <IEntitySlim, EntityBasic>(entity, options => options.AfterMap((src, dest) => { dest.AdditionalData["hasChildren"] = src.HasChildren; }) ) ) }; return(pagedResult); } //now we need to convert the unknown ones switch (type) { case UmbracoEntityTypes.PropertyType: case UmbracoEntityTypes.PropertyGroup: case UmbracoEntityTypes.Domain: case UmbracoEntityTypes.Language: case UmbracoEntityTypes.User: case UmbracoEntityTypes.Macro: default: throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + type); } }
protected void IndexPublishedContent(int contentParentId, int pageIndex, int pageSize, IReadOnlyList <IIndex> indexes) { IContent[] content; var publishedPages = new HashSet <int>(); do { //add the published filter //note: We will filter for published variants in the validator content = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out _, _publishedQuery, Ordering.By("Path", Direction.Ascending)).ToArray(); if (content.Length > 0) { var indexableContent = new List <IContent>(); foreach (var item in content) { if (item.Level == 1) { // first level pages are always published so no need to filter them indexableContent.Add(item); publishedPages.Add(item.Id); } else { if (publishedPages.Contains(item.ParentId)) { // only index when parent is published publishedPages.Add(item.Id); indexableContent.Add(item); } } } var valueSets = _contentValueSetBuilder.GetValueSets(indexableContent.ToArray()).ToList(); // ReSharper disable once PossibleMultipleEnumeration foreach (var index in indexes) { index.IndexItems(valueSets); } } pageIndex++; } while (content.Length == pageSize); }
public void EntityService_Can_Get_Paged_Descendants_Ordering_Path() { var contentType = ServiceContext.ContentTypeService.Get("umbTextpage"); var root = MockedContent.CreateSimpleContent(contentType); ServiceContext.ContentService.Save(root); var rootId = root.Id; var ids = new List <int>(); for (int i = 0; i < 10; i++) { var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root); ServiceContext.ContentService.Save(c1); ids.Add(c1.Id); root = c1; // make a hierarchy } var service = ServiceContext.EntityService; long total; var entities = service.GetPagedDescendants(rootId, UmbracoObjectTypes.Document, 0, 6, out total).ToArray(); Assert.That(entities.Length, Is.EqualTo(6)); Assert.That(total, Is.EqualTo(10)); Assert.AreEqual(ids[0], entities[0].Id); entities = service.GetPagedDescendants(rootId, UmbracoObjectTypes.Document, 1, 6, out total).ToArray(); Assert.That(entities.Length, Is.EqualTo(4)); Assert.That(total, Is.EqualTo(10)); Assert.AreEqual(ids[6], entities[0].Id); //Test ordering direction entities = service.GetPagedDescendants(rootId, UmbracoObjectTypes.Document, 0, 6, out total, ordering: Ordering.By("Path", Direction.Descending)).ToArray(); Assert.That(entities.Length, Is.EqualTo(6)); Assert.That(total, Is.EqualTo(10)); Assert.AreEqual(ids[ids.Count - 1], entities[0].Id); entities = service.GetPagedDescendants(rootId, UmbracoObjectTypes.Document, 1, 6, out total, ordering: Ordering.By("Path", Direction.Descending)).ToArray(); Assert.That(entities.Length, Is.EqualTo(4)); Assert.That(total, Is.EqualTo(10)); Assert.AreEqual(ids[ids.Count - 1 - 6], entities[0].Id); }
protected override void PopulateIndexes(IReadOnlyList <IIndex> indexes) { if (indexes.Count == 0) { return; } const int pageSize = 10000; var pageIndex = 0; var contentParentId = -1; if (_parentId.HasValue && _parentId.Value > 0) { contentParentId = _parentId.Value; } IContent[] content; do { if (!_publishedValuesOnly) { content = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out _) .ToArray(); } else { //add the published filter //note: We will filter for published variants in the validator content = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out _, _publishedQuery, Ordering.By("Path", Direction.Ascending)).ToArray(); } if (content.Length > 0) { // ReSharper disable once PossibleMultipleEnumeration foreach (var index in indexes) { index.IndexItems(_contentValueSetBuilder.GetValueSets(content)); } } pageIndex++; } while (content.Length == pageSize); }
public void Get_Paged_Children_With_Media_Type_Filter() { var mediaType1 = MediaTypeBuilder.CreateImageMediaType("Image2"); MediaTypeService.Save(mediaType1); var mediaType2 = MediaTypeBuilder.CreateImageMediaType("Image3"); MediaTypeService.Save(mediaType2); for (var i = 0; i < 10; i++) { var m1 = MediaBuilder.CreateMediaImage(mediaType1, -1); MediaService.Save(m1); var m2 = MediaBuilder.CreateMediaImage(mediaType2, -1); MediaService.Save(m2); } var provider = ScopeProvider; using (provider.CreateScope()) { var result = MediaService.GetPagedChildren( -1, 0, 11, out var total, provider.CreateQuery <IMedia>() .Where(x => new[] { mediaType1.Id, mediaType2.Id }.Contains(x.ContentTypeId)), Ordering.By("SortOrder")); Assert.AreEqual(11, result.Count()); Assert.AreEqual(20, total); result = MediaService.GetPagedChildren( -1, 1, 11, out total, provider.CreateQuery <IMedia>() .Where(x => new[] { mediaType1.Id, mediaType2.Id }.Contains(x.ContentTypeId)), Ordering.By("SortOrder")); Assert.AreEqual(9, result.Count()); Assert.AreEqual(20, total); } }
public void Get_Paged_Children_With_Media_Type_Filter() { MediaType mediaType1 = MediaTypeBuilder.CreateImageMediaType("Image2"); MediaTypeService.Save(mediaType1); MediaType mediaType2 = MediaTypeBuilder.CreateImageMediaType("Image3"); MediaTypeService.Save(mediaType2); for (int i = 0; i < 10; i++) { Media m1 = MediaBuilder.CreateMediaImage(mediaType1, -1); MediaService.Save(m1); Media m2 = MediaBuilder.CreateMediaImage(mediaType2, -1); MediaService.Save(m2); } IScopeProvider provider = ScopeProvider; using (provider.CreateScope()) { IEnumerable <IMedia> result = MediaService.GetPagedChildren( -1, 0, 11, out long total, provider.SqlContext.Query <IMedia>() .Where(x => new[] { mediaType1.Id, mediaType2.Id }.Contains(x.ContentTypeId)), Ordering.By("SortOrder", Direction.Ascending)); Assert.AreEqual(11, result.Count()); Assert.AreEqual(20, total); result = MediaService.GetPagedChildren( -1, 1, 11, out total, provider.SqlContext.Query <IMedia>() .Where(x => new[] { mediaType1.Id, mediaType2.Id }.Contains(x.ContentTypeId)), Ordering.By("SortOrder", Direction.Ascending)); Assert.AreEqual(9, result.Count()); Assert.AreEqual(20, total); } }
public void GetPagedResultsByQuery_AlternateOrder() { // Arrange var provider = ScopeProvider; using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider, out var mediaTypeRepository); // Act var query = provider.CreateQuery <IMedia>().Where(x => x.Level == 2); var result = repository.GetPage(query, 0, 1, out var totalRecords, null, Ordering.By("Name")).ToArray(); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); Assert.That(result.Count(), Is.EqualTo(1)); Assert.That(result.First().Name, Is.EqualTo("Test File")); } }
private void RefreshMediaOfMediaTypes(int[] mediaTypeIds) { const int pageSize = 500; var page = 0; var total = long.MaxValue; while (page * pageSize < total) { var mediaToRefresh = _services.MediaService.GetPagedOfTypes( //Re-index all content of these types mediaTypeIds, page++, pageSize, out total, null, Ordering.By("Path", Direction.Ascending)); foreach (var c in mediaToRefresh) { ReIndexForMedia(c, c.Trashed == false); } } }
private void RefreshMediaOfMediaTypes(int[] mediaTypeIds) { const int pageSize = 500; var page = 0; var total = long.MaxValue; while (page * pageSize < total) { IEnumerable <IMedia> mediaToRefresh = _mediaService.GetPagedOfTypes( // Re-index all content of these types mediaTypeIds, page++, pageSize, out total, null, Ordering.By("Path")); foreach (IMedia c in mediaToRefresh) { _umbracoIndexingHandler.ReIndexForMedia(c, c.Trashed == false); } } }
/// <inheritdoc /> protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, ContentPermissionsPublishBranchRequirement requirement, IContent resource) { IUser? currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser; var denied = new List<IUmbracoEntity>(); var page = 0; const int pageSize = 500; var total = long.MaxValue; while (page * pageSize < total) { // Order descendents by shallowest to deepest, this allows us to check permissions from top to bottom so we can exit // early if a permission higher up fails. IEnumerable<IEntitySlim> descendants = _entityService.GetPagedDescendants( resource.Id, UmbracoObjectTypes.Document, page++, pageSize, out total, ordering: Ordering.By("path")); foreach (IEntitySlim c in descendants) { // If this item's path has already been denied or if the user doesn't have access to it, add to the deny list. if (denied.Any(x => c.Path.StartsWith($"{x.Path},")) || _contentPermissions.CheckPermissions( c, currentUser, requirement.Permission) == ContentPermissions.ContentAccess.Denied) { denied.Add(c); } } } return Task.FromResult(denied.Count == 0); }
public IEnumerable <IRelation> GetPagedRelationsByQuery(IQuery <IRelation>?query, long pageIndex, int pageSize, out long totalRecords, Ordering?ordering) { Sql <ISqlContext> sql = GetBaseQuery(false); if (ordering == null || ordering.IsEmpty) { ordering = Ordering.By(SqlSyntax.GetQuotedColumn(Constants.DatabaseSchema.Tables.Relation, "id")); } var translator = new SqlTranslator <IRelation>(sql, query); sql = translator.Translate(); // apply ordering ApplyOrdering(ref sql, ordering); var pageIndexToFetch = pageIndex + 1; Page <RelationDto>?page = Database.Page <RelationDto>(pageIndexToFetch, pageSize, sql); List <RelationDto>?dtos = page.Items; totalRecords = page.TotalItems; var relTypes = _relationTypeRepository.GetMany(dtos.Select(x => x.RelationType).Distinct().ToArray())? .ToDictionary(x => x.Id, x => x); var result = dtos.Select(r => { if (relTypes is null || !relTypes.TryGetValue(r.RelationType, out IRelationType? relType)) { throw new InvalidOperationException(string.Format("RelationType with Id: {0} doesn't exist", r.RelationType)); } return(DtoToEntity(r, relType)); }).WhereNotNull().ToList(); return(result); }
public void GetPagedResultsByQuery_DescendingOrder() { var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { var repository = CreateRepository((IScopeAccessor)provider, out _); var query = scope.SqlContext.Query <IContent>().Where(x => x.Level == 2); var result = repository.GetPage(query, 0, 1, out var totalRecords, null, Ordering.By("Name", Direction.Descending)); Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); Assert.That(result.Count(), Is.EqualTo(1)); Assert.That(result.First().Name, Is.EqualTo("Text Page 2")); } }
public void GetPagedResultsByQuery_FilterMatchingAll() { var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { var repository = CreateRepository((IScopeAccessor)provider, out _); var query = scope.SqlContext.Query <IContent>().Where(x => x.Level == 2); var filterQuery = scope.SqlContext.Query <IContent>().Where(x => x.Name.Contains("text")); var result = repository.GetPage(query, 0, 1, out var totalRecords, filterQuery, Ordering.By("Name")); Assert.That(totalRecords, Is.EqualTo(2)); Assert.That(result.Count(), Is.EqualTo(1)); Assert.That(result.First().Name, Is.EqualTo("Text Page 1")); } }
// assumes content tree lock private void RebuildContentDbCache(IContentCacheDataSerializer serializer, int groupSize, IReadOnlyCollection <int> contentTypeIds) { Guid contentObjectType = Constants.ObjectTypes.Document; // remove all - if anything fails the transaction will rollback if (contentTypeIds == null || contentTypeIds.Count == 0) { // must support SQL-CE Database.Execute( @"DELETE FROM cmsContentNu WHERE cmsContentNu.nodeId IN ( SELECT id FROM umbracoNode WHERE umbracoNode.nodeObjectType=@objType )", new { objType = contentObjectType }); } else { // assume number of ctypes won't blow IN(...) // must support SQL-CE Database.Execute( $@"DELETE FROM cmsContentNu WHERE cmsContentNu.nodeId IN ( SELECT id FROM umbracoNode JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id WHERE umbracoNode.nodeObjectType=@objType AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes) )", new { objType = contentObjectType, ctypes = contentTypeIds }); } // insert back - if anything fails the transaction will rollback IQuery <IContent> query = SqlContext.Query <IContent>(); if (contentTypeIds != null && contentTypeIds.Count > 0) { query = query.WhereIn(x => x.ContentTypeId, contentTypeIds); // assume number of ctypes won't blow IN(...) } long pageIndex = 0; long processed = 0; long total; do { // the tree is locked, counting and comparing to total is safe IEnumerable <IContent> descendants = _documentRepository.GetPage(query, pageIndex++, groupSize, out total, null, Ordering.By("Path")); var items = new List <ContentNuDto>(); var count = 0; foreach (IContent c in descendants) { // always the edited version items.Add(GetDto(c, false, serializer)); // and also the published version if it makes any sense if (c.Published) { items.Add(GetDto(c, true, serializer)); } count++; } Database.BulkInsertRecords(items); processed += count; } while (processed < total); }
public void GetPagedResultsByQuery_FirstPage() { var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { var repository = CreateRepository((IScopeAccessor)provider, out _); var query = scope.SqlContext.Query <IContent>().Where(x => x.Level == 2); try { scope.Database.AsUmbracoDatabase().EnableSqlTrace = true; scope.Database.AsUmbracoDatabase().EnableSqlCount = true; var result = repository.GetPage(query, 0, 1, out var totalRecords, null, Ordering.By("Name")); Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); Assert.That(result.Count(), Is.EqualTo(1)); Assert.That(result.First().Name, Is.EqualTo("Text Page 1")); } finally { scope.Database.AsUmbracoDatabase().EnableSqlTrace = false; scope.Database.AsUmbracoDatabase().EnableSqlCount = false; } } }
// assumes member tree lock private void RebuildMemberDbCache(IContentCacheDataSerializer serializer, int groupSize, IReadOnlyCollection <int> contentTypeIds) { Guid memberObjectType = Constants.ObjectTypes.Member; // remove all - if anything fails the transaction will rollback if (contentTypeIds == null || contentTypeIds.Count == 0) { // must support SQL-CE Database.Execute( @"DELETE FROM cmsContentNu WHERE cmsContentNu.nodeId IN ( SELECT id FROM umbracoNode WHERE umbracoNode.nodeObjectType=@objType )", new { objType = memberObjectType }); } else { // assume number of ctypes won't blow IN(...) // must support SQL-CE Database.Execute( $@"DELETE FROM cmsContentNu WHERE cmsContentNu.nodeId IN ( SELECT id FROM umbracoNode JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id WHERE umbracoNode.nodeObjectType=@objType AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes) )", new { objType = memberObjectType, ctypes = contentTypeIds }); } // insert back - if anything fails the transaction will rollback IQuery <IMember> query = SqlContext.Query <IMember>(); if (contentTypeIds != null && contentTypeIds.Count > 0) { query = query.WhereIn(x => x.ContentTypeId, contentTypeIds); // assume number of ctypes won't blow IN(...) } long pageIndex = 0; long processed = 0; long total; do { IEnumerable <IMember> descendants = _memberRepository.GetPage(query, pageIndex++, groupSize, out total, null, Ordering.By("Path")); ContentNuDto[] items = descendants.Select(m => GetDto(m, false, serializer)).ToArray(); Database.BulkInsertRecords(items); processed += items.Length; } while (processed < total); }
public void GetPagedResultsByQuery_With_Variant_Names() { // one invariant content type named "umbInvariantTextPage" // var invariantCt = MockedContentTypes.CreateSimpleContentType("umbInvariantTextpage", "Invariant Textpage"); invariantCt.Variations = ContentVariation.Nothing; foreach (var p in invariantCt.PropertyTypes) { p.Variations = ContentVariation.Nothing; } ServiceContext.FileService.SaveTemplate(invariantCt.DefaultTemplate); // else, FK violation on contentType! ServiceContext.ContentTypeService.Save(invariantCt); // one variant (by culture) content type named "umbVariantTextPage" // with properties, every 2nd one being variant (by culture), the other being invariant // var variantCt = MockedContentTypes.CreateSimpleContentType("umbVariantTextpage", "Variant Textpage"); variantCt.Variations = ContentVariation.Culture; var propTypes = variantCt.PropertyTypes.ToList(); for (var i = 0; i < propTypes.Count; i++) { var p = propTypes[i]; p.Variations = i % 2 == 0 ? ContentVariation.Culture : ContentVariation.Nothing; } ServiceContext.FileService.SaveTemplate(variantCt.DefaultTemplate); // else, FK violation on contentType! ServiceContext.ContentTypeService.Save(variantCt); invariantCt.AllowedContentTypes = new[] { new ContentTypeSort(invariantCt.Id, 0), new ContentTypeSort(variantCt.Id, 1) }; ServiceContext.ContentTypeService.Save(invariantCt); //create content var root = MockedContent.CreateSimpleContent(invariantCt); ServiceContext.ContentService.Save(root); var children = new List <IContent>(); for (var i = 0; i < 25; i++) { var isInvariant = i % 2 == 0; var name = (isInvariant ? "INV" : "VAR") + "_" + Guid.NewGuid(); var culture = isInvariant ? null : "en-US"; var child = MockedContent.CreateSimpleContent( isInvariant ? invariantCt : variantCt, name, root, culture, setPropertyValues: isInvariant); if (!isInvariant) { //manually set the property values since we have mixed variant/invariant property types child.SetValue("title", name + " Subpage", culture: culture); child.SetValue("bodyText", "This is a subpage", culture: null); //this one is invariant child.SetValue("author", "John Doe", culture: culture); } ServiceContext.ContentService.Save(child); children.Add(child); } var child1 = children[1]; Assert.IsTrue(child1.ContentType.VariesByCulture()); Assert.IsTrue(child1.Name.StartsWith("VAR")); Assert.IsTrue(child1.GetCultureName("en-US").StartsWith("VAR")); var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { var repository = CreateRepository((IScopeAccessor)provider, out _); var child = repository.Get(children[1].Id); // 1 is variant Assert.IsTrue(child.ContentType.VariesByCulture()); Assert.IsTrue(child.Name.StartsWith("VAR")); Assert.IsTrue(child.GetCultureName("en-US").StartsWith("VAR")); try { scope.Database.AsUmbracoDatabase().EnableSqlTrace = true; scope.Database.AsUmbracoDatabase().EnableSqlCount = true; var query = scope.SqlContext.Query <IContent>().Where(x => x.ParentId == root.Id); var result = repository.GetPage(query, 0, 20, out var totalRecords, null, Ordering.By("UpdateDate")); Assert.AreEqual(25, totalRecords); foreach (var r in result) { var isInvariant = r.ContentType.Alias == "umbInvariantTextpage"; var name = isInvariant ? r.Name : r.CultureInfos["en-US"].Name; var namePrefix = isInvariant ? "INV" : "VAR"; //ensure the correct name (invariant vs variant) is in the result Assert.IsTrue(name.StartsWith(namePrefix)); foreach (var p in r.Properties) { //ensure there is a value for the correct variant/invariant property var value = p.GetValue(p.PropertyType.Variations.VariesByNothing() ? null : "en-US"); Assert.IsNotNull(value); } } } finally { scope.Database.AsUmbracoDatabase().EnableSqlTrace = false; scope.Database.AsUmbracoDatabase().EnableSqlCount = false; } } }
/// <summary> /// Updates indexes based on content changes /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void ContentCacheRefresherUpdated(ContentCacheRefresher sender, CacheRefresherEventArgs args) { if (Suspendable.ExamineEvents.CanIndex == false) { return; } if (args.MessageType != MessageType.RefreshByPayload) { throw new NotSupportedException(); } var contentService = _services.ContentService; foreach (var payload in (ContentCacheRefresher.JsonPayload[])args.MessageObject) { if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove)) { // delete content entirely (with descendants) // false: remove entirely from all indexes DeleteIndexForEntity(payload.Id, false); } else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll)) { // ExamineEvents does not support RefreshAll // just ignore that payload // so what?! // TODO: Rebuild the index at this point? } else // RefreshNode or RefreshBranch (maybe trashed) { // don't try to be too clever - refresh entirely // there has to be race conditions in there ;-( var content = contentService.GetById(payload.Id); if (content == null) { // gone fishing, remove entirely from all indexes (with descendants) DeleteIndexForEntity(payload.Id, false); continue; } IContent published = null; if (content.Published && contentService.IsPathPublished(content)) { published = content; } if (published == null) { DeleteIndexForEntity(payload.Id, true); } // just that content ReIndexForContent(content, published != null); // branch if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch)) { var masked = published == null ? null : new List <int>(); const int pageSize = 500; var page = 0; var total = long.MaxValue; while (page * pageSize < total) { var descendants = contentService.GetPagedDescendants(content.Id, page++, pageSize, out total, //order by shallowest to deepest, this allows us to check it's published state without checking every item ordering: Ordering.By("Path", Direction.Ascending)); foreach (var descendant in descendants) { published = null; if (masked != null) // else everything is masked { if (masked.Contains(descendant.ParentId) || !descendant.Published) { masked.Add(descendant.Id); } else { published = descendant; } } ReIndexForContent(descendant, published != null); } } } } // NOTE // // DeleteIndexForEntity is handled by UmbracoContentIndexer.DeleteFromIndex() which takes // care of also deleting the descendants // // ReIndexForContent is NOT taking care of descendants so we have to reload everything // again in order to process the branch - we COULD improve that by just reloading the // XML from database instead of reloading content & re-serializing! // // BUT ... pretty sure it is! see test "Index_Delete_Index_Item_Ensure_Heirarchy_Removed" } }
private void AddBlogPosts(IContent archiveNode, BlogMLDocument blogMlDoc, string categoryGroup, string tagGroup) { const int pageSize = 1000; var pageIndex = 0; IContent[] posts; do { posts = _contentService.GetPagedChildren(archiveNode.Id, pageIndex, pageSize, out long _, ordering: Ordering.By("createDate")).ToArray(); foreach (var child in posts) { string content = ""; if (child.ContentType.Alias.InvariantEquals("ArticulateRichText")) { //TODO: this would also need to export all macros content = child.GetValue <string>("richText"); } else if (child.ContentType.Alias.InvariantEquals("ArticulateMarkdown")) { var md = new Markdown(); content = md.Transform(child.GetValue <string>("markdown")); } var postUrl = new Uri(_umbracoContextAccessor.UmbracoContext.UrlProvider.GetUrl(child.Id), UriKind.RelativeOrAbsolute); var postAbsoluteUrl = new Uri(_umbracoContextAccessor.UmbracoContext.UrlProvider.GetUrl(child.Id, UrlProviderMode.Absolute), UriKind.Absolute); var blogMlPost = new BlogMLPost() { Id = child.Key.ToString(), Name = new BlogMLTextConstruct(child.Name), Title = new BlogMLTextConstruct(child.Name), ApprovalStatus = BlogMLApprovalStatus.Approved, PostType = BlogMLPostType.Normal, CreatedOn = child.CreateDate, LastModifiedOn = child.UpdateDate, Content = new BlogMLTextConstruct(content, BlogMLContentType.Html), Excerpt = new BlogMLTextConstruct(child.GetValue <string>("excerpt")), Url = postUrl }; var author = blogMlDoc.Authors.FirstOrDefault(x => x.Title != null && x.Title.Content.InvariantEquals(child.GetValue <string>("author"))); if (author != null) { blogMlPost.Authors.Add(author.Id); } var categories = _tagService.GetTagsForEntity(child.Id, categoryGroup); foreach (var category in categories) { blogMlPost.Categories.Add(category.Id.ToString()); } var tags = _tagService.GetTagsForEntity(child.Id, tagGroup).Select(t => t.Text).ToList(); if (tags?.Any() == true) { blogMlPost.AddExtension( new Syndication.BlogML.TagsSyndicationExtension() { Context = { Tags = new Collection <string>(tags) } }); } //add the image attached if there is one if (child.HasProperty("postImage")) { try { var val = child.GetValue <string>("postImage"); var json = JsonConvert.DeserializeObject <JObject>(val); var src = json.Value <string>("src"); var mime = ImageMimeType(src); if (!mime.IsNullOrWhiteSpace()) { var imageUrl = new Uri(postAbsoluteUrl.GetLeftPart(UriPartial.Authority) + src.EnsureStartsWith('/'), UriKind.Absolute); blogMlPost.Attachments.Add(new BlogMLAttachment { Content = string.Empty, //this is used for embedded resources Url = imageUrl, ExternalUri = imageUrl, IsEmbedded = false, MimeType = mime }); } } catch (Exception ex) { _logger.Error <BlogMlExporter>(ex, "Could not add the file to the blogML post attachments"); } } blogMlDoc.AddPost(blogMlPost); } pageIndex++; } while (posts.Length == pageSize); }
public void GetPagedResultsByQuery_FilterMatchingAll() { // Arrange var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider, out _); // Act var query = scope.SqlContext.Query <IMedia>().Where(x => x.Level == 2); var filter = scope.SqlContext.Query <IMedia>().Where(x => x.Name.Contains("Test")); var result = repository.GetPage(query, 0, 1, out var totalRecords, filter, Ordering.By("SortOrder")); // Assert Assert.That(totalRecords, Is.EqualTo(2)); Assert.That(result.Count(), Is.EqualTo(1)); Assert.That(result.First().Name, Is.EqualTo("Test Image")); } }
public void GetPagedResultsByQuery_AlternateOrder() { // Arrange IScopeProvider provider = ScopeProvider; using (IScope scope = provider.CreateScope()) { MediaRepository repository = CreateRepository(provider, out MediaTypeRepository mediaTypeRepository); // Act IQuery <IMedia> query = provider.CreateQuery <IMedia>().Where(x => x.Level == 2); IEnumerable <IMedia> result = repository.GetPage(query, 0, 1, out long totalRecords, null, Ordering.By("Name")); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); Assert.That(result.Count(), Is.EqualTo(1)); Assert.That(result.First().Name, Is.EqualTo("Test File")); } }
public void GetPagedResultsByQuery_DescendingOrder() { // Arrange var provider = TestObjects.GetScopeProvider(Logger); using (var scope = provider.CreateScope()) { MediaTypeRepository mediaTypeRepository; var repository = CreateRepository(provider, out mediaTypeRepository); // Act var query = scope.SqlContext.Query <IMedia>().Where(x => x.Level == 2); long totalRecords; var result = repository.GetPage(query, 0, 1, out totalRecords, null, Ordering.By("SortOrder", Direction.Descending)); // Assert Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2)); Assert.That(result.Count(), Is.EqualTo(1)); Assert.That(result.First().Name, Is.EqualTo("Test File")); } }
public void GetPagedResultsByQuery_FilterMatchingAll() { // Arrange IScopeProvider provider = ScopeProvider; using (IScope scope = provider.CreateScope()) { MediaRepository repository = CreateRepository(provider, out _); // Act IQuery <IMedia> query = provider.CreateQuery <IMedia>().Where(x => x.Level == 2); IQuery <IMedia> filter = provider.CreateQuery <IMedia>().Where(x => x.Name.Contains("Test")); IEnumerable <IMedia> result = repository.GetPage(query, 0, 1, out long totalRecords, filter, Ordering.By("SortOrder")); // Assert Assert.That(totalRecords, Is.EqualTo(2)); Assert.That(result.Count(), Is.EqualTo(1)); Assert.That(result.First().Name, Is.EqualTo("Test Image")); } }
public PagedResult <ContentItemBasic <ContentPropertyBasic> > GetChildren(int id, int pageNumber = 0, int pageSize = 0, string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "") { //if a request is made for the root node data but the user's start node is not the default, then // we need to return their start nodes if (id == Constants.System.Root && UserStartNodes.Length > 0 && UserStartNodes.Contains(Constants.System.Root) == false) { if (pageNumber > 0) { return(new PagedResult <ContentItemBasic <ContentPropertyBasic> >(0, 0, 0)); } var nodes = _mediaService.GetByIds(UserStartNodes).ToArray(); if (nodes.Length == 0) { return(new PagedResult <ContentItemBasic <ContentPropertyBasic> >(0, 0, 0)); } if (pageSize < nodes.Length) { pageSize = nodes.Length; // bah } var pr = new PagedResult <ContentItemBasic <ContentPropertyBasic> >(nodes.Length, pageNumber, pageSize) { Items = nodes.Select(_umbracoMapper.Map <IMedia, ContentItemBasic <ContentPropertyBasic> >) }; return(pr); } // else proceed as usual long totalChildren; List <IMedia> children; if (pageNumber > 0 && pageSize > 0) { IQuery <IMedia> queryFilter = null; if (filter.IsNullOrWhiteSpace() == false) { //add the default text filter queryFilter = _sqlContext.Query <IMedia>() .Where(x => x.Name.Contains(filter)); } children = _mediaService .GetPagedChildren( id, (pageNumber - 1), pageSize, out totalChildren, queryFilter, Ordering.By(orderBy, orderDirection, isCustomField: !orderBySystemField)).ToList(); } else { //better to not use this without paging where possible, currently only the sort dialog does children = _mediaService.GetPagedChildren(id, 0, int.MaxValue, out var total).ToList(); totalChildren = children.Count; } if (totalChildren == 0) { return(new PagedResult <ContentItemBasic <ContentPropertyBasic> >(0, 0, 0)); } var pagedResult = new PagedResult <ContentItemBasic <ContentPropertyBasic> >(totalChildren, pageNumber, pageSize); pagedResult.Items = children .Select(_umbracoMapper.Map <IMedia, ContentItemBasic <ContentPropertyBasic> >); return(pagedResult); }
public PagedResult <EntityBasic> GetPagedDescendants( int id, UmbracoEntityTypes type, int pageNumber, int pageSize, bool ignoreUserStartNodes, string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "") { if (pageNumber <= 0) { throw new HttpResponseException(HttpStatusCode.NotFound); } if (pageSize <= 0) { throw new HttpResponseException(HttpStatusCode.NotFound); } var objectType = ConvertToObjectType(type); if (objectType.HasValue) { IEnumerable <IUmbracoEntity> entities; long totalRecords; if (id == Constants.System.Root) { // root is special: we reduce it to start nodes int[] aids = null; switch (type) { case UmbracoEntityTypes.Document: aids = Security.CurrentUser.CalculateContentStartNodeIds(Services.EntityService); break; case UmbracoEntityTypes.Media: aids = Security.CurrentUser.CalculateMediaStartNodeIds(Services.EntityService); break; } entities = aids == null || aids.Contains(Constants.System.Root) || ignoreUserStartNodes ? Services.EntityService.GetPagedDescendants(objectType.Value, pageNumber - 1, pageSize, out totalRecords, SqlContext.Query <IUmbracoEntity>().Where(x => x.Name.Contains(filter)), Ordering.By(orderBy, orderDirection), includeTrashed : false) : Services.EntityService.GetPagedDescendants(aids, objectType.Value, pageNumber - 1, pageSize, out totalRecords, SqlContext.Query <IUmbracoEntity>().Where(x => x.Name.Contains(filter)), Ordering.By(orderBy, orderDirection)); } else { entities = Services.EntityService.GetPagedDescendants(id, objectType.Value, pageNumber - 1, pageSize, out totalRecords, SqlContext.Query <IUmbracoEntity>().Where(x => x.Name.Contains(filter)), Ordering.By(orderBy, orderDirection)); } if (totalRecords == 0) { return(new PagedResult <EntityBasic>(0, 0, 0)); } var pagedResult = new PagedResult <EntityBasic>(totalRecords, pageNumber, pageSize) { Items = entities.Select(MapEntities()) }; return(pagedResult); } //now we need to convert the unknown ones switch (type) { case UmbracoEntityTypes.PropertyType: case UmbracoEntityTypes.PropertyGroup: case UmbracoEntityTypes.Domain: case UmbracoEntityTypes.Language: case UmbracoEntityTypes.User: case UmbracoEntityTypes.Macro: default: throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + type); } }
/// <summary> /// Updates indexes based on content changes /// </summary> /// <param name="sender"></param> /// <param name="args"></param> public void Handle(ContentCacheRefresherNotification args) { if (!_umbracoIndexingHandler.Enabled) { return; } if (Suspendable.ExamineEvents.CanIndex == false) { return; } if (args.MessageType != MessageType.RefreshByPayload) { throw new NotSupportedException(); } // Used to track permanent deletions so we can bulk delete from the index // when needed. For example, when emptying the recycle bin, else it will // individually update the index which will be much slower. HashSet <int> deleteBatch = null; foreach (var payload in (ContentCacheRefresher.JsonPayload[])args.MessageObject) { if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove)) { if (deleteBatch == null) { deleteBatch = new HashSet <int>(); } deleteBatch.Add(payload.Id); } else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll)) { // ExamineEvents does not support RefreshAll // just ignore that payload // so what?! // TODO: Rebuild the index at this point? } else // RefreshNode or RefreshBranch (maybe trashed) { if (deleteBatch != null && deleteBatch.Contains(payload.Id)) { // the same node has already been deleted, to ensure ordering is // handled, we'll need to execute all queued deleted items now // and reset the deleted items list. _umbracoIndexingHandler.DeleteIndexForEntities(deleteBatch, false); deleteBatch = null; } // don't try to be too clever - refresh entirely // there has to be race conditions in there ;-( var content = _contentService.GetById(payload.Id); if (content == null) { // gone fishing, remove entirely from all indexes (with descendants) _umbracoIndexingHandler.DeleteIndexForEntity(payload.Id, false); continue; } IContent published = null; if (content.Published && _contentService.IsPathPublished(content)) { published = content; } if (published == null) { _umbracoIndexingHandler.DeleteIndexForEntity(payload.Id, true); } // just that content _umbracoIndexingHandler.ReIndexForContent(content, published != null); // branch if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch)) { var masked = published == null ? null : new List <int>(); const int pageSize = 500; var page = 0; var total = long.MaxValue; while (page * pageSize < total) { var descendants = _contentService.GetPagedDescendants(content.Id, page++, pageSize, out total, //order by shallowest to deepest, this allows us to check it's published state without checking every item ordering: Ordering.By("Path", Direction.Ascending)); foreach (var descendant in descendants) { published = null; if (masked != null) // else everything is masked { if (masked.Contains(descendant.ParentId) || !descendant.Published) { masked.Add(descendant.Id); } else { published = descendant; } } _umbracoIndexingHandler.ReIndexForContent(descendant, published != null); } } } } // NOTE // // DeleteIndexForEntity is handled by UmbracoContentIndexer.DeleteFromIndex() which takes // care of also deleting the descendants // // ReIndexForContent is NOT taking care of descendants so we have to reload everything // again in order to process the branch - we COULD improve that by just reloading the // XML from database instead of reloading content & re-serializing! // // BUT ... pretty sure it is! see test "Index_Delete_Index_Item_Ensure_Heirarchy_Removed" } if (deleteBatch != null) { // process the delete batch _umbracoIndexingHandler.DeleteIndexForEntities(deleteBatch, false); } }