Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Beta/Users.User/Users.User/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ input-file: $(spec-doc-repo)/$(title).yml
### Versioning

``` yaml
module-version: 0.5.1
module-version: 0.7.0
release-notes: See https://aka.ms/GraphPowerShell-Release.
```
16 changes: 13 additions & 3 deletions src/readme.graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ directive:
parameter-name: Top
set:
parameter-name: PageSize
alias: Top
alias:
- Top
- Limit
- where:
parameter-name: Select
set:
Expand Down Expand Up @@ -378,7 +380,7 @@ directive:
}
return $;
}
# Temporarily disable paging.
# Add custom -All parameter to *_List cmdlets that support Odata next link.
- from: source-file-csharp
where: $
transform: >
Expand All @@ -388,7 +390,15 @@ directive:
} else {
let odataNextLinkRegex = /(^\s*)(if\s*\(\s*result.OdataNextLink\s*!=\s*null\s*\))/gmi
if($.match(odataNextLinkRegex)) {
$ = $.replace(odataNextLinkRegex, '$1result.OdataNextLink = null;\n$1if (result.OdataNextLink != null)$1');
$ = $.replace(odataNextLinkRegex, '$1if (result.OdataNextLink != null && this.ShouldIteratePages(this.InvocationInformation.BoundParameters, result.Value.Length))\n$1');
let psBaseClassImplementationRegex = /(\s*:\s*)(global::System.Management.Automation.PSCmdlet)/gmi
$ = $.replace(psBaseClassImplementationRegex, '$1Microsoft.Graph.PowerShell.Cmdlets.Custom.ListCmdlet');

let beginProcessingRegex = /(^\s*)(protected\s*override\s*void\s*BeginProcessing\(\)\s*{)/gmi
$ = $.replace(beginProcessingRegex, '$1$2\n$1$1if (this.InvocationInformation.BoundParameters.ContainsKey("PageSize")){ InitializePaging(ref this.__invocationInfo, ref this._pageSize); }\n$1');

let odataNextLinkCallRegex = /(^\s*)(await\s*this\.Client\.UsersUserListUser_Call\(requestMessage\,\s*onOk\,\s*onDefault\,\s*this\,\s*Pipeline\)\;)/gmi
$ = $.replace(odataNextLinkCallRegex, '$1requestMessage.RequestUri = GetOverflowItemsNextLinkUri(requestMessage.RequestUri);\n$1$2');
}
return $;
}
Expand Down
118 changes: 118 additions & 0 deletions tools/Custom/ListCmdlet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// ------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
// ------------------------------------------------------------------------------
namespace Microsoft.Graph.PowerShell.Cmdlets.Custom
{

public partial class ListCmdlet : global::System.Management.Automation.PSCmdlet
{
/// <summary>Backing field for <see cref="All" /> property.</summary>
private global::System.Management.Automation.SwitchParameter _all;

/// <summary>List All pages</summary>
[global::System.Management.Automation.Parameter(Mandatory = false, HelpMessage = "List all pages")]
[Microsoft.Graph.PowerShell.Runtime.Info(
Required = false,
ReadOnly = false,
Description = @"List all pages",
SerializedName = @"$all",
PossibleTypes = new[] { typeof(global::System.Management.Automation.SwitchParameter) })]
[global::Microsoft.Graph.PowerShell.Category(global::Microsoft.Graph.PowerShell.ParameterCategory.Runtime)]
public global::System.Management.Automation.SwitchParameter All { get => this._all; set => this._all = value; }

/// <summary>
/// Default number of items per page.
/// </summary>
internal const int DefaultPageSize = 100;

/// <summary>
/// Maximum number of items per page.
/// </summary>
internal const int MaxPageSize = 999;

/// <summary>
/// Original page size/top/limit passed to Cmdlet via parameter.
/// </summary>
internal int originalPageSize = 0;

/// <summary>
/// Total number of pages required to iterate page collections excluding overflow items.
/// </summary>
internal int requiredPages = 0;

/// <summary>
/// A count of iterated pages thus far.
/// </summary>
internal int iteratedPages = 0;

/// <summary>
/// Total number of overflow items, less than the maximum number of items in a page.
/// Modulus of original page size.
/// </summary>
internal int overflowItemsCount = 0;

/// <summary>
/// Total number of fetched items.
/// </summary>
internal int totalFetchedItems = 0;

/// <summary>
/// Initializes paging values.
/// </summary>
/// <param name="invocationInfo">A reference to <see cref="System.Management.Automation.InvocationInfo"/> object.</param>
/// <param name="PageSize">A reference to page size parameter.</param>
public void InitializePaging(ref global::System.Management.Automation.InvocationInfo invocationInfo, ref int PageSize)
{
if (PageSize > MaxPageSize)
{
invocationInfo.BoundParameters["All"] = true;
originalPageSize = PageSize;
requiredPages = PageSize / DefaultPageSize;
overflowItemsCount = PageSize % DefaultPageSize;
invocationInfo.BoundParameters["PageSize"] = DefaultPageSize;
PageSize = DefaultPageSize;
}
}

/// <summary>
/// Determines whether the cmdlet should follow the OData next link url.
/// </summary>
/// <param name="boundParameters">The bound parameters of the cmdlet.</param>
/// <param name="itemsCount">Current page items count.</param>
/// <returns>True if it can iterate pages; False if it can't.</returns>
public bool ShouldIteratePages(global::System.Collections.Generic.Dictionary<string, object> boundParameters, int itemsCount)
{
iteratedPages++;
totalFetchedItems += itemsCount;
if ((boundParameters.ContainsKey("All") && !boundParameters.ContainsKey("PageSize")) ||
(boundParameters.ContainsKey("PageSize") && totalFetchedItems < originalPageSize))
return true;
else
return false;
}

/// <summary>
/// Gets an OData next link for the overflow items.
/// </summary>
/// <param name="requestUri">The OData next link returned by the service.</param>
/// <returns>An OData next link URI for the overflow items.</returns>
public global::System.Uri GetOverflowItemsNextLinkUri(global::System.Uri requestUri)
{
var nextLinkUri = new global::System.UriBuilder(requestUri);
if (requiredPages == iteratedPages && overflowItemsCount > 0)
{
if (nextLinkUri.Query.Contains("$top"))
{
global::System.Collections.Specialized.NameValueCollection queryString = global::System.Web.HttpUtility.ParseQueryString(nextLinkUri.Query);
queryString["$top"] = global::System.Uri.EscapeDataString(overflowItemsCount.ToString());
nextLinkUri.Query = queryString.ToString();
}
else
{
nextLinkUri.Query += $"$top=" + global::System.Uri.EscapeDataString(overflowItemsCount.ToString());
}
}
return nextLinkUri.Uri;
}
}
}