diff --git a/docs/Examples.md b/docs/Examples.md
deleted file mode 100644
index d4746429da6..00000000000
--- a/docs/Examples.md
+++ /dev/null
@@ -1,762 +0,0 @@
-# Usage Examples
-
-## Creating a Graph client
-This creates a default Graph client that uses `https://graph.microsoft.com` as the default base URL and default configured Guzzle HTTP client to make the requests.
-
-To make requests with a signed-in user, you can initialise an `AuthorizationCodeContext` with the code returned by Microsoft Identity after redirecting the
-user to the sign-in page. The same redirect URI provided while requesting the auth code is required:
-
-```php
-
-use Microsoft\Graph\GraphServiceClient;
-use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
-
-$tokenRequestContext = new AuthorizationCodeContext(
- 'tenantId',
- 'clientId',
- 'clientSecret',
- 'authCode',
- 'redirectUri'
-);
-$scopes = ['User.Read', 'Mail.ReadWrite'];
-$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
-
-```
-
-To make requests on behalf of an already signed in user, where your front-end application has already acquired an access token for the user, you can use the `OnBehalfOfContext` which uses the [On-Behalf-Of flow](https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow) to fetch
-an access token for your backend application to access the Microsoft Graph API. To do this, you pass the already acquired access token as the "assertion";
-
-```php
-use Microsoft\Graph\GraphServiceClient;
-use Microsoft\Kiota\Authentication\Oauth\OnBehalfOfContext;
-
-$tokenRequestContext = new OnBehalfOfContext(
- 'tenantId',
- 'clientId',
- 'clientSecret',
- 'assertion'
-);
-
-$scopes = ['User.Read', 'Mail.ReadWrite'];
-$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
-
-```
-
-
-To make requests without a signed-in user (using application permissions), you can initialise a `ClientCredentialsContext` object:
-
-```php
-use Microsoft\Graph\GraphServiceClient;
-use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext;
-
-// Uses https://graph.microsoft.com/.default scopes if none are specified
-$tokenRequestContext = new ClientCredentialContext(
- 'tenantId',
- 'clientId',
- 'clientSecret'
-);
-$graphServiceClient = new GraphServiceClient($tokenRequestContext);
-
-```
-
-Using a custom National Cloud deployment:
-```php
-$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes, NationalCloud::CHINA);
-```
-
-Customizing the default Guzzle client:
-```php
-
-use Microsoft\Graph\Core\GraphClientFactory;
-use Microsoft\Graph\GraphRequestAdapter;
-use Microsoft\Graph\GraphServiceClient;
-use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
-
-$tokenRequestContext = new ClientCredentialContext(
- 'tenantId',
- 'clientId',
- 'clientSecret'
-);
-$authProvider = new GraphPhpLeagueAuthenticationProvider($tokenRequestContext);
-$guzzleConfig = [
- // your custom config
-];
-$httpClient = GraphClientFactory::createWithConfig($guzzleConfig);
-$requestAdapter = new GraphRequestAdapter($authProvider, $httpClient);
-$graphServiceClient = GraphServiceClient::createWithRequestAdapter($requestAdapter);
-
-```
-
-## Access token management
-
-Using the `TokenRequestContext`, an instance of the `GraphServiceClient` requests access tokens and refresh tokens.
-The tokens are stored by default in an in-memory cache so that future requests using the same instance of the `GraphServiceClient` can re-use the previously acquired tokens.
-
-The default in-memory cache is a map/dictionary with a unique key identifying a user/application with a tenant and a PHPLeague [`AccessToken`](https://github.com/thephpleague/oauth2-client/blob/master/src/Token/AccessToken.php) object as its value. The unique key ensures the right token for a user is retrieved from the cache. For `TokenRequestContexts` that do not require a signed-in user (application permissions), the cache key will be **`{tenantId}-{clientId}`** and for those that require a signed-in user (delegated permissions), the cache key will be
-**`{tenantId}-{clientId}-{userId}`**. The `AccessToken` object carries both the `access_token`, its expiry and a `refresh_token` if available.
-The in-memory cache lives as a PHP object within your application's PHP process and is destroyed when the process terminates.
-
-For scenarios where an application requires a signed-in user, retaining the same
-instance of the `GraphServiceClient` across multiple requests to your application for the same user's session is not feasible. This section outlines
-how your application can retrieve access tokens from the SDK and pass already acquired access tokens to the SDK for future requests without the user signing in for each request.
-
-### Retrieving the access token from the SDK
-
-The SDK provides a mechanism to expose the access token and refresh token that it acquires to your application for use in future requests. This would prevent the SDK from making a new
-token request with each `GraphServiceClient` your application instantiates. It also allows your application to prevent its users from signing in with each request within a session.
-
-By default, a `GraphServiceClient` instance caches access tokens in a built-in [`InMemoryAccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/InMemoryAccessTokenCache.php). The cache will be populated with a PHPLeague [`AccessToken`](https://github.com/thephpleague/oauth2-client/blob/master/src/Token/AccessToken.php) object which carries both the `access_token`, its expiry and a `refresh_token` if available. When the `GraphServiceClient` instance is re-used for a request with the same user/application, the in-memory cache is checked for a valid token otherwise a new token request is made.
-
-However, to get the cached token that the SDK requests for a user/application you
-can initialise an `InMemoryAccessTokenCache` or pass a custom implementation of the [`AccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/AccessTokenCache.php) interface and pass it as a parameter when initialising the `GraphServiceClient`. The two approaches are outlined below:
-
-### Using an InMemoryAccessTokenCache instance
-
-```php
-use Microsoft\Kiota\Authentication\Cache\InMemoryAccessTokenCache;
-use Microsoft\Graph\GraphServiceClient;
-use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAccessTokenProvider;
-use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
-use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
-
-$tokenRequestContext = new AuthorizationCodeContext(
- 'tenantId',
- 'clientId',
- 'clientSecret',
- 'authCode',
- 'redirectUri'
-);
-$scopes = ['User.Read', 'Mail.ReadWrite'];
-
-$inMemoryCache = new InMemoryAccessTokenCache();
-
-$graphServiceClient = GraphServiceClient::createWithAuthenticationProvider(
- GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
- GraphPhpLeagueAccessTokenProvider::createWithCache(
- $inMemoryCache,
- $tokenRequestContext,
- $scopes
- )
- )
-);
-
-$accessToken = $inMemoryCache->getTokenWithContext($tokenRequestContext);
-
-```
-
-### Using a custom AccessTokenCache implementation
-
-A custom [`AccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/AccessTokenCache.php) interface implementation can also be provided. After the request, the SDK persists the token in the
-custom cache via the `persistAccessToken()` method.
-
-By default, the SDK adds a unique cache key/identifier to a `TokenRequestContext` that uniquely identifies the tenant, client and user (if applicable).
-For `TokenRequestContexts` that do not require a signed-in user (application permissions), the cache key will be
-**`{tenantId}-{clientId}`** and for those that require a signed-in user (delegated permissions), the cache key will be
-**`{tenantId}-{clientId}-{userId}`**.
-
-Alternatively, you can override the default cache key
-
-To retrieve the access token persisted to your custom cache for a particular user's/application's `TokenRequestContext`:
-```php
-
-$accessToken = $customCache->getAccessToken($tokenRequestContext->getCacheKey());
-
-```
-
-### Initializing a GraphServiceClient with an access token
-
-For applications that already have built-in mechanisms to fetch and refresh access tokens, the SDK supports passing these tokens to a `GraphServiceClient` by initializing
-a client using an [`AccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/AccessTokenCache.php) interface implementation.
-
-The SDK provides a built-in implementation of this interface via an [`InMemoryAccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/InMemoryAccessTokenCache.php).
-
-This is also useful when re-using a previously retrieved access token for a signed-in user during a previous request.
-
-The SDK will check the cache for a valid token before considering requesting a new token. If the provided token is expired
-and a refresh token is present, the access token will be refreshed and persisted to the cache. If no refresh token is provided, the SDK requests attempts to retrieve a new access token and persists it to the cache. In cases where a signed-in user is present, e.g. authorization_code OAuth flows, the new token request will most likely fail because no valid `authorization_code` will be present meaning the user has to sign in again.
-
-### Using the `InMemoryAccessTokenCache`
-
-The in-memory cache can be hydrated/initialised using the `TokenRequestContext` and a PHPLeague [`AccessToken`](https://github.com/thephpleague/oauth2-client/blob/master/src/Token/AccessToken.php) object for a user/application:
-
-```php
-
-use Microsoft\Kiota\Authentication\Cache\InMemoryAccessTokenCache;
-use Microsoft\Graph\GraphServiceClient;
-use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAccessTokenProvider;
-use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
-use League\OAuth2\Client\Token\AccessToken;
-
-$tokenRequestContext = new AuthorizationCodeContext(
- 'tenantId',
- 'clientId',
- 'clientSecret',
- 'authCode', // use a placeholder value since user is not signed in again
- 'redirectUri'
-);
-
-$cache = new InMemoryAccessTokenCache(
- $tokenRequestContext,
- new AccessToken(
- [
- 'access_token' => $accessToken,
- 'refresh_token' => $refreshToken,
- 'expires' => 1
- ]
- )
-);
-
-$graphServiceClient = GraphServiceClient::createWithAuthenticationProvider(
- GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
- GraphPhpLeagueAccessTokenProvider::createWithCache(
- $cache,
- $tokenRequestContext,
- $scopes
- )
- )
-);
-
-```
-
-For scenarios where your application may need to make requests for multiple users using the same `GraphServiceClient`, the `InMemoryAccessTokenCache` can
-be initialized with multiple TokenRequestContext-AccessToken pairs using `withToken`:
-```php
-
-use Microsoft\Kiota\Authentication\Cache\InMemoryAccessTokenCache;
-use Microsoft\Graph\GraphServiceClient;
-use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAccessTokenProvider;
-use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
-use League\OAuth2\Client\Token\AccessToken;
-
-$tokenRequestContext = new AuthorizationCodeContext(
- 'tenantId',
- 'clientId',
- 'clientSecret',
- 'authCode', // use a placeholder value since user is not signed in again
- 'redirectUri'
-);
-
-$cache = (new InMemoryAccessTokenCache($tokenRequestContext, new AccessToken([
- // ...
-])));
-
-$cache->withToken($tokenRequestContext2, new AccessToken([
- // ...
- ]))->withToken($tokenRequestContext, new AccessToken([
- // ...
- ]))->withToken($tokenRequestContext3, new AccessToken());
-
-
-$graphServiceClient = GraphServiceClient::createWithAuthenticationProvider(
- GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
- GraphPhpLeagueAccessTokenProvider::createWithCache(
- $cache,
- $tokenRequestContext,
- $scopes
- )
- )
-);
-
-```
-
-### Using a custom `AccessTokenCache` implementation`
-
-The SDK retrieves cached tokens using a cache key/identifier on the `TokenRequestContext`. The cache key
-on the `TokenRequestContext` is set using `setCacheKey()` which accepts an [`AccessToken`](https://github.com/thephpleague/oauth2-client/blob/master/src/Token/AccessToken.php) object.
-
-The `TokenRequestContext` uses the `AccessToken` to generate a unique identifier per user, client and tenant. For `TokenRequestContexts` that do not require a signed-in user (application permissions), the cache key will be
-**`{tenantId}-{clientId}`** and for those that require a signed-in user (delegated permissions), the cache key will be
-**`{tenantId}-{clientId}-{userId}`**.
-
-For this scenario, the custom AccessTokenCache will need to be initialized in a way that the cache key set on the
-`TokenRequestContext` aligns with the key the custom AccessTokenCache maps to the user/application's access token
-
-```php
-
-$accessToken = new AccessToken([
- 'access_token' => $accessToken,
- 'refresh_token' => $refreshToken,
- 'expires' => ...
-]);
-
-$tokenRequestContext->setCacheKey($accessToken);
-
-// init custom cache with tokens mapped to specific user/app using $tokenRequestContext->getCacheKey()
-$customCache = new CustomCache($tokenRequestContext->getCacheKey(), $accessToken);
-
-// init graph client
-$graphServiceClient = GraphServiceClient::createWithAuthenticationProvider(
- GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
- GraphPhpLeagueAccessTokenProvider::createWithCache(
- $customCache,
- $tokenRequestContext,
- $scopes
- )
- )
-);
-
-```
-
-## Get an item from the Graph
-This sample fetches the current signed-in user. Note that to use `\me` you need
-a delegated permission. Alternatively, using application permissions, you can request `/users/[userPrincipalName]`.
-See [Microsoft Graph Permissions](https://docs.microsoft.com/en-us/graph/auth/auth-concepts#microsoft-graph-permissions) for more.
-
-
-```php
-$user = $graphServiceClient->me()->get()->wait();
-
-// Or
-
-$user = $graphServiceClient->users()->byUserId('userPrincipalName')->get()->wait();
-```
-
-## Get a collection of items
-Some queries against Microsoft Graph return multiple pages of data either due to server-side paging or due to the use of the $top query parameter to specifically limit the page size in a request. When a result set spans multiple pages, Microsoft Graph returns an @odata.nextLink property in the response that contains a URL to the next page of results.
-
-This snippet retrieves the messages in the signed-in user's mailbox. Ensure you have the [correct permissions](https://docs.microsoft.com/en-us/graph/api/user-list-messages?view=graph-rest-1.0&tabs=http#permissions) set.
-The Graph API response is deserialized into a collection of `Message` - a model class provided by the SDK.
-
-```php
-use Microsoft\Graph\Generated\Users\Item\Messages\MessagesRequestBuilderGetQueryParameters;
-use Microsoft\Graph\Generated\Users\Item\Messages\MessagesRequestBuilderGetRequestConfiguration;
-
-$requestConfig = new MessagesRequestBuilderGetRequestConfiguration();
-$requestConfig->queryParameters = MessagesRequestBuilderGetRequestConfiguration::createQueryParameters();
-$requestConfig->queryParameters->select = ['subject'];
-$requestConfig->queryParameters->top = 2;
-$requestConfig->headers = ['Prefer' => 'outlook.body-content-type=text'];
-
-// or with PHP 8
-$requestConfig = new MessagesRequestBuilderGetRequestConfiguration(
- queryParameters: MessagesRequestBuilderGetRequestConfiguration::createQueryParameters(
- select: ['subject'],
- top: 2
- ),
- headers: ['Prefer' => 'outlook.body-content-type=text']
-);
-
-$messages = $graphServiceClient->users()->byUserId(USER_ID)->messages()->get($requestConfig)->wait();
-
-foreach ($messages->getValue() as $message) {
- echo "Subject: {$message->getSubject()}\n";
-}
-```
-
-## Paging through a collection
-
-Using our `PageIterator` you can page through a collection applying a callback to be executed against each item in the collection.
-The Page Iterator automatically requests the next page until the last.
-
-It is initialised with an initial response to a collection request and the request adapter to be used for subsequent page requests.
-
-We call `iterate()` while passing a callback to be executed. If the callback returns `false` iteration pauses at the current item.
-
-Iteration can be resumed by calling `iterate()` again.
-
-```php
-use Microsoft\Graph\Core\Tasks\PageIterator;
-use Microsoft\Graph\Generated\Models\Message;
-use DateTimeInterface;
-
-$messages = $graphServiceClient->users()->byUserId(USER_ID)->messages()->get()->wait();
-
-$pageIterator = new PageIterator($messages, $graphServiceClient->getRequestAdapter());
-
-$counter = 0;
-$callback = function (Message $message) use (&$counter) {
- echo "Subject: {$message->getSubject()}, Received at: {$message->getReceivedDateTime()->format(DateTimeInterface::RFC2822)}\n";
- $counter ++;
- return ($counter % 5 != 0);
-};
-
-while ($pageIterator->hasNext()) {
- // iteration pauses and resumes after every 5 messages
- $pageIterator->iterate($callback);
-
- echo "\nPaused iteration...Total messages: {$counter}\n\n";
-}
-
-```
-
-
-## Use a Custom Response Handler / Get the raw HTTP response
-Define a response handler that implements the [Response Handler interface](https://github.com/microsoft/kiota-abstractions-php/blob/main/src/ResponseHandler.php) and pass it into the request using the request options.
-
-The SDK provides a default asynchronous response handler which returns a promise that resolves to a raw HTTP response.
-
-To get the raw response:
-```php
-
-// PHP 7
-$nativeResponseHandler = new NativeResponseHandler();
-$config = new MeRequestBuilderGetRequestConfiguration();
-$config->options = [new ResponseHandlerOption($nativeResponseHandler)];
-$result = $graphServiceClient->me()->get($config)->wait();
-$rawResponse = $result->getResponse();
-
-
-// PHP 8
-$nativeResponseHandler = new NativeResponseHandler();
-$result = $graphServiceClient->me()->get(new MeRequestBuilderGetRequestConfiguration(
- options: [new ResponseHandlerOption($nativeResponseHandler)]
-))->wait();
-$rawResponse = $result->getResponse();
-```
-
-## Send an email
-This sample sends an email. The request body is constructed using the provided models.
-Ensure you have the [right permissions](https://docs.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http#permissions).
-
-```php
-
-use Microsoft\Graph\Generated\Users\Item\SendMail\SendMailPostRequestBody;
-use Microsoft\Graph\Generated\Models\BodyType;
-use Microsoft\Graph\Generated\Models\EmailAddress;
-use Microsoft\Graph\Generated\Models\ItemBody;
-use Microsoft\Graph\Generated\Models\Message;
-use Microsoft\Graph\Generated\Models\Recipient;
-use Microsoft\Graph\GraphServiceClient;
-use Microsoft\Kiota\Abstractions\ApiException;
-use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
-
-
-$tokenRequestContext = new AuthorizationCodeContext(
- 'tenantId',
- 'clientId',
- 'clientSecret',
- 'authCode',
- 'redirectUri'
-);
-$scopes = ['Mail.Send'];
-$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
-
-try {
- $sender = new EmailAddress();
- $sender->setAddress('john.doe@outlook.com');
- $sender->setName('John Doe');
- $fromRecipient = new Recipient();
- $fromRecipient->setEmailAddress($sender);
-
- $recipients = [];
-
- $recipientEmail = new EmailAddress();
- $recipientEmail->setAddress('jane.doe@outlook.com');
- $recipientEmail->setName('Jane Doe');
- $toRecipient = new Recipient();
- $toRecipient->setEmailAddress($recipientEmail);
- $recipients[] = $toRecipient;
-
- $emailBody = new ItemBody();
- $emailBody->setContent('Dummy content');
- $emailBody->setContentType(new BodyType(BodyType::TEXT));
-
- $message = new Message();
- $message->setSubject('Test Email');
- $message->setFrom($fromRecipient);
- $message->setToRecipients($recipients);
- $message->setBody($emailBody);
-
- $requestBody = new SendMailPostRequestBody();
- $requestBody->setMessage($message);
-
- $response = $graphServiceClient->me()->sendMail()->post($requestBody)->wait();
-
-} catch (ApiException $ex) {
- echo $ex->getError()->getMessage();
-}
-
-```
-
-## Download an item
-
-```php
-
-use Microsoft\Graph\GraphServiceClient;
-use Microsoft\Kiota\Abstractions\ApiException;
-use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
-
-$tokenRequestContext = new AuthorizationCodeContext(
- 'tenantId',
- 'clientId',
- 'clientSecret',
- 'authCode',
- 'redirectUri'
-);
-$scopes = ['Files.ReadWrite'];
-$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
-
-try {
- $fileContents = $graphServiceclient->drives()->byDriveId('driveId')->items()->byDriveItemId('itemId')->content()->get()->wait();
-
-} catch (ApiException $ex) {
- echo $ex->getError()->getMessage();
-}
-
-```
-
-
-## Upload an item
-
-For files less than 3MB, you can send a byte stream to the API with the sample below. See the next section for files larger than 3MB.
-
-```php
-
-$driveItemId = 'root:/upload.txt:';
-
-$inputStream = Utils::streamFor(fopen('upload.txt', 'r'));
-$uploadItem = $graphServiceClient->drives()->byDriveId('[driveId]')->items()->byDriveItemId($driveItemId)->content()->put($inputStream)->wait();
-
-```
-
-
-## Uploading large files
-
-To upload files larger than 3MB, the Microsoft Graph API supports uploads using resumable upload sessions where a number of bytes are uploaded at a time.
-
-The SDK provides a `LargeFileUpload` task that slices your file into bytes and progressively uploads them until completion.
-
-To add a large attachment to an Outlook message:
-
-```php
-use Psr\Http\Client\NetworkExceptionInterface;
-
-
-// create a file stream
-$file = Utils::streamFor(fopen('fileName', 'r'));
-
-// create an upload session
-$attachmentItem = new AttachmentItem();
-$attachmentItem->setAttachmentType(new AttachmentType('file'));
-$attachmentItem->setName('fileName');
-$attachmentItem->setSize($file->getSize());
-
-$uploadSessionRequestBody = new CreateUploadSessionPostRequestBody();
-$uploadSessionRequestBody->setAttachmentItem($attachmentItem);
-
-$uploadSession = $graphServiceClient->users()->byUserId(USER_ID)->messages()->byMessageId('[id]')->attachments()->createUploadSession()->post($uploadSessionRequestBody)->wait();
-
-// upload
-$largeFileUpload = new LargeFileUploadTask($uploadSession, $graphServiceClient->getRequestAdapter(), $file);
-try {
- $uploadSession = $largeFileUpload->upload()->wait();
-} catch (NetworkExceptionInterface $ex) {
- // resume upload in case of network errors
- $retries = 0;
- $maxRetries = 3;
- while ($retries < $maxRetries) {
- try {
- $uploadSession = $largeFileUpload->resume()->wait();
- if ($uploadSession) {
- break;
- }
- } catch (NetworkExceptionInterface $ex) {
- $retries ++;
- }
- }
- throw $ex;
-}
-
-```
-
-You can also cancel a large file upload session:
-
-```php
-$largeFileUpload->cancel()->wait();
-```
-
-*Known Issue*
-At the moment, when attaching large files to Outlook Messages and Events, we don't expose the `Location` header value. For now, you'd need to fetch the message's attachments/events.
-
-## Passing request headers
-Each execution method i.e. get(), post(), put(), patch(), delete() accepts a Request Configuration object where the request headers can be set:
-
-```php
-
-use Microsoft\Graph\Generated\Me\Messages\MessagesRequestBuilderGetRequestConfiguration;
-
-$requestConfig = new MessagesRequestBuilderGetRequestConfiguration();
-$requestConfig->headers = ['Prefer' => 'outlook.body-content-type=text'];
-
-$messages = $graphServiceclient->me()->messages()->get($requestConfig)->wait();
-
-// PHP 8
-$messages = $graphServiceClient->me()->messages()->get(new MessagesRequestBuilderGetRequestConfiguration(
- headers: ['Prefer' => 'outlook.body-content-type=text']
-))->wait();
-
-```
-
-## Passing query parameters
-
-```php
-
-use Microsoft\Graph\Generated\Me\Messages\MessagesRequestBuilderGetRequestConfiguration;
-
-$requestConfig = new MessagesRequestBuilderGetRequestConfiguration();
-$requestConfig->queryParameters = MessagesRequestBuilderGetRequestConfiguration::createQueryParameters();
-$requestConfig->queryParameters->select = ['subject', 'from'];
-$requestConfig->queryParameters->skip = 2;
-$requestConfig->queryParameters->top = 3;
-
-$messages = $graphServiceClient->me()->messages()->get($requestConfig)->wait();
-
-// PHP 8
-$messages = $graphServiceClient->me()->messages()->get(new MessagesRequestBuilderGetRequestConfiguration(
- queryParameters: MessagesRequestBuilderGetRequestConfiguration::createQueryParameters(
- select: ['subject', 'from'],
- skip: 2,
- top: 3
- )
-))->wait();
-
-
-```
-
-## Customizing middleware configuration
-
-```php
-
-use Microsoft\Graph\Generated\Users\Item\Messages\MessagesRequestBuilderGetRequestConfiguration;
-use Microsoft\Kiota\Http\Middleware\Options\RetryOption;
-
-$requestConfig = new MessagesRequestBuilderGetRequestConfiguration();
-$requestConfig->options = [new RetryOption(2, 5)];
-
-$messages = $graphServiceClient->me()->messages()->get($requestConfig)->wait();
-
-```
-
-## Batching requests
-
-Up to 20 individual requests can be batched together to reduce network latency of making each request separately.
-
-The `BatchRequestBuilder` allows you to make requests to the `/$batch` endpoint of the Microsoft Graph API.
-
-### 1. Create a `BatchRequestContent` object
-
-The `BatchRequestContent` object consists of a list of requests to be batched together.
-
-Here we batch 3 requests.
-```php
-use Microsoft\Graph\Core\Requests\BatchRequestContent;
-use Microsoft\Graph\Generated\Models\Message;
-
-$message = new Message();
-$message->setSubject("Test Subject");
-
-$batchRequestContent = new BatchRequestContent([
- $graphServiceClient->users()->byUserId(USER_ID)->messages()->byMessageId('id')->toDeleteRequestInformation(),
- $graphServiceClient->users()->byUserId(USER_ID)->messages()->toPostRequestInformation($message),
- $graphServiceClient->users()->byUserId(USER_ID)->toGetRequestInformation()
-]);
-
-```
-
-You can also add requests to the `BatchRequestContent` via `addPsrRequest()`, `addRequest()` and `addRequestInformation()`
-
-### 2. Send the batch request using the `BatchRequestBuilder`
-
-```php
-use Microsoft\Graph\BatchRequestBuilder;
-use Microsoft\Graph\Core\Requests\BatchResponseItem;
-
-$requestBuilder = new BatchRequestBuilder($graphServiceClient->getRequestAdapter());
-$batchResponse = $requestBuilder->postAsync($batchRequestContent)->wait();
-
-```
-
-### 3. Get the responses to the batch request items
-
-The responses are by default returned in a `BatchResponseContent` object comprised of various `BatchResponseItem` objects corresponding to the requests made in step 1
-
-An `id` is automatically assigned to each request in the `BatchRequestContent` object.
-
-The assigned `id` can be fetched by calling `getRequests()` on the `BatchRequestContent` object.
-
-The SDK supports getting the response status code, body and headers.
-
-```php
-$batchRequests = $batchRequestContent->getRequests();
-// Uses the auto-generated ID added to the batch request content
-$response1 = $batchResponse->getResponse($batchRequests[0]->getId());
-echo "Response1 status code: {$response1->getStatusCode()}";
-
-```
-
-By default, the body is a `StreamInterface` object.
-However, you can deserialize a `BatchResponseItem` to a `Parsable` (model) implementation
-
-```php
-use Microsoft\Graph\Generated\Models\Message;
-
-$message = $batchResponse->getResponseBody($batchRequests[1]->getId(), Message::class);
-echo "Created message subject: {$message->getSubject()}\n";
-```
-
-If you would like fine-grained control over each request in the batch, you can initialise `BatchRequestItem` objects and set dependencies betweeen requests etc.
-
-For example, here we want to update a message but also want the API to return the previous message object before the update. We would need to set a dependency
-between the requests so that the update only happens after the initial message has been fetched.
-
-```php
-use Microsoft\Graph\Core\Requests\BatchRequestContent;
-use Microsoft\Graph\Core\Requests\BatchRequestItem;
-use Microsoft\Graph\Generated\Models\Message;
-
-$message = new Message();
-$message->setSubject("Test Subject");
-
-$request1 = new BatchRequestItem($graphServiceClient->users()->byUserId(USER_ID)->messages()->byMessageId('[id]')->toGetRequestInformation());
-$request2 = new BatchRequestItem($graphServiceClient->users()->byUserId(USER_ID)->messages()->byMessageId('[id]')->toPatchRequestInformation($message));
-$request2->dependsOn([$request1]);
-
-$batchRequestContent = new BatchRequestContent([
- $request1, $request2
-]);
-
-```
-
-## Continuous Access Evaluation (CAE)
-
-See https://learn.microsoft.com/en-us/azure/active-directory/conditional-access/concept-continuous-access-evaluation
-
-CAE is disabled by default. The SDK attempts to refresh the access token only ONCE when a claims challenge is returned by the Microsoft Graph API.
-Should the SDK be unable to refresh the token, it calls a custom method provided by you which should ensure the user logs in again and provides an
-updated `TokenRequestContext`. The SDK uses this new `TokenRequestContext` to fetch a new access token. If the same request fails again with the new
-access token, the SDK returns the deserialized 401 response body:
-
-```php
-
-$tokenRequestContext = new AuthorizationCodeContext(
- 'tenantId',
- 'clientId',
- 'clientSecret',
- 'authCode',
- 'redirectUri'
-);
-$graphServiceClient = new GraphServiceClient($tokenRequestContext);
-
-$tokenRequestContext->setCAEEnabled(true);
-$tokenRequestContext->setCAERedirectCallback(function (string $claims) {
- // your app makes the user log in again asynchronously
- return yourCustomLoginAsync()->then(
- function (string $authCode) {
- $newTokenRequestContext = new AuthorizationCodeContext(
- 'tenantId',
- 'clientId',
- 'clientSecret',
- $authCode,
- 'redirectUri'
- );
- return $newTokenRequestContext;
- }
- );
-});
-
-try {
- $numUsers = $graphServiceClient->users()->count()->get()->wait();
-} catch (ContinuousAccessEvaluationException $ex) {
- echo $ex->getError()->getMessage();
-}
-```
diff --git a/docs/application_samples.md b/docs/application_samples.md
new file mode 100644
index 00000000000..b8a3dba8437
--- /dev/null
+++ b/docs/application_samples.md
@@ -0,0 +1,21 @@
+## List all applications in a tenant
+
+```php
+
+
+
+// Create a new GraphServiceClient instance
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+try {
+ $applications = $graphServiceClient->applications()->get()->wait();
+ if ($applications && $applications->getValue()) {
+ foreach ($applications->getValue() as $app) {
+ echo "Application ID: {$app->getId()}
";
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
\ No newline at end of file
diff --git a/docs/authentication_samples.md b/docs/authentication_samples.md
new file mode 100644
index 00000000000..fbbecdc9df0
--- /dev/null
+++ b/docs/authentication_samples.md
@@ -0,0 +1,298 @@
+# Usage Examples
+
+## Creating a Graph client
+This creates a default Graph client that uses `https://graph.microsoft.com` as the default base URL and default configured Guzzle HTTP client to make the requests.
+
+To make requests with a signed-in user, you can initialise an `AuthorizationCodeContext` with the code returned by Microsoft Identity after redirecting the
+user to the sign-in page. The same redirect URI provided while requesting the auth code is required:
+
+```php
+
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
+
+$tokenRequestContext = new AuthorizationCodeContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ 'authCode',
+ 'redirectUri'
+);
+$scopes = ['User.Read', 'Mail.ReadWrite'];
+$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
+
+```
+
+To make requests on behalf of an already signed in user, where your front-end application has already acquired an access token for the user, you can use the `OnBehalfOfContext` which uses the [On-Behalf-Of flow](https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow) to fetch
+an access token for your backend application to access the Microsoft Graph API. To do this, you pass the already acquired access token as the "assertion";
+
+```php
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Kiota\Authentication\Oauth\OnBehalfOfContext;
+
+$tokenRequestContext = new OnBehalfOfContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ 'assertion'
+);
+
+$scopes = ['User.Read', 'Mail.ReadWrite'];
+$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
+
+```
+
+
+To make requests without a signed-in user (using application permissions), you can initialise a `ClientCredentialsContext` object:
+
+```php
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext;
+
+// Uses https://graph.microsoft.com/.default scopes if none are specified
+$tokenRequestContext = new ClientCredentialContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret'
+);
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+```
+
+Using a custom National Cloud deployment:
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes, NationalCloud::CHINA);
+```
+
+Customizing the default Guzzle client:
+```php
+
+use Microsoft\Graph\Core\GraphClientFactory;
+use Microsoft\Graph\GraphRequestAdapter;
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
+
+$tokenRequestContext = new ClientCredentialContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret'
+);
+$authProvider = new GraphPhpLeagueAuthenticationProvider($tokenRequestContext);
+$guzzleConfig = [
+ // your custom config
+];
+$httpClient = GraphClientFactory::createWithConfig($guzzleConfig);
+$requestAdapter = new GraphRequestAdapter($authProvider, $httpClient);
+$graphServiceClient = GraphServiceClient::createWithRequestAdapter($requestAdapter);
+
+```
+
+## Access token management
+
+Using the `TokenRequestContext`, an instance of the `GraphServiceClient` requests access tokens and refresh tokens.
+The tokens are stored by default in an in-memory cache so that future requests using the same instance of the `GraphServiceClient` can re-use the previously acquired tokens.
+
+The default in-memory cache is a map/dictionary with a unique key identifying a user/application with a tenant and a PHPLeague [`AccessToken`](https://github.com/thephpleague/oauth2-client/blob/master/src/Token/AccessToken.php) object as its value. The unique key ensures the right token for a user is retrieved from the cache. For `TokenRequestContexts` that do not require a signed-in user (application permissions), the cache key will be **`{tenantId}-{clientId}`** and for those that require a signed-in user (delegated permissions), the cache key will be
+**`{tenantId}-{clientId}-{userId}`**. The `AccessToken` object carries both the `access_token`, its expiry and a `refresh_token` if available.
+The in-memory cache lives as a PHP object within your application's PHP process and is destroyed when the process terminates.
+
+For scenarios where an application requires a signed-in user, retaining the same
+instance of the `GraphServiceClient` across multiple requests to your application for the same user's session is not feasible. This section outlines
+how your application can retrieve access tokens from the SDK and pass already acquired access tokens to the SDK for future requests without the user signing in for each request.
+
+### Retrieving the access token from the SDK
+
+The SDK provides a mechanism to expose the access token and refresh token that it acquires to your application for use in future requests. This would prevent the SDK from making a new
+token request with each `GraphServiceClient` your application instantiates. It also allows your application to prevent its users from signing in with each request within a session.
+
+By default, a `GraphServiceClient` instance caches access tokens in a built-in [`InMemoryAccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/InMemoryAccessTokenCache.php). The cache will be populated with a PHPLeague [`AccessToken`](https://github.com/thephpleague/oauth2-client/blob/master/src/Token/AccessToken.php) object which carries both the `access_token`, its expiry and a `refresh_token` if available. When the `GraphServiceClient` instance is re-used for a request with the same user/application, the in-memory cache is checked for a valid token otherwise a new token request is made.
+
+However, to get the cached token that the SDK requests for a user/application you
+can initialise an `InMemoryAccessTokenCache` or pass a custom implementation of the [`AccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/AccessTokenCache.php) interface and pass it as a parameter when initialising the `GraphServiceClient`. The two approaches are outlined below:
+
+### Using an InMemoryAccessTokenCache instance
+
+```php
+use Microsoft\Kiota\Authentication\Cache\InMemoryAccessTokenCache;
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAccessTokenProvider;
+use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
+use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
+
+$tokenRequestContext = new AuthorizationCodeContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ 'authCode',
+ 'redirectUri'
+);
+$scopes = ['User.Read', 'Mail.ReadWrite'];
+
+$inMemoryCache = new InMemoryAccessTokenCache();
+
+$graphServiceClient = GraphServiceClient::createWithAuthenticationProvider(
+ GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
+ GraphPhpLeagueAccessTokenProvider::createWithCache(
+ $inMemoryCache,
+ $tokenRequestContext,
+ $scopes
+ )
+ )
+);
+
+$accessToken = $inMemoryCache->getTokenWithContext($tokenRequestContext);
+
+```
+
+### Using a custom AccessTokenCache implementation
+
+A custom [`AccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/AccessTokenCache.php) interface implementation can also be provided. After the request, the SDK persists the token in the
+custom cache via the `persistAccessToken()` method.
+
+By default, the SDK adds a unique cache key/identifier to a `TokenRequestContext` that uniquely identifies the tenant, client and user (if applicable).
+For `TokenRequestContexts` that do not require a signed-in user (application permissions), the cache key will be
+**`{tenantId}-{clientId}`** and for those that require a signed-in user (delegated permissions), the cache key will be
+**`{tenantId}-{clientId}-{userId}`**.
+
+Alternatively, you can override the default cache key
+
+To retrieve the access token persisted to your custom cache for a particular user's/application's `TokenRequestContext`:
+```php
+
+$accessToken = $customCache->getAccessToken($tokenRequestContext->getCacheKey());
+
+```
+
+### Initializing a GraphServiceClient with an access token
+
+For applications that already have built-in mechanisms to fetch and refresh access tokens, the SDK supports passing these tokens to a `GraphServiceClient` by initializing
+a client using an [`AccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/AccessTokenCache.php) interface implementation.
+
+The SDK provides a built-in implementation of this interface via an [`InMemoryAccessTokenCache`](https://github.com/microsoft/kiota-authentication-phpleague-php/blob/main/src/Cache/InMemoryAccessTokenCache.php).
+
+This is also useful when re-using a previously retrieved access token for a signed-in user during a previous request.
+
+The SDK will check the cache for a valid token before considering requesting a new token. If the provided token is expired
+and a refresh token is present, the access token will be refreshed and persisted to the cache. If no refresh token is provided, the SDK requests attempts to retrieve a new access token and persists it to the cache. In cases where a signed-in user is present, e.g. authorization_code OAuth flows, the new token request will most likely fail because no valid `authorization_code` will be present meaning the user has to sign in again.
+
+### Using the `InMemoryAccessTokenCache`
+
+The in-memory cache can be hydrated/initialised using the `TokenRequestContext` and a PHPLeague [`AccessToken`](https://github.com/thephpleague/oauth2-client/blob/master/src/Token/AccessToken.php) object for a user/application:
+
+```php
+
+use Microsoft\Kiota\Authentication\Cache\InMemoryAccessTokenCache;
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAccessTokenProvider;
+use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
+use League\OAuth2\Client\Token\AccessToken;
+
+$tokenRequestContext = new AuthorizationCodeContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ 'authCode', // use a placeholder value since user is not signed in again
+ 'redirectUri'
+);
+
+$cache = new InMemoryAccessTokenCache(
+ $tokenRequestContext,
+ new AccessToken(
+ [
+ 'access_token' => $accessToken,
+ 'refresh_token' => $refreshToken,
+ 'expires' => 1
+ ]
+ )
+);
+
+$graphServiceClient = GraphServiceClient::createWithAuthenticationProvider(
+ GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
+ GraphPhpLeagueAccessTokenProvider::createWithCache(
+ $cache,
+ $tokenRequestContext,
+ $scopes
+ )
+ )
+);
+
+```
+
+For scenarios where your application may need to make requests for multiple users using the same `GraphServiceClient`, the `InMemoryAccessTokenCache` can
+be initialized with multiple TokenRequestContext-AccessToken pairs using `withToken`:
+```php
+
+use Microsoft\Kiota\Authentication\Cache\InMemoryAccessTokenCache;
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAccessTokenProvider;
+use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;
+use League\OAuth2\Client\Token\AccessToken;
+
+$tokenRequestContext = new AuthorizationCodeContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ 'authCode', // use a placeholder value since user is not signed in again
+ 'redirectUri'
+);
+
+$cache = (new InMemoryAccessTokenCache($tokenRequestContext, new AccessToken([
+ // ...
+])));
+
+$cache->withToken($tokenRequestContext2, new AccessToken([
+ // ...
+ ]))->withToken($tokenRequestContext, new AccessToken([
+ // ...
+ ]))->withToken($tokenRequestContext3, new AccessToken());
+
+
+$graphServiceClient = GraphServiceClient::createWithAuthenticationProvider(
+ GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
+ GraphPhpLeagueAccessTokenProvider::createWithCache(
+ $cache,
+ $tokenRequestContext,
+ $scopes
+ )
+ )
+);
+
+```
+
+### Using a custom `AccessTokenCache` implementation`
+
+The SDK retrieves cached tokens using a cache key/identifier on the `TokenRequestContext`. The cache key
+on the `TokenRequestContext` is set using `setCacheKey()` which accepts an [`AccessToken`](https://github.com/thephpleague/oauth2-client/blob/master/src/Token/AccessToken.php) object.
+
+The `TokenRequestContext` uses the `AccessToken` to generate a unique identifier per user, client and tenant. For `TokenRequestContexts` that do not require a signed-in user (application permissions), the cache key will be
+**`{tenantId}-{clientId}`** and for those that require a signed-in user (delegated permissions), the cache key will be
+**`{tenantId}-{clientId}-{userId}`**.
+
+For this scenario, the custom AccessTokenCache will need to be initialized in a way that the cache key set on the
+`TokenRequestContext` aligns with the key the custom AccessTokenCache maps to the user/application's access token
+
+```php
+
+$accessToken = new AccessToken([
+ 'access_token' => $accessToken,
+ 'refresh_token' => $refreshToken,
+ 'expires' => ...
+]);
+
+$tokenRequestContext->setCacheKey($accessToken);
+
+// init custom cache with tokens mapped to specific user/app using $tokenRequestContext->getCacheKey()
+$customCache = new CustomCache($tokenRequestContext->getCacheKey(), $accessToken);
+
+// init graph client
+$graphServiceClient = GraphServiceClient::createWithAuthenticationProvider(
+ GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
+ GraphPhpLeagueAccessTokenProvider::createWithCache(
+ $customCache,
+ $tokenRequestContext,
+ $scopes
+ )
+ )
+);
+
+```
diff --git a/docs/drives_samples.md b/docs/drives_samples.md
new file mode 100644
index 00000000000..1370b6d0dce
--- /dev/null
+++ b/docs/drives_samples.md
@@ -0,0 +1,137 @@
+
+## 1. LIST ALL DRIVES (GET /drives)
+
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+try {
+ $drives = $graphServiceClient->drives()->get()->wait();
+ if ($drives && $drives->getValue()) {
+ foreach ($drives->getValue() as $drive) {
+ echo "Drive ID: {$drive->getId()}
";
+ echo "Drive Type: {$drive->getDriveType()}
";
+ echo "Drive Name: {$drive->getName()}
";
+ echo "Drive Description: {$drive->getDescription()}
";
+ echo "Drive Web URL: {$drive->getWebUrl()}
";
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 2. GET DRIVE BY ID (GET /drives/{id})
+
+```php
+$driveId = "DRIVE-ID";
+
+try {
+ $drive = $graphServiceClient->drives()->byDriveId($driveId)->get()->wait();
+ if ($drive) {
+ echo "Drive ID: {$drive->getId()}
";
+ echo "Drive Type: {$drive->getDriveType()}
";
+ echo "Drive Name: {$drive->getName()}
";
+ echo "Drive Description: {$drive->getDescription()}
";
+ echo "Drive Web URL: {$drive->getWebUrl()}
";
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 3. LIST ALL THE ITEMS IN A DRIVE (GET /drives/{id}/items)
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$driveId = "DRIVE-ID";
+
+try {
+ $requestConfig = new ItemsRequestBuilderGetRequestConfiguration();
+ $requestConfig->queryParameters = ItemsRequestBuilderGetRequestConfiguration::createQueryParameters();
+ $requestConfig->queryParameters->filter = "startswith(name, 'B')";
+
+ $items = $graphServiceClient->drives()->byDriveId($driveId)->items()->get($requestConfig)->wait();
+ if ($items && $items->getValue()) {
+ foreach ($items->getValue() as $item) {
+ echo "Item ID: {$item->getId()}
";
+ echo "Item Name: {$item->getName()}
";
+ echo "Item Size: {$item->getSize()}
";
+ echo "Item Folder: " . json_encode($item->getFolder()) . "
";
+ echo "Item File: " . json_encode($item->getFile()) . "
";
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 4. GET AN ITEM IN THE DRIVE (GET /drives/{id}/items/{id})
+
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$driveId = "DRIVE-ID";
+
+try {
+ $items = $graphServiceClient->drives()->byDriveId($driveId)->items()->get()->wait();
+ if ($items && $items->getValue()) {
+ foreach ($items->getValue() as $item) {
+ echo "Item ID: {$item->getId()}
";
+ echo "Item Name: {$item->getName()}
";
+ echo "Item Size: {$item->getSize()}
";
+ echo "Item Folder: " . json_encode($item->getFolder()) . "
";
+ echo "Item File: " . json_encode($item->getFile()) . "
";
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 5. GET THE ROOT FOLDER OF THE DRIVE (GET /drives/{id}/root)
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$driveId = "DRIVE-ID"; // Replace with the actual drive ID
+
+try {
+ $root = $graphServiceClient->drives()->byDriveId($driveId)->root()->get()->wait();
+ if ($root) {
+ echo "Root ID: {$root->getId()}
";
+ echo "Root Name: {$root->getName()}
";
+ echo "Folder Child Count: " . ($root->getFolder() ? $root->getFolder()->getChildCount() : 'N/A') . "
";
+ echo "Root: " . json_encode($root->getRoot()) . "
";
+ echo "Root Size: {$root->getSize()}
";
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 6. GET ITEMS IN THE ROOT FOLDER OF THE DRIVE (GET drives/{id}/items/root/children)
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$driveId = "DRIVE-ID";
+
+try {
+ $items = $graphServiceClient->drives()->byDriveId($driveId)->items()->byDriveItemId('root')->children()->get()->wait();
+ if ($items && $items->getValue()) {
+ foreach ($items->getValue() as $item) {
+ echo "Item ID: {$item->getId()}
";
+ echo "Item Name: {$item->getName()}
";
+ echo "Item Size: {$item->getSize()}
";
+ echo "Item Folder: " . json_encode($item->getFolder()) . "
";
+ echo "Item File: " . json_encode($item->getFile()) . "
";
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
\ No newline at end of file
diff --git a/docs/general_samples.md b/docs/general_samples.md
new file mode 100644
index 00000000000..f02d24e047f
--- /dev/null
+++ b/docs/general_samples.md
@@ -0,0 +1,416 @@
+ Usage Examples
+
+## Creating a Graph client
+This creates a default Graph client that uses `https://graph.microsoft.com` as the default base URL and default configured Guzzle HTTP client to make the requests.
+
+To make requests with a signed-in user, you can initialise an `AuthorizationCodeContext` with the code returned by Microsoft Identity after redirecting the
+user to the sign-in page. The same redirect URI provided while requesting the auth code is required:
+
+```php
+
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
+
+$tokenRequestContext = new AuthorizationCodeContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ 'authCode',
+ 'redirectUri'
+);
+$scopes = ['User.Read', 'Mail.ReadWrite'];
+$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
+
+```
+
+## Get an item from the Graph
+This sample fetches the current signed-in user. Note that to use `\me` you need
+a delegated permission. Alternatively, using application permissions, you can request `/users/[userPrincipalName]`.
+See [Microsoft Graph Permissions](https://docs.microsoft.com/en-us/graph/auth/auth-concepts#microsoft-graph-permissions) for more.
+
+
+```php
+$user = $graphServiceClient->me()->get()->wait();
+
+// Or
+
+$user = $graphServiceClient->users()->byUserId('userPrincipalName')->get()->wait();
+```
+
+## Get a collection of items
+Some queries against Microsoft Graph return multiple pages of data either due to server-side paging or due to the use of the $top query parameter to specifically limit the page size in a request. When a result set spans multiple pages, Microsoft Graph returns an @odata.nextLink property in the response that contains a URL to the next page of results.
+
+This snippet retrieves the messages in the signed-in user's mailbox. Ensure you have the [correct permissions](https://docs.microsoft.com/en-us/graph/api/user-list-messages?view=graph-rest-1.0&tabs=http#permissions) set.
+The Graph API response is deserialized into a collection of `Message` - a model class provided by the SDK.
+
+```php
+use Microsoft\Graph\Generated\Users\Item\Messages\MessagesRequestBuilderGetQueryParameters;
+use Microsoft\Graph\Generated\Users\Item\Messages\MessagesRequestBuilderGetRequestConfiguration;
+
+$requestConfig = new MessagesRequestBuilderGetRequestConfiguration();
+$requestConfig->queryParameters = MessagesRequestBuilderGetRequestConfiguration::createQueryParameters();
+$requestConfig->queryParameters->select = ['subject'];
+$requestConfig->queryParameters->top = 2;
+$requestConfig->headers = ['Prefer' => 'outlook.body-content-type=text'];
+
+// or with PHP 8
+$requestConfig = new MessagesRequestBuilderGetRequestConfiguration(
+ queryParameters: MessagesRequestBuilderGetRequestConfiguration::createQueryParameters(
+ select: ['subject'],
+ top: 2
+ ),
+ headers: ['Prefer' => 'outlook.body-content-type=text']
+);
+
+$messages = $graphServiceClient->users()->byUserId(USER_ID)->messages()->get($requestConfig)->wait();
+
+foreach ($messages->getValue() as $message) {
+ echo "Subject: {$message->getSubject()}\n";
+}
+```
+
+## Paging through a collection
+
+Using our `PageIterator` you can page through a collection applying a callback to be executed against each item in the collection.
+The Page Iterator automatically requests the next page until the last.
+
+It is initialised with an initial response to a collection request and the request adapter to be used for subsequent page requests.
+
+We call `iterate()` while passing a callback to be executed. If the callback returns `false` iteration pauses at the current item.
+
+Iteration can be resumed by calling `iterate()` again.
+
+```php
+use Microsoft\Graph\Core\Tasks\PageIterator;
+use Microsoft\Graph\Generated\Models\Message;
+use DateTimeInterface;
+
+$messages = $graphServiceClient->users()->byUserId(USER_ID)->messages()->get()->wait();
+
+$pageIterator = new PageIterator($messages, $graphServiceClient->getRequestAdapter());
+
+$counter = 0;
+$callback = function (Message $message) use (&$counter) {
+ echo "Subject: {$message->getSubject()}, Received at: {$message->getReceivedDateTime()->format(DateTimeInterface::RFC2822)}\n";
+ $counter ++;
+ return ($counter % 5 != 0);
+};
+
+while ($pageIterator->hasNext()) {
+ // iteration pauses and resumes after every 5 messages
+ $pageIterator->iterate($callback);
+
+ echo "\nPaused iteration...Total messages: {$counter}\n\n";
+}
+
+```
+
+
+## Use a Custom Response Handler / Get the raw HTTP response
+Define a response handler that implements the [Response Handler interface](https://github.com/microsoft/kiota-abstractions-php/blob/main/src/ResponseHandler.php) and pass it into the request using the request options.
+
+The SDK provides a default asynchronous response handler which returns a promise that resolves to a raw HTTP response.
+
+To get the raw response:
+```php
+
+// PHP 7
+$nativeResponseHandler = new NativeResponseHandler();
+$config = new MeRequestBuilderGetRequestConfiguration();
+$config->options = [new ResponseHandlerOption($nativeResponseHandler)];
+$result = $graphServiceClient->me()->get($config)->wait();
+$rawResponse = $result->getResponse();
+
+
+// PHP 8
+$nativeResponseHandler = new NativeResponseHandler();
+$result = $graphServiceClient->me()->get(new MeRequestBuilderGetRequestConfiguration(
+ options: [new ResponseHandlerOption($nativeResponseHandler)]
+))->wait();
+$rawResponse = $result->getResponse();
+```
+
+## Send an email
+This sample sends an email. The request body is constructed using the provided models.
+Ensure you have the [right permissions](https://docs.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http#permissions).
+
+```php
+
+use Microsoft\Graph\Generated\Users\Item\SendMail\SendMailPostRequestBody;
+use Microsoft\Graph\Generated\Models\BodyType;
+use Microsoft\Graph\Generated\Models\EmailAddress;
+use Microsoft\Graph\Generated\Models\ItemBody;
+use Microsoft\Graph\Generated\Models\Message;
+use Microsoft\Graph\Generated\Models\Recipient;
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Kiota\Abstractions\ApiException;
+use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
+
+
+$tokenRequestContext = new AuthorizationCodeContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ 'authCode',
+ 'redirectUri'
+);
+$scopes = ['Mail.Send'];
+$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
+
+try {
+ $sender = new EmailAddress();
+ $sender->setAddress('john.doe@outlook.com');
+ $sender->setName('John Doe');
+ $fromRecipient = new Recipient();
+ $fromRecipient->setEmailAddress($sender);
+
+ $recipients = [];
+
+ $recipientEmail = new EmailAddress();
+ $recipientEmail->setAddress('jane.doe@outlook.com');
+ $recipientEmail->setName('Jane Doe');
+ $toRecipient = new Recipient();
+ $toRecipient->setEmailAddress($recipientEmail);
+ $recipients[] = $toRecipient;
+
+ $emailBody = new ItemBody();
+ $emailBody->setContent('Dummy content');
+ $emailBody->setContentType(new BodyType(BodyType::TEXT));
+
+ $message = new Message();
+ $message->setSubject('Test Email');
+ $message->setFrom($fromRecipient);
+ $message->setToRecipients($recipients);
+ $message->setBody($emailBody);
+
+ $requestBody = new SendMailPostRequestBody();
+ $requestBody->setMessage($message);
+
+ $response = $graphServiceClient->me()->sendMail()->post($requestBody)->wait();
+
+} catch (ApiException $ex) {
+ echo $ex->getError()->getMessage();
+}
+
+```
+
+## Download an item
+
+```php
+
+use Microsoft\Graph\GraphServiceClient;
+use Microsoft\Kiota\Abstractions\ApiException;
+use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
+
+$tokenRequestContext = new AuthorizationCodeContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ 'authCode',
+ 'redirectUri'
+);
+$scopes = ['Files.ReadWrite'];
+$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
+
+try {
+ $fileContents = $graphServiceclient->drives()->byDriveId('driveId')->items()->byDriveItemId('itemId')->content()->get()->wait();
+
+} catch (ApiException $ex) {
+ echo $ex->getError()->getMessage();
+}
+
+```
+
+
+## Passing request headers
+Each execution method i.e. get(), post(), put(), patch(), delete() accepts a Request Configuration object where the request headers can be set:
+
+```php
+
+use Microsoft\Graph\Generated\Me\Messages\MessagesRequestBuilderGetRequestConfiguration;
+
+$requestConfig = new MessagesRequestBuilderGetRequestConfiguration();
+$requestConfig->headers = ['Prefer' => 'outlook.body-content-type=text'];
+
+$messages = $graphServiceclient->me()->messages()->get($requestConfig)->wait();
+
+// PHP 8
+$messages = $graphServiceClient->me()->messages()->get(new MessagesRequestBuilderGetRequestConfiguration(
+ headers: ['Prefer' => 'outlook.body-content-type=text']
+))->wait();
+
+```
+
+## Passing query parameters
+
+```php
+
+use Microsoft\Graph\Generated\Me\Messages\MessagesRequestBuilderGetRequestConfiguration;
+
+$requestConfig = new MessagesRequestBuilderGetRequestConfiguration();
+$requestConfig->queryParameters = MessagesRequestBuilderGetRequestConfiguration::createQueryParameters();
+$requestConfig->queryParameters->select = ['subject', 'from'];
+$requestConfig->queryParameters->skip = 2;
+$requestConfig->queryParameters->top = 3;
+
+$messages = $graphServiceClient->me()->messages()->get($requestConfig)->wait();
+
+// PHP 8
+$messages = $graphServiceClient->me()->messages()->get(new MessagesRequestBuilderGetRequestConfiguration(
+ queryParameters: MessagesRequestBuilderGetRequestConfiguration::createQueryParameters(
+ select: ['subject', 'from'],
+ skip: 2,
+ top: 3
+ )
+))->wait();
+
+
+```
+
+## Customizing middleware configuration
+
+```php
+
+use Microsoft\Graph\Generated\Users\Item\Messages\MessagesRequestBuilderGetRequestConfiguration;
+use Microsoft\Kiota\Http\Middleware\Options\RetryOption;
+
+$requestConfig = new MessagesRequestBuilderGetRequestConfiguration();
+$requestConfig->options = [new RetryOption(2, 5)];
+
+$messages = $graphServiceClient->me()->messages()->get($requestConfig)->wait();
+
+```
+
+## Batching requests
+
+Up to 20 individual requests can be batched together to reduce network latency of making each request separately.
+
+The `BatchRequestBuilder` allows you to make requests to the `/$batch` endpoint of the Microsoft Graph API.
+
+### 1. Create a `BatchRequestContent` object
+
+The `BatchRequestContent` object consists of a list of requests to be batched together.
+
+Here we batch 3 requests.
+```php
+use Microsoft\Graph\Core\Requests\BatchRequestContent;
+use Microsoft\Graph\Generated\Models\Message;
+
+$message = new Message();
+$message->setSubject("Test Subject");
+
+$batchRequestContent = new BatchRequestContent([
+ $graphServiceClient->users()->byUserId(USER_ID)->messages()->byMessageId('id')->toDeleteRequestInformation(),
+ $graphServiceClient->users()->byUserId(USER_ID)->messages()->toPostRequestInformation($message),
+ $graphServiceClient->users()->byUserId(USER_ID)->toGetRequestInformation()
+]);
+
+```
+
+You can also add requests to the `BatchRequestContent` via `addPsrRequest()`, `addRequest()` and `addRequestInformation()`
+
+### 2. Send the batch request using the `BatchRequestBuilder`
+
+```php
+use Microsoft\Graph\BatchRequestBuilder;
+use Microsoft\Graph\Core\Requests\BatchResponseItem;
+
+$requestBuilder = new BatchRequestBuilder($graphServiceClient->getRequestAdapter());
+$batchResponse = $requestBuilder->postAsync($batchRequestContent)->wait();
+
+```
+
+### 3. Get the responses to the batch request items
+
+The responses are by default returned in a `BatchResponseContent` object comprised of various `BatchResponseItem` objects corresponding to the requests made in step 1
+
+An `id` is automatically assigned to each request in the `BatchRequestContent` object.
+
+The assigned `id` can be fetched by calling `getRequests()` on the `BatchRequestContent` object.
+
+The SDK supports getting the response status code, body and headers.
+
+```php
+$batchRequests = $batchRequestContent->getRequests();
+// Uses the auto-generated ID added to the batch request content
+$response1 = $batchResponse->getResponse($batchRequests[0]->getId());
+echo "Response1 status code: {$response1->getStatusCode()}";
+
+```
+
+By default, the body is a `StreamInterface` object.
+However, you can deserialize a `BatchResponseItem` to a `Parsable` (model) implementation
+
+```php
+use Microsoft\Graph\Generated\Models\Message;
+
+$message = $batchResponse->getResponseBody($batchRequests[1]->getId(), Message::class);
+echo "Created message subject: {$message->getSubject()}\n";
+```
+
+If you would like fine-grained control over each request in the batch, you can initialise `BatchRequestItem` objects and set dependencies betweeen requests etc.
+
+For example, here we want to update a message but also want the API to return the previous message object before the update. We would need to set a dependency
+between the requests so that the update only happens after the initial message has been fetched.
+
+```php
+use Microsoft\Graph\Core\Requests\BatchRequestContent;
+use Microsoft\Graph\Core\Requests\BatchRequestItem;
+use Microsoft\Graph\Generated\Models\Message;
+
+$message = new Message();
+$message->setSubject("Test Subject");
+
+$request1 = new BatchRequestItem($graphServiceClient->users()->byUserId(USER_ID)->messages()->byMessageId('[id]')->toGetRequestInformation());
+$request2 = new BatchRequestItem($graphServiceClient->users()->byUserId(USER_ID)->messages()->byMessageId('[id]')->toPatchRequestInformation($message));
+$request2->dependsOn([$request1]);
+
+$batchRequestContent = new BatchRequestContent([
+ $request1, $request2
+]);
+
+```
+
+## Continuous Access Evaluation (CAE)
+
+See https://learn.microsoft.com/en-us/azure/active-directory/conditional-access/concept-continuous-access-evaluation
+
+CAE is disabled by default. The SDK attempts to refresh the access token only ONCE when a claims challenge is returned by the Microsoft Graph API.
+Should the SDK be unable to refresh the token, it calls a custom method provided by you which should ensure the user logs in again and provides an
+updated `TokenRequestContext`. The SDK uses this new `TokenRequestContext` to fetch a new access token. If the same request fails again with the new
+access token, the SDK returns the deserialized 401 response body:
+
+```php
+
+$tokenRequestContext = new AuthorizationCodeContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ 'authCode',
+ 'redirectUri'
+);
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$tokenRequestContext->setCAEEnabled(true);
+$tokenRequestContext->setCAERedirectCallback(function (string $claims) {
+ // your app makes the user log in again asynchronously
+ return yourCustomLoginAsync()->then(
+ function (string $authCode) {
+ $newTokenRequestContext = new AuthorizationCodeContext(
+ 'tenantId',
+ 'clientId',
+ 'clientSecret',
+ $authCode,
+ 'redirectUri'
+ );
+ return $newTokenRequestContext;
+ }
+ );
+});
+
+try {
+ $numUsers = $graphServiceClient->users()->count()->get()->wait();
+} catch (ContinuousAccessEvaluationException $ex) {
+ echo $ex->getError()->getMessage();
+}
+```
diff --git a/docs/groups_samples.md b/docs/groups_samples.md
new file mode 100644
index 00000000000..6662d35d664
--- /dev/null
+++ b/docs/groups_samples.md
@@ -0,0 +1,157 @@
+## 1. LIST ALL GROUPS IN THE TENANT (GET /groups)
+
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+try {
+ $groups = $graphServiceClient->groups()->get()->wait();
+ if ($groups && $groups->getValue()) {
+ foreach ($groups->getValue() as $group) {
+ echo "Group ID: {$group->getId()}
";
+ echo "Group Display Name: {$group->getDisplayName()}
";
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 2. GET A SPECIFIC GROUP (GET /groups/{id})
+
+
+```php
+
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$groupId = "";
+
+try {
+ $group = $graphServiceClient->groups()->byGroupId($groupId)->get()->wait();
+ if ($group) {
+ echo "Group ID: {$group->getId()}
";
+ echo "Group Display Name: {$group->getDisplayName()}
";
+ echo "Group Description: {$group->getDescription()}
";
+ echo "Group Types: " . json_encode($group->getGroupTypes()) . "
";
+ echo "Security Enabled: " . ($group->getSecurityEnabled() ? 'true' : 'false') . "
";
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " . $ex->getError()->getMessage();";
+}
+```
+
+## 3. LIST ALL MEMBERS IN A GROUP (GET /groups/{id}/members)
+
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$groupId = "";
+
+try {
+ $members = $graphServiceClient->groups()->byGroupId($groupId)->members()->get()->wait();
+ if ($members && $members->getValue()) {
+ foreach ($members->getValue() as $member) {
+ $user = $graphServiceClient->users()->byUserId($member->getId())->get()->wait();
+ if ($user) {
+ echo "User Display Name: {$user->getDisplayName()}
";
+ echo "User Mail: {$user->getMail()}
";
+ }
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 4. LIST A GROUP TEAM SHAREPOINT SITES (GET /groups/{id}/sites)
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$groupId = "c";
+
+try {
+ $sites = $graphServiceClient->groups()->byGroupId($groupId)->sites()->get()->wait();
+ if ($sites && $sites->getValue()) {
+ foreach ($sites->getValue() as $site) {
+ echo "Site ID: {$site->getId()}
";
+ echo "Site Web URL: {$site->getWebUrl()}
";
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+
+## 5. LIST A GROUP'S TRANSITIVE MEMBERS (GET /groups/{id}/transitiveMembers)
+
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$groupId = "";
+try {
+ $members = $graphServiceClient->groups()->byGroupId($groupId)->transitiveMembers()->get()->wait();
+ if ($members && $members->getValue()) {
+ foreach ($members->getValue() as $member) {
+ $obj = $graphServiceClient->directoryObjects()->byDirectoryObjectId($member->getId())->get()->wait();
+ if ($obj && $obj->getOdataType() === '#microsoft.graph.user') {
+ $user = $graphServiceClient->users()->byUserId($obj->getId())->get()->wait();
+ if ($user) {
+ echo "User ID: {$user->getId()}
";
+ echo "User Display Name: {$user->getDisplayName()}
";
+ echo "User Mail: {$user->getMail()}
";
+ }
+ }
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 6. LIST ALL GROUP DRIVES (GET /groups/{id}/drives)
+
+```php
+
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$groupId = "";
+
+try {
+ $drives = $graphServiceClient->groups()->byGroupId($groupId)->drives()->get()->wait();
+ if ($drives && $drives->getValue()) {
+ foreach ($drives->getValue() as $drive) {
+ echo "Drive ID: {$drive->getId()}
";
+ echo "Drive Name: {$drive->getName()}
";
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 7. GET A GROUP DRIVE (GET /groups/{id}/drives/{id})
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$groupId = "";
+$driveId = "";
+
+try {
+ $drive = $graphServiceClient->groups()->byGroupId($groupId)->drives()->byDriveId($driveId)->get()->wait();
+ if ($drive) {
+ echo "Drive ID: {$drive->getId()}
";
+ echo "Drive Type: {$drive->getDriveType()}
";
+ echo "Drive Name: {$drive->getName()}
";
+ echo "Drive Web URL: {$drive->getWebUrl()}
";
+ echo "Drive Items: " . json_encode($drive->getItems()) . "
";
+ }
+} catch (ApiException $ex) {
+ echo $ex->getError()->getMessage();
+}
+```
\ No newline at end of file
diff --git a/docs/sharepoint_samples.md b/docs/sharepoint_samples.md
new file mode 100644
index 00000000000..3738a16faa9
--- /dev/null
+++ b/docs/sharepoint_samples.md
@@ -0,0 +1,89 @@
+## Get Site By Site ID
+
+```php
+
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$siteId = "";
+
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+try {
+
+ $siteData = $graphServiceClient->sites()->bySiteId($siteId)->get()->wait();
+ echo "Site ID: {$siteData->getId()}\n";
+ echo "Site Name: {$siteData->getName()}\n";
+ echo "Site URL: {$siteData->getWebUrl()}\n";
+
+
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## Get Site Lists
+```php
+$siteId = "";
+
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+try {
+
+ $siteLists = $graphServiceClient->sites()->bySiteId($siteId)->lists()->get()->wait();
+ foreach ($siteLists->getValue() as $item) {
+ echo "Site ID: {$item->getId()}
";
+ echo "Site Name: {$item->getName()}
";
+ echo "Site Additional Data: " . json_encode($item->getAdditionalData()) . "
";
+ echo "Site URL: {$item->getWebUrl()}
";
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+```
+
+## Get Site List List items - by site id and site list id
+```php
+
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$siteId = "";
+$listId = "";
+
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+try {
+
+ $siteList = $graphServiceClient->sites()->bySiteId($siteId)->lists()->byListId($listId)->get()->wait();
+ echo "Site URL: {$siteList->getWebUrl()}\n";
+ echo "Site ID: {$siteList->getId()}\n";
+ echo "Site Name: {$siteList->getName()}\n";
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+```
+
+## Get site list items
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$siteId = "";
+$listId = "";
+
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+try {
+
+ $siteListItems = $graphServiceClient->sites()->bySiteId($siteId)->lists()->byListId($listId)->items()->get()->wait();
+ foreach ($siteListItems->getValue() as $item) {
+ echo "Site ID: {$item->getId()}\n";
+ echo "Site Name: {$item->getName()}\n";
+ echo "Site Additional Data: " . json_encode($item->getAdditionalData()) . "\n";
+ echo "Site URL: {$item->getWebUrl()}\n";
+ }
+
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
\ No newline at end of file
diff --git a/docs/uploads_samples.md b/docs/uploads_samples.md
new file mode 100644
index 00000000000..e914c1651ad
--- /dev/null
+++ b/docs/uploads_samples.md
@@ -0,0 +1,72 @@
+
+## Upload an item
+
+For files less than 3MB, you can send a byte stream to the API with the sample below. See the next section for files larger than 3MB.
+
+```php
+
+$driveItemId = 'root:/upload.txt:';
+
+$inputStream = Utils::streamFor(fopen('upload.txt', 'r'));
+$uploadItem = $graphServiceClient->drives()->byDriveId('[driveId]')->items()->byDriveItemId($driveItemId)->content()->put($inputStream)->wait();
+
+```
+
+
+## Uploading large files
+
+To upload files larger than 3MB, the Microsoft Graph API supports uploads using resumable upload sessions where a number of bytes are uploaded at a time.
+
+The SDK provides a `LargeFileUpload` task that slices your file into bytes and progressively uploads them until completion.
+
+To add a large attachment to an Outlook message:
+
+```php
+use Psr\Http\Client\NetworkExceptionInterface;
+
+
+// create a file stream
+$file = Utils::streamFor(fopen('fileName', 'r'));
+
+// create an upload session
+$attachmentItem = new AttachmentItem();
+$attachmentItem->setAttachmentType(new AttachmentType('file'));
+$attachmentItem->setName('fileName');
+$attachmentItem->setSize($file->getSize());
+
+$uploadSessionRequestBody = new CreateUploadSessionPostRequestBody();
+$uploadSessionRequestBody->setAttachmentItem($attachmentItem);
+
+$uploadSession = $graphServiceClient->users()->byUserId(USER_ID)->messages()->byMessageId('[id]')->attachments()->createUploadSession()->post($uploadSessionRequestBody)->wait();
+
+// upload
+$largeFileUpload = new LargeFileUploadTask($uploadSession, $graphServiceClient->getRequestAdapter(), $file);
+try {
+ $uploadSession = $largeFileUpload->upload()->wait();
+} catch (NetworkExceptionInterface $ex) {
+ // resume upload in case of network errors
+ $retries = 0;
+ $maxRetries = 3;
+ while ($retries < $maxRetries) {
+ try {
+ $uploadSession = $largeFileUpload->resume()->wait();
+ if ($uploadSession) {
+ break;
+ }
+ } catch (NetworkExceptionInterface $ex) {
+ $retries ++;
+ }
+ }
+ throw $ex;
+}
+
+```
+
+You can also cancel a large file upload session:
+
+```php
+$largeFileUpload->cancel()->wait();
+```
+
+*Known Issue*
+At the moment, when attaching large files to Outlook Messages and Events, we don't expose the `Location` header value. For now, you'd need to fetch the message's attachments/events.
diff --git a/docs/users_samples.md b/docs/users_samples.md
new file mode 100644
index 00000000000..6b8f90ec8ba
--- /dev/null
+++ b/docs/users_samples.md
@@ -0,0 +1,69 @@
+## 1. GET ALL USERS IN A TENANT (GET /users)
+
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+try {
+ $users = $graphServiceClient->users()->get()->wait();
+ if ($users && $users->getValue()) {
+ foreach ($users->getValue() as $user) {
+ echo "User ID: {$user->getId()}
";
+ echo "User Display Name: {$user->getDisplayName()}
";
+ echo "User Mail: {$user->getMail()}
";
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 2. GET A SPECIFIC USER (GET /users/{id | userPrincipalName})
+
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$userId = "";
+
+try {
+ $user = $graphServiceClient->users()->byUserId($userId)->get()->wait();
+ if ($user) {
+ echo "User Principal Name: {$user->getUserPrincipalName()}
";
+ echo "User Display Name: {$user->getDisplayName()}
";
+ echo "User ID: {$user->getId()}
";
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```
+
+## 3. SEARCH USER BY NAME (GET /users/$search?=)
+
+
+```php
+$graphServiceClient = new GraphServiceClient($tokenRequestContext);
+
+$userId = "";
+
+try {
+ $memberships = $graphServiceClient->users()->byUserId($userId)->transitiveMemberOf()->get()->wait();
+ if ($memberships && $memberships->getValue()) {
+ foreach ($memberships->getValue() as $membership) {
+ $obj = $graphServiceClient->directoryObjects()->byDirectoryObjectId($membership->getId())->get()->wait();
+ if ($obj && $obj->getOdataType() === '#microsoft.graph.group') {
+ $group = $graphServiceClient->groups()->byGroupId($obj->getId())->get()->wait();
+ if ($group) {
+ echo "Group ID: {$group->getId()}
";
+ echo "Group Types: " . json_encode($group->getGroupTypes()) . "
";
+ echo "Group Display Name: {$group->getDisplayName()}
";
+ echo "Group Mail: {$group->getMail()}
";
+ }
+ }
+ }
+ }
+} catch (ApiException $ex) {
+ echo "Error: " . $ex->getResponseStatusCode() . "\n";
+ echo "Error: " .$ex->getError()->getMessage();";
+}
+```