/// <summary> /// Create content /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentType">Type of content, usually page</param> /// <param name="title">Title for the content</param> /// <param name="spaceKey">Key of the space to add the content to</param> /// <param name="body">the complete body (HTML)</param> /// <param name="ancestorId">Optional ID for the ancestor (parent)</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Content</returns> public static Task <Content> CreateAsync(this IContentDomain confluenceClient, ContentTypes contentType, string title, string spaceKey, string body, long?ancestorId = null, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(title)) { throw new ArgumentNullException(nameof(title)); } if (string.IsNullOrEmpty(spaceKey)) { throw new ArgumentNullException(nameof(spaceKey)); } if (string.IsNullOrEmpty(body)) { throw new ArgumentNullException(nameof(body)); } var contentBody = new Body { Storage = new BodyContent { Value = body, Representation = "storage" } }; return(confluenceClient.CreateAsync(contentType, title, spaceKey, contentBody, ancestorId, cancellationToken)); }
/// <summary> /// Get content by title /// See: https://docs.atlassian.com/confluence/REST/latest/#d2e4539 /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="spaceKey">Space key</param> /// <param name="title">Title of the content</param> /// <param name="start">Start of the results, used for paging</param> /// <param name="limit">Maximum number of results returned, default is 20</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Results with content items</returns> public static async Task <Result <Content> > GetByTitleAsync(this IContentDomain confluenceClient, string spaceKey, string title, int start = 0, int limit = 20, CancellationToken cancellationToken = default) { confluenceClient.Behaviour.MakeCurrent(); var searchUri = confluenceClient.ConfluenceApiUri.AppendSegments("content").ExtendQuery(new Dictionary <string, object> { { "start", start }, { "limit", limit }, { "type", "page" }, { "spaceKey", spaceKey }, { "title", title } }); var expand = string.Join(",", ConfluenceClientConfig.ExpandGetContentByTitle ?? Enumerable.Empty <string>()); if (!string.IsNullOrEmpty(expand)) { searchUri = searchUri.ExtendQuery("expand", expand); } var response = await searchUri.GetAsAsync <HttpResponse <Result <Content>, Error> >(cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Create content /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentType">Type of content, usually page</param> /// <param name="title">Title for the content</param> /// <param name="spaceKey">Key of the space to add the content to</param> /// <param name="body">Body</param> /// <param name="ancestorId">Optional ID for the ancestor (parent)</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Content</returns> public static Task <Content> CreateAsync(this IContentDomain confluenceClient, ContentTypes contentType, string title, string spaceKey, Body body, long?ancestorId = null, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(title)) { throw new ArgumentNullException(nameof(title)); } if (string.IsNullOrEmpty(spaceKey)) { throw new ArgumentNullException(nameof(spaceKey)); } if (body == null) { throw new ArgumentNullException(nameof(body)); } var content = new Content { Type = contentType, Title = title, Space = new Space { Key = spaceKey }, Body = body, Ancestors = !ancestorId.HasValue ? null : new List <Content> { new Content { Id = ancestorId.Value } } }; return(confluenceClient.CreateAsync(content, cancellationToken)); }
/// <summary> /// Get Content information see <a href="https://docs.atlassian.com/confluence/REST/latest/#d3e164">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">content id</param> /// <param name="cancellationToken">CancellationToken</param> /// <param name="start">int specifying where to start, used for paging.</param> /// <param name="limit">int used to limit the amount of results, used for paging.</param> /// <param name="parentVersion">int representing the version of the content to retrieve children for.</param> /// <returns>List with Content</returns> public static async Task <Result <Content> > GetChildrenAsync(this IContentDomain confluenceClient, long contentId, int?start = null, int?limit = null, int?parentVersion = null, CancellationToken cancellationToken = default) { var contentUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId, "child", "page"); if (start.HasValue) { contentUri = contentUri.ExtendQuery("start", start); } if (limit.HasValue) { contentUri = contentUri.ExtendQuery("limit", limit); } if (parentVersion.HasValue) { contentUri = contentUri.ExtendQuery("parentVersion", parentVersion); } var expand = string.Join(",", ConfluenceClientConfig.ExpandGetChildren ?? Enumerable.Empty <string>()); if (!string.IsNullOrEmpty(expand)) { contentUri = contentUri.ExtendQuery("expand", expand); } confluenceClient.Behaviour.MakeCurrent(); var response = await contentUri.GetAsAsync <HttpResponse <Result <Content>, Error> >(cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Create content /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="content">Content (e.g. Page) to create</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Content</returns> public static async Task <Content> CreateAsync(this IContentDomain confluenceClient, Content content, CancellationToken cancellationToken = default) { var contentUri = confluenceClient.ConfluenceApiUri.AppendSegments("content"); confluenceClient.Behaviour.MakeCurrent(); var response = await contentUri.PostAsync <HttpResponse <Content, Error> >(content, cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Get Labels for content see <a href="https://docs.atlassian.com/confluence/REST/latest/#content/{id}/label">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">content id</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Result with labels</returns> public static async Task <Result <Label> > GetLabelsAsync(this IContentDomain confluenceClient, long contentId, CancellationToken cancellationToken = default) { var labelUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId, "label"); confluenceClient.Behaviour.MakeCurrent(); var response = await labelUri.GetAsAsync <HttpResponse <Result <Label>, Error> >(cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Add Labels to content see <a href="https://docs.atlassian.com/confluence/REST/latest/#content/{id}/label">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">content id</param> /// <param name="labels">IEnumerable labels</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Task</returns> public static async Task AddLabelsAsync(this IContentDomain confluenceClient, long contentId, IEnumerable <Label> labels, CancellationToken cancellationToken = default) { var labelUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId, "label"); confluenceClient.Behaviour.MakeCurrent(); var response = await labelUri.PostAsync <HttpResponseWithError <Error> >(labels, cancellationToken).ConfigureAwait(false); response.HandleStatusCode(); }
/// <summary> /// Get Content History information see <a href="https://docs.atlassian.com/confluence/REST/latest/#d3e164">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">content id</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Content</returns> public static async Task <History> GetHistoryAsync(this IContentDomain confluenceClient, long contentId, CancellationToken cancellationToken = default(CancellationToken)) { var historyUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId, "history"); confluenceClient.Behaviour.MakeCurrent(); var response = await historyUri.GetAsAsync <HttpResponse <History, Error> >(cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Delete Label for content see <a href="https://docs.atlassian.com/confluence/REST/latest/#content/{id}/label">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">content id</param> /// <param name="label">Name of label</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Task</returns> public static async Task DeleteLabelAsync(this IContentDomain confluenceClient, long contentId, string label, CancellationToken cancellationToken = default) { var labelUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId, "label", label); confluenceClient.Behaviour.MakeCurrent(); var response = await labelUri.DeleteAsync <HttpResponse>(cancellationToken).ConfigureAwait(false); response.HandleStatusCode(HttpStatusCode.NoContent); }
/// <summary> /// Create content /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentType">Type of content, usually page</param> /// <param name="title">Title for the content</param> /// <param name="spaceKey">Key of the space to add the content to</param> /// <param name="body">the complete body (HTML)</param> /// <param name="ancestorId">Optional ID for the ancestor (parent)</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Content</returns> public static Task <Content> CreateAsync(this IContentDomain confluenceClient, ContentTypes contentType, string title, string spaceKey, string body, long?ancestorId = null, CancellationToken cancellationToken = default) { var contentBody = new Body { Storage = new BodyContent { Value = body, Representation = "storage" } }; return(confluenceClient.CreateAsync(contentType, title, spaceKey, contentBody, ancestorId, cancellationToken)); }
/// <summary> /// Update content /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="content">Content to update</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Content</returns> public static async Task <Content> UpdateAsync(this IContentDomain confluenceClient, Content content, CancellationToken cancellationToken = default) { if (content == null) { throw new ArgumentNullException(nameof(content)); } var contentUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", content.Id); confluenceClient.Behaviour.MakeCurrent(); var response = await contentUri.PutAsync <HttpResponse <Content, Error> >(content, cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Delete content (attachments are also content) /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">ID for the content which needs to be deleted</param> /// <param name="isTrashed">If the content is trashable, you will need to call DeleteAsyc twice, second time with isTrashed = true</param> /// <param name="cancellationToken">CancellationToken</param> public static async Task DeleteAsync(this IContentDomain confluenceClient, long contentId, bool isTrashed = false, CancellationToken cancellationToken = default) { var contentUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId); if (isTrashed) { contentUri = contentUri.ExtendQuery("status", "trashed"); } confluenceClient.Behaviour.MakeCurrent(); var response = await contentUri.DeleteAsync <HttpResponse>(cancellationToken).ConfigureAwait(false); response.HandleStatusCode(isTrashed ? HttpStatusCode.OK : HttpStatusCode.NoContent); }
/// <summary> /// Get Content information see <a href="https://docs.atlassian.com/confluence/REST/latest/#d3e164">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">content id</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>List with Content</returns> public static async Task <IList <Content> > GetChildrenAsync(this IContentDomain confluenceClient, long contentId, CancellationToken cancellationToken = default(CancellationToken)) { var contentUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId, "child"); if (ConfluenceClientConfig.ExpandGetChildren != null && ConfluenceClientConfig.ExpandGetChildren.Length != 0) { contentUri = contentUri.ExtendQuery("expand", string.Join(",", ConfluenceClientConfig.ExpandGetChildren)); } confluenceClient.Behaviour.MakeCurrent(); var response = await contentUri.GetAsAsync <HttpResponse <Children, Error> >(cancellationToken).ConfigureAwait(false); return(response.HandleErrors().Result?.Results); }
/// <summary> /// Get Content information see <a href="https://docs.atlassian.com/confluence/REST/latest/#d3e164">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">content id (as content implements an implicit cast, you can also pass the content instance)</param> /// <param name="expandGetContent">Specify the expand values, if null the default from the configuration is used</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Content</returns> public static async Task <Content> GetAsync(this IContentDomain confluenceClient, long contentId, IEnumerable <string> expandGetContent = null, CancellationToken cancellationToken = default) { var contentUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId); var expand = string.Join(",", expandGetContent ?? ConfluenceClientConfig.ExpandGetContent ?? Enumerable.Empty <string>()); if (!string.IsNullOrEmpty(expand)) { contentUri = contentUri.ExtendQuery("expand", expand); } confluenceClient.Behaviour.MakeCurrent(); var response = await contentUri.GetAsAsync <HttpResponse <Content, Error> >(cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Add Labels to content see <a href="https://docs.atlassian.com/confluence/REST/latest/#content/{id}/label">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">content id</param> /// <param name="labels">IEnumerable labels</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Task</returns> public static async Task AddLabelsAsync(this IContentDomain confluenceClient, long contentId, IEnumerable <Label> labels, CancellationToken cancellationToken = default) { if (contentId == 0) { throw new ArgumentNullException(nameof(contentId)); } if (labels == null || !labels.Any()) { throw new ArgumentNullException(nameof(labels)); } var labelUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId, "label"); confluenceClient.Behaviour.MakeCurrent(); var response = await labelUri.PostAsync <HttpResponseWithError <Error> >(labels, cancellationToken).ConfigureAwait(false); response.HandleStatusCode(); }
/// <summary> /// Possible since 5.7 /// Search for issues, with a CQL (e.g. from a filter) see /// <a href="https://docs.atlassian.com/confluence/REST/latest/#d2e4539">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="cqlClause">Confluence Query Language, like SQL, for the search</param> /// <param name="cqlContext"> /// the execution context for CQL functions, provides current space key and content id. If this is /// not provided some CQL functions will not be available. /// </param> /// <param name="pagingInformation">PagingInformation</param> /// <param name="expandSearch">The expand value for the search, when null the value from the ConfluenceClientConfig.ExpandSearch is taken</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Result with content items</returns> public static Task <Result <Content> > SearchAsync(this IContentDomain confluenceClient, IFinalClause cqlClause, string cqlContext = null, PagingInformation pagingInformation = null, IEnumerable <string> expandSearch = null, CancellationToken cancellationToken = default) { var searchDetails = new SearchDetails(cqlClause) { Start = pagingInformation?.Start, Limit = pagingInformation?.Limit }; if (cqlContext != null) { searchDetails.CqlContext = cqlContext; } if (expandSearch != null) { searchDetails.ExpandSearch = expandSearch; } return(confluenceClient.SearchAsync(searchDetails, cancellationToken)); }
/// <summary> /// Delete Label for content see <a href="https://docs.atlassian.com/confluence/REST/latest/#content/{id}/label">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentId">content id</param> /// <param name="label">Name of label</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Task</returns> public static async Task DeleteLabelAsync(this IContentDomain confluenceClient, long contentId, string label, CancellationToken cancellationToken = default) { if (contentId == 0) { throw new ArgumentNullException(nameof(contentId)); } if (string.IsNullOrEmpty(label)) { throw new ArgumentNullException(nameof(label)); } var labelUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", contentId, "label", label); confluenceClient.Behaviour.MakeCurrent(); var response = await labelUri.DeleteAsync <HttpResponse>(cancellationToken).ConfigureAwait(false); response.HandleStatusCode(HttpStatusCode.NoContent); }
/// <summary> /// Possible since 5.7 /// Search for issues, with a CQL (e.g. from a filter) see /// <a href="https://docs.atlassian.com/confluence/REST/latest/#d2e4539">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="cql">Confluence Query Language, like SQL, for the search</param> /// <param name="cqlContext"> /// the execution context for CQL functions, provides current space key and content id. If this is /// not provided some CQL functions will not be available. /// </param> /// <param name="limit">Maximum number of results returned, default is 20</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Result with content items</returns> public static async Task <Result <Content> > SearchAsync(this IContentDomain confluenceClient, string cql, string cqlContext = null, int limit = 20, CancellationToken cancellationToken = default(CancellationToken)) { confluenceClient.Behaviour.MakeCurrent(); var searchUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", "search").ExtendQuery("cql", cql).ExtendQuery("limit", limit); if (ConfluenceClientConfig.ExpandSearch != null && ConfluenceClientConfig.ExpandSearch.Length != 0) { searchUri = searchUri.ExtendQuery("expand", string.Join(",", ConfluenceClientConfig.ExpandSearch)); } if (cqlContext != null) { searchUri = searchUri.ExtendQuery("cqlcontext", cqlContext); } var response = await searchUri.GetAsAsync <HttpResponse <Result <Content>, Error> >(cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Create content /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="contentType">Type of content, usually page</param> /// <param name="title">Title for the content</param> /// <param name="spaceKey">Key of the space to add the content to</param> /// <param name="body">Body</param> /// <param name="ancestorId">Optional ID for the ancestor (parent)</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Content</returns> public static Task <Content> CreateAsync(this IContentDomain confluenceClient, ContentTypes contentType, string title, string spaceKey, Body body, long?ancestorId = null, CancellationToken cancellationToken = default) { var content = new Content { Type = contentType, Title = title, Space = new Space { Key = spaceKey }, Body = body, Ancestors = !ancestorId.HasValue ? null : new List <Content> { new Content { Id = ancestorId.Value } } }; return(confluenceClient.CreateAsync(content, cancellationToken)); }
/// <summary> /// Possible since 5.7 /// Search for issues, with a CQL (e.g. from a filter) see /// <a href="https://docs.atlassian.com/confluence/REST/latest/#d2e4539">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="cql">Confluence Query Language, like SQL, for the search</param> /// <param name="cqlContext"> /// the execution context for CQL functions, provides current space key and content id. If this is /// not provided some CQL functions will not be available. /// </param> /// <param name="limit">Maximum number of results returned, default is 20</param> /// <param name="expandSearch">The expand value for the search, when null the value from the ConfluenceClientConfig.ExpandSearch is taken</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Result with content items</returns> public static async Task <Result <Content> > SearchAsync(this IContentDomain confluenceClient, string cql, string cqlContext = null, int limit = 20, IEnumerable <string> expandSearch = null, CancellationToken cancellationToken = default) { confluenceClient.Behaviour.MakeCurrent(); var searchUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", "search").ExtendQuery("cql", cql).ExtendQuery("limit", limit); var expand = string.Join(",", expandSearch ?? ConfluenceClientConfig.ExpandSearch ?? Enumerable.Empty <string>()); if (!string.IsNullOrEmpty(expand)) { searchUri = searchUri.ExtendQuery("expand", expand); } if (cqlContext != null) { searchUri = searchUri.ExtendQuery("cqlcontext", cqlContext); } var response = await searchUri.GetAsAsync <HttpResponse <Result <Content>, Error> >(cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Possible since 5.7 /// Search for issues, with a CQL (e.g. from a filter) see /// <a href="https://docs.atlassian.com/confluence/REST/latest/#d2e4539">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="searchDetails">All the details needed for a search</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Result with content items</returns> public static async Task <Result <Content> > SearchAsync(this IContentDomain confluenceClient, SearchDetails searchDetails, CancellationToken cancellationToken = default) { if (searchDetails == null) { throw new ArgumentNullException(nameof(searchDetails)); } confluenceClient.Behaviour.MakeCurrent(); var searchUri = confluenceClient.ConfluenceApiUri.AppendSegments("content", "search").ExtendQuery("cql", searchDetails.Cql); if (searchDetails.Limit.HasValue) { searchUri = searchUri.ExtendQuery("limit", searchDetails.Limit); } if (searchDetails.Start.HasValue) { searchUri = searchUri.ExtendQuery("start", searchDetails.Start); } var expand = string.Join(",", searchDetails.ExpandSearch ?? ConfluenceClientConfig.ExpandSearch ?? Enumerable.Empty <string>()); if (!string.IsNullOrEmpty(expand)) { searchUri = searchUri.ExtendQuery("expand", expand); } if (searchDetails.CqlContext != null) { searchUri = searchUri.ExtendQuery("cqlcontext", searchDetails.CqlContext); } var response = await searchUri.GetAsAsync <HttpResponse <Result <Content>, Error> >(cancellationToken).ConfigureAwait(false); return(response.HandleErrors()); }
/// <summary> /// Possible since 5.7 /// Search for issues, with a CQL (e.g. from a filter) see /// <a href="https://docs.atlassian.com/confluence/REST/latest/#d2e4539">here</a> /// </summary> /// <param name="confluenceClient">IContentDomain to bind the extension method to</param> /// <param name="cqlClause">Confluence Query Language clause, created via Where</param> /// <param name="cqlContext"> /// the execution context for CQL functions, provides current space key and content id. If this is /// not provided some CQL functions will not be available. /// </param> /// <param name="limit">Maximum number of results returned, default is 20</param> /// <param name="expandSearch">The expand value for the search, when null the value from the ConfluenceClientConfig.ExpandSearch is taken</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>Result with content items</returns> public static Task <Result <Content> > SearchAsync(this IContentDomain confluenceClient, IFinalClause cqlClause, string cqlContext = null, int limit = 20, IEnumerable <string> expandSearch = null, CancellationToken cancellationToken = default) { return(confluenceClient.SearchAsync(cqlClause.ToString(), cqlContext, limit, expandSearch, cancellationToken)); }