├── .github ├── ISSUE_TEMPLATE │ ├── ask-a-question.md │ └── bug_report.md ├── dependabot.yml ├── policies │ ├── closeStaleIssues.yml │ └── labelStaleIssues.yml └── workflows │ ├── auto-merge-dependabot.yml │ └── php.yml ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── app-auth ├── README.md ├── RegisterAppForAppOnlyAuth.ps1 └── graphapponlytutorial │ ├── .env.example │ ├── GraphHelper.php │ ├── composer.json │ ├── composer.lock │ ├── main.php │ └── phpstan.neon ├── qs.json └── user-auth ├── README.md ├── RegisterAppForUserAuth.ps1 ├── graphtutorial ├── .env.example ├── DeviceCodeTokenProvider.php ├── GraphHelper.php ├── composer.json ├── composer.lock ├── main.php └── phpstan.neon └── version /.github/ISSUE_TEMPLATE/ask-a-question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Ask a question 3 | about: Ask a question about Graph, adding features to this sample, etc. 4 | title: '' 5 | labels: question, needs triage 6 | assignees: '' 7 | 8 | --- 9 | 10 | Thank you for taking an interest in Microsoft Graph development! Please feel free to ask a question here, but keep in mind the following: 11 | 12 | - This is not an official Microsoft support channel, and our ability to respond to questions here is limited. Questions about Graph, or questions about adding a new feature to the sample, will be answered on a best-effort basis. 13 | - Questions should be asked on [Microsoft Q&A](https://aka.ms/askgraph). 14 | - Issues with Microsoft Graph itself should be handled through [support](https://developer.microsoft.com/graph/support). 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug report, needs triage 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Where did you get the code?** 11 | 12 | - [ ] Downloaded from GitHub 13 | - [ ] Downloaded from the [Microsoft Graph quick start tool](https://developer.microsoft.com/graph/quick-start) 14 | - [ ] Followed the tutorial from [Microsoft Graph tutorials](https://learn.microsoft.com/graph/tutorials) 15 | 16 | **Describe the bug** 17 | A clear and concise description of what the bug is. 18 | 19 | **To Reproduce** 20 | Steps to reproduce the behavior: 21 | 22 | 1. Go to '...' 23 | 2. Click on '....' 24 | 3. Scroll down to '....' 25 | 4. See error 26 | 27 | **Expected behavior** 28 | A clear and concise description of what you expected to happen. 29 | 30 | **Screenshots** 31 | If applicable, add screenshots to help explain your problem. 32 | 33 | **Desktop (please complete the following information):** 34 | 35 | - OS: [e.g. iOS] 36 | - Browser [e.g. chrome, safari] 37 | - Version [e.g. 22] 38 | 39 | **Dependency versions** 40 | 41 | - Authentication library (MSAL, etc.) version: 42 | - Graph library (Graph SDK, REST library, etc.) version: 43 | 44 | **Additional context** 45 | Add any other context about the problem here. 46 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "composer" # See documentation for possible values 9 | directory: "/user-auth/graphtutorial" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | 13 | - package-ecosystem: "composer" # See documentation for possible values 14 | directory: "/app-auth/graphapponlytutorial" # Location of package manifests 15 | schedule: 16 | interval: "weekly" 17 | -------------------------------------------------------------------------------- /.github/policies/closeStaleIssues.yml: -------------------------------------------------------------------------------- 1 | name: Close stale issues 2 | description: Close issues labeled no recent activity with no response for 3 days 3 | resource: repository 4 | 5 | configuration: 6 | resourceManagementConfiguration: 7 | scheduledSearches: 8 | - description: Close any issues with no recent activity label that have not had activity for 3 days 9 | frequencies: 10 | - daily: 11 | time: 13:00 12 | filters: 13 | - isOpen 14 | - hasLabel: 15 | label: no recent activity 16 | - hasLabel: 17 | label: needs author feedback 18 | - noActivitySince: 19 | days: 3 20 | actions: 21 | - removeLabel: 22 | label: no recent activity 23 | - removeLabel: 24 | label: needs author feedback 25 | - closeIssue 26 | -------------------------------------------------------------------------------- /.github/policies/labelStaleIssues.yml: -------------------------------------------------------------------------------- 1 | name: Label stale issues 2 | description: Label issues waiting for author response with no response for a week 3 | resource: repository 4 | 5 | configuration: 6 | resourceManagementConfiguration: 7 | scheduledSearches: 8 | - description: Label any issues waiting for author feedback with no response in 7 days 9 | frequencies: 10 | - daily: 11 | time: 13:00 12 | filters: 13 | - isOpen 14 | - hasLabel: 15 | label: needs author feedback 16 | - isNotLabeledWith: 17 | label: no recent activity 18 | - noActivitySince: 19 | days: 7 20 | actions: 21 | - addLabel: 22 | label: no recent activity 23 | - addReply: 24 | reply: This issue has been automatically marked as stale because it has been marked as needing author feedback but has not had any activity for **7 days**. It will be closed if no further activity occurs **within 3 days of this comment**. 25 | eventResponderTasks: 26 | - description: Remove needs author feedback and no recent activity if author comments 27 | if: 28 | - payloadType: Issue_Comment 29 | - isAction: Created 30 | - isActivitySender: 31 | issueAuthor: true 32 | - hasLabel: 33 | label: needs author feedback 34 | - isOpen 35 | then: 36 | - removeLabel: 37 | label: needs author feedback 38 | - removeLabel: 39 | label: no recent activity 40 | - addLabel: 41 | label: 'needs attention :wave:' 42 | -------------------------------------------------------------------------------- /.github/workflows/auto-merge-dependabot.yml: -------------------------------------------------------------------------------- 1 | name: Auto-merge dependabot updates 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | 7 | permissions: 8 | pull-requests: write 9 | contents: write 10 | 11 | jobs: 12 | 13 | dependabot-merge: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | if: ${{ github.actor == 'dependabot[bot]' }} 18 | 19 | steps: 20 | - name: Dependabot metadata 21 | id: metadata 22 | uses: dependabot/fetch-metadata@v1.1.1 23 | with: 24 | github-token: "${{ secrets.GITHUB_TOKEN }}" 25 | 26 | - name: Enable auto-merge for Dependabot PRs 27 | if: ${{steps.metadata.outputs.update-type != 'version-update:semver-major'}} 28 | run: gh pr merge --auto --merge "$PR_URL" 29 | env: 30 | PR_URL: ${{github.event.pull_request.html_url}} 31 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 32 | -------------------------------------------------------------------------------- /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main, live ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | build-user: 14 | defaults: 15 | run: 16 | working-directory: user-auth/graphtutorial/ 17 | 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | 23 | - name: Validate composer.json and composer.lock 24 | run: composer validate --strict 25 | 26 | - name: Cache Composer packages 27 | id: composer-cache 28 | uses: actions/cache@v3 29 | with: 30 | path: vendor 31 | key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} 32 | restore-keys: | 33 | ${{ runner.os }}-php- 34 | 35 | - name: Install dependencies 36 | run: composer install --prefer-dist --no-progress 37 | 38 | - name: Run test suite 39 | run: composer run-script test 40 | 41 | build-app-only: 42 | defaults: 43 | run: 44 | working-directory: app-auth/graphapponlytutorial/ 45 | 46 | runs-on: ubuntu-latest 47 | 48 | steps: 49 | - uses: actions/checkout@v3 50 | 51 | - name: Validate composer.json and composer.lock 52 | run: composer validate --strict 53 | 54 | - name: Cache Composer packages 55 | id: composer-cache 56 | uses: actions/cache@v3 57 | with: 58 | path: vendor 59 | key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} 60 | restore-keys: | 61 | ${{ runner.os }}-php- 62 | 63 | - name: Install dependencies 64 | run: composer install --prefer-dist --no-progress 65 | 66 | - name: Run test suite 67 | run: composer run-script test 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | composer.phar 2 | vendor/ 3 | 4 | # Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control 5 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 6 | # composer.lock 7 | 8 | .env 9 | *.zip 10 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "xdebug.php-debug", 4 | "bmewburn.vscode-intelephense-client" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Debug user auth sample", 9 | "type": "php", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/user-auth/graphtutorial/main.php", 12 | "cwd": "${fileDirname}", 13 | "externalConsole": true, 14 | "port": 0, 15 | "runtimeArgs": [ 16 | "-dxdebug.start_with_request=yes" 17 | ], 18 | "env": { 19 | "XDEBUG_MODE": "debug,develop", 20 | "XDEBUG_CONFIG": "client_port=${port}" 21 | } 22 | }, 23 | { 24 | "name": "Debug app auth sample", 25 | "type": "php", 26 | "request": "launch", 27 | "program": "${workspaceFolder}/app-auth/graphapponlytutorial/main.php", 28 | "cwd": "${fileDirname}", 29 | "externalConsole": true, 30 | "port": 0, 31 | "runtimeArgs": [ 32 | "-dxdebug.start_with_request=yes" 33 | ], 34 | "env": { 35 | "XDEBUG_MODE": "debug,develop", 36 | "XDEBUG_CONFIG": "client_port=${port}" 37 | } 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "analyse", 4 | "CURLOPT", 5 | "devicecode", 6 | "FAILONERROR", 7 | "graphapponlytutorial", 8 | "graphtutorial", 9 | "phpdotenv", 10 | "phpstan", 11 | "vlucas" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | - Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support) 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Microsoft Graph 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build PHP apps with Microsoft Graph - Completed project 2 | 3 | [![PHP Composer](https://github.com/microsoftgraph/msgraph-training-php/actions/workflows/php.yml/badge.svg)](https://github.com/microsoftgraph/msgraph-training-php/actions/workflows/php.yml) 4 | 5 | This sample will introduce you to working with the Microsoft Graph SDK to access data in Microsoft 365 from PHP applications. This code is the result of completing the [PHP Microsoft Graph tutorial](https://learn.microsoft.com/graph/tutorials/php) and the [.NET Microsoft Graph app-only tutorial](https://learn.microsoft.com/graph/tutorials/php-app-only). 6 | 7 | ## Running the sample 8 | 9 | The code for the delegated user authentication sample is in the [user-auth](user-auth) folder. Instructions to configure and run the sample can be found in the [README](user-auth/README.md) in that folder. 10 | 11 | The code for the app-only authentication sample is in the [app-auth](app-auth) folder. Instructions to configure and run the sample can be found in the [README](app-auth/README.md) in that folder. 12 | 13 | ## Code of conduct 14 | 15 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 16 | 17 | ## Disclaimer 18 | 19 | **THIS CODE IS PROVIDED _AS IS_ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.** 20 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /app-auth/README.md: -------------------------------------------------------------------------------- 1 | # How to run the completed project 2 | 3 | ## Prerequisites 4 | 5 | To run the completed project in this folder, you need the following: 6 | 7 | - [PHP](https://www.php.net/) and [Composer](https://getcomposer.org/) installed on your development machine. (**Note:** This tutorial was written with PHP version 8.1.5 and Composer version 2.3.5. The steps in this guide may work with other versions, but that has not been tested.) 8 | - A Microsoft work or school account with the **Global administrator** role. 9 | 10 | If you don't have a Microsoft account, you can [sign up for the Microsoft 365 Developer Program](https://developer.microsoft.com/microsoft-365/dev-program) to get a free Microsoft 365 subscription. 11 | 12 | ## Register an application 13 | 14 | You can register an application using the Azure Active Directory admin center, or by using the [Microsoft Graph PowerShell SDK](https://learn.microsoft.com/graph/powershell/get-started). 15 | 16 | ### Azure Active Directory admin center 17 | 18 | 1. Open a browser and navigate to the [Azure Active Directory admin center](https://aad.portal.azure.com) and login using a Global administrator account. 19 | 20 | 1. Select **Azure Active Directory** in the left-hand navigation, then select **App registrations** under **Manage**. 21 | 22 | 1. Select **New registration**. Enter a name for your application, for example, `PHP App-Only Graph Tutorial`. 23 | 24 | 1. Set **Supported account types** to **Accounts in this organizational directory only**. 25 | 26 | 1. Leave **Redirect URI** empty. 27 | 28 | 1. Select **Register**. On the application's **Overview** page, copy the value of the **Application (client) ID** and **Directory (tenant) ID** and save them, you will need these values in the next step. 29 | 30 | 1. Select **API permissions** under **Manage**. 31 | 32 | 1. Remove the default **User.Read** permission under **Configured permissions** by selecting the ellipses (**...**) in its row and selecting **Remove permission**. 33 | 34 | 1. Select **Add a permission**, then **Microsoft Graph**. 35 | 36 | 1. Select **Application permissions**. 37 | 38 | 1. Select **User.Read.All**, then select **Add permissions**. 39 | 40 | 1. Select **Grant admin consent for...**, then select **Yes** to provide admin consent for the selected permission. 41 | 42 | 1. Select **Certificates and secrets** under **Manage**, then select **New client secret**. 43 | 44 | 1. Enter a description, choose a duration, and select **Add**. 45 | 46 | 1. Copy the secret from the **Value** column, you will need it in the next steps. 47 | 48 | ### PowerShell 49 | 50 | To use PowerShell, you'll need the Microsoft Graph PowerShell SDK. If you do not have it, see [Install the Microsoft Graph PowerShell SDK](https://learn.microsoft.com/graph/powershell/installation) for installation instructions. 51 | 52 | 1. Open PowerShell and run the [RegisterAppForAppOnlyAuth.ps1](RegisterAppForAppOnlyAuth.ps1) file with the following command. 53 | 54 | ```powershell 55 | .\RegisterAppForAppOnlyAuth.ps1 -AppName "PHP App-Only Graph Tutorial" -GraphScopes "User.Read.All" 56 | ``` 57 | 58 | 1. Copy the **Client ID**, **Tenant ID**, and **Client secret** values from the script output. You will need these values in the next step. 59 | 60 | ```powershell 61 | SUCCESS 62 | Client ID: ae2386e6-799e-4f75-b191-855d7e691c75 63 | Tenant ID: 5927c10a-91bd-4408-9c70-c50bce922b71 64 | Client secret: ... 65 | Secret expires: 10/28/2024 5:01:45 PM 66 | ``` 67 | 68 | ## Configure the sample 69 | 70 | 1. Rename [.env.example](./graphapponlytutorial/.env.example) to **.env** and update the values according to the following table. 71 | 72 | | Setting | Value | 73 | |-----------------|-------| 74 | | `CLIENT_ID` | The client ID of your app registration | 75 | | `CLIENT_SECRET` | The client secret of your app registration | 76 | | `TENANT_ID` | The tenant ID of your organization | 77 | 78 | ## Run the sample 79 | 80 | In your command-line interface (CLI), navigate to the project directory and run the following commands. 81 | 82 | ```bash 83 | composer install 84 | php main.php 85 | ``` 86 | -------------------------------------------------------------------------------- /app-auth/RegisterAppForAppOnlyAuth.ps1: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT license. 3 | 4 | # 5 | param( 6 | [Parameter(Mandatory=$true, 7 | HelpMessage="The friendly name of the app registration")] 8 | [String] 9 | $AppName, 10 | 11 | [Parameter(Mandatory=$true, 12 | HelpMessage="The application permission scopes to configure on the app registration")] 13 | [String[]] 14 | $GraphScopes, 15 | 16 | [Parameter(Mandatory=$false)] 17 | [Switch] 18 | $StayConnected = $false 19 | ) 20 | 21 | $graphAppId = "00000003-0000-0000-c000-000000000000" 22 | 23 | # Requires an admin 24 | Connect-MgGraph -Scopes "Application.ReadWrite.All AppRoleAssignment.ReadWrite.All User.Read" -UseDeviceAuthentication -ErrorAction Stop 25 | 26 | # Get context for access to tenant ID 27 | $context = Get-MgContext -ErrorAction Stop 28 | $authTenant = $context.TenantId 29 | 30 | # Create app registration 31 | $appRegistration = New-MgApplication -DisplayName $AppName -SignInAudience "AzureADMyOrg" -ErrorAction Stop 32 | Write-Host -ForegroundColor Cyan "App registration created with app ID" $appRegistration.AppId 33 | 34 | # Create corresponding service principal 35 | $appServicePrincipal = New-MgServicePrincipal -AppId $appRegistration.AppId -ErrorAction SilentlyContinue ` 36 | -ErrorVariable SPError 37 | if ($SPError) 38 | { 39 | Write-Host -ForegroundColor Red "A service principal for the app could not be created." 40 | Write-Host -ForegroundColor Red $SPError 41 | Exit 42 | } 43 | 44 | Write-Host -ForegroundColor Cyan "Service principal created" 45 | 46 | # Lookup available Graph application permissions 47 | $graphServicePrincipal = Get-MgServicePrincipal -Filter ("appId eq '" + $graphAppId + "'") -ErrorAction Stop 48 | $graphAppPermissions = $graphServicePrincipal.AppRoles 49 | 50 | $resourceAccess = @() 51 | 52 | foreach($scope in $GraphScopes) 53 | { 54 | $permission = $graphAppPermissions | Where-Object { $_.Value -eq $scope } 55 | if ($permission) 56 | { 57 | $resourceAccess += @{ Id = $permission.Id; Type = "Role"} 58 | } 59 | else 60 | { 61 | Write-Host -ForegroundColor Red "Invalid scope:" $scope 62 | Exit 63 | } 64 | } 65 | 66 | # Add the permissions to required resource access 67 | Update-MgApplication -ApplicationId $appRegistration.Id -RequiredResourceAccess ` 68 | @{ ResourceAppId = $graphAppId; ResourceAccess = $resourceAccess } -ErrorAction Stop 69 | Write-Host -ForegroundColor Cyan "Added application permissions to app registration" 70 | 71 | # Add admin consent 72 | foreach ($appRole in $resourceAccess) 73 | { 74 | New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $appServicePrincipal.Id ` 75 | -PrincipalId $appServicePrincipal.Id -ResourceId $graphServicePrincipal.Id ` 76 | -AppRoleId $appRole.Id -ErrorAction SilentlyContinue -ErrorVariable SPError | Out-Null 77 | if ($SPError) 78 | { 79 | Write-Host -ForegroundColor Red "Admin consent for one of the requested scopes could not be added." 80 | Write-Host -ForegroundColor Red $SPError 81 | Exit 82 | } 83 | } 84 | Write-Host -ForegroundColor Cyan "Added admin consent" 85 | 86 | # Add a client secret 87 | $clientSecret = Add-MgApplicationPassword -ApplicationId $appRegistration.Id -PasswordCredential ` 88 | @{ DisplayName = "Added by PowerShell" } -ErrorAction Stop 89 | 90 | Write-Host 91 | Write-Host -ForegroundColor Green "SUCCESS" 92 | Write-Host -ForegroundColor Cyan -NoNewline "Client ID: " 93 | Write-Host -ForegroundColor Yellow $appRegistration.AppId 94 | Write-Host -ForegroundColor Cyan -NoNewline "Tenant ID: " 95 | Write-Host -ForegroundColor Yellow $authTenant 96 | Write-Host -ForegroundColor Cyan -NoNewline "Client secret: " 97 | Write-Host -ForegroundColor Yellow $clientSecret.SecretText 98 | Write-Host -ForegroundColor Cyan -NoNewline "Secret expires: " 99 | Write-Host -ForegroundColor Yellow $clientSecret.EndDateTime 100 | 101 | if ($StayConnected -eq $false) 102 | { 103 | Disconnect-MgGraph | Out-Null 104 | Write-Host "Disconnected from Microsoft Graph" 105 | } 106 | else 107 | { 108 | Write-Host 109 | Write-Host -ForegroundColor Yellow ` 110 | "The connection to Microsoft Graph is still active. To disconnect, use Disconnect-MgGraph" 111 | } 112 | # 113 | -------------------------------------------------------------------------------- /app-auth/graphapponlytutorial/.env.example: -------------------------------------------------------------------------------- 1 | CLIENT_ID=YOUR_CLIENT_ID_HERE 2 | CLIENT_SECRET=YOUR_CLIENT_SECRET_HERE_IF_USING_APP_ONLY 3 | TENANT_ID=YOUR_TENANT_ID_HERE_IF_USING_APP_ONLY 4 | -------------------------------------------------------------------------------- /app-auth/graphapponlytutorial/GraphHelper.php: -------------------------------------------------------------------------------- 1 | 6 | use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAccessTokenProvider; 7 | use Microsoft\Graph\Generated\Models; 8 | use Microsoft\Graph\Generated\Users\UsersRequestBuilderGetQueryParameters; 9 | use Microsoft\Graph\Generated\Users\UsersRequestBuilderGetRequestConfiguration; 10 | use Microsoft\Graph\GraphServiceClient; 11 | use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext; 12 | // 13 | 14 | class GraphHelper { 15 | // 16 | private static string $clientId = ''; 17 | private static string $clientSecret = ''; 18 | private static string $tenantId = ''; 19 | private static ClientCredentialContext $tokenContext; 20 | private static GraphServiceClient $appClient; 21 | 22 | public static function initializeGraphForAppOnlyAuth(): void { 23 | GraphHelper::$clientId = $_ENV['CLIENT_ID']; 24 | GraphHelper::$clientSecret = $_ENV['CLIENT_SECRET']; 25 | GraphHelper::$tenantId = $_ENV['TENANT_ID']; 26 | 27 | GraphHelper::$tokenContext = new ClientCredentialContext( 28 | GraphHelper::$tenantId, 29 | GraphHelper::$clientId, 30 | GraphHelper::$clientSecret); 31 | 32 | GraphHelper::$appClient = new GraphServiceClient( 33 | GraphHelper::$tokenContext, ['https://graph.microsoft.com/.default']); 34 | } 35 | // 36 | 37 | // 38 | public static function getAppOnlyToken(): string { 39 | // Create an access token provider to get the token 40 | $tokenProvider = new GraphPhpLeagueAccessTokenProvider(GraphHelper::$tokenContext); 41 | return $tokenProvider 42 | ->getAuthorizationTokenAsync('https://graph.microsoft.com') 43 | ->wait(); 44 | } 45 | // 46 | 47 | // 48 | public static function getUsers(): Models\UserCollectionResponse { 49 | $configuration = new UsersRequestBuilderGetRequestConfiguration(); 50 | $configuration->queryParameters = new UsersRequestBuilderGetQueryParameters(); 51 | // Only request specific properties 52 | $configuration->queryParameters->select = ['displayName','id','mail']; 53 | // Sort by display name 54 | $configuration->queryParameters->orderby = ['displayName']; 55 | // Get at most 25 results 56 | $configuration->queryParameters->top = 25; 57 | 58 | return GraphHelper::$appClient->users()->get($configuration)->wait(); 59 | } 60 | // 61 | 62 | // 63 | public static function makeGraphCall(): void { 64 | // INSERT YOUR CODE HERE 65 | } 66 | // 67 | } 68 | ?> 69 | -------------------------------------------------------------------------------- /app-auth/graphapponlytutorial/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "microsoft/graphapponlytutorial", 3 | "description": "Microsoft Graph PHP App-Only tutorial", 4 | "type": "project", 5 | "license": "MIT", 6 | "scripts": { 7 | "test": "./vendor/bin/phpstan analyse -c ./phpstan.neon --level 7 ./" 8 | }, 9 | "require": { 10 | "vlucas/phpdotenv": "^5.4", 11 | "microsoft/microsoft-graph": "^2.0.0", 12 | "php-http/guzzle7-adapter": "^1.0" 13 | }, 14 | "require-dev": { 15 | "phpstan/phpstan": "^1.10" 16 | }, 17 | "minimum-stability": "dev", 18 | "prefer-stable": true, 19 | "config": { 20 | "allow-plugins": { 21 | "php-http/discovery": true 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app-auth/graphapponlytutorial/main.php: -------------------------------------------------------------------------------- 1 | 6 | // Enable loading of Composer dependencies 7 | require_once realpath(__DIR__ . '/vendor/autoload.php'); 8 | require_once 'GraphHelper.php'; 9 | 10 | print('PHP Graph Tutorial'.PHP_EOL.PHP_EOL); 11 | 12 | // Load .env file 13 | $dotenv = Dotenv\Dotenv::createImmutable(__DIR__); 14 | $dotenv->load(); 15 | $dotenv->required(['CLIENT_ID', 'CLIENT_SECRET', 'TENANT_ID']); 16 | 17 | initializeGraph(); 18 | 19 | $choice = -1; 20 | 21 | while ($choice != 0) { 22 | echo('Please choose one of the following options:'.PHP_EOL); 23 | echo('0. Exit'.PHP_EOL); 24 | echo('1. Display access token'.PHP_EOL); 25 | echo('2. List users'.PHP_EOL); 26 | echo('3. Make a Graph call'.PHP_EOL); 27 | 28 | $choice = (int)readline(''); 29 | 30 | switch ($choice) { 31 | case 1: 32 | displayAccessToken(); 33 | break; 34 | case 2: 35 | listUsers(); 36 | break; 37 | case 3: 38 | makeGraphCall(); 39 | break; 40 | case 0: 41 | default: 42 | print('Goodbye...'.PHP_EOL); 43 | } 44 | } 45 | // 46 | 47 | // 48 | function initializeGraph(): void { 49 | GraphHelper::initializeGraphForAppOnlyAuth(); 50 | } 51 | // 52 | 53 | // 54 | function displayAccessToken(): void { 55 | try { 56 | $token = GraphHelper::getAppOnlyToken(); 57 | print('App-only token: '.$token.PHP_EOL.PHP_EOL); 58 | } catch (Exception $e) { 59 | print('Error getting access token: '.$e->getMessage().PHP_EOL.PHP_EOL); 60 | } 61 | } 62 | // 63 | 64 | // 65 | function listUsers(): void { 66 | try { 67 | $users = GraphHelper::getUsers(); 68 | 69 | // Output each user's details 70 | foreach ($users->getValue() as $user) { 71 | print('User: '.$user->getDisplayName().PHP_EOL); 72 | print(' ID: '.$user->getId().PHP_EOL); 73 | $email = $user->getMail(); 74 | $email = isset($email) ? $email : 'NO EMAIL'; 75 | print(' Email: '.$email.PHP_EOL); 76 | } 77 | 78 | $nextLink = $users->getOdataNextLink(); 79 | $moreAvailable = isset($nextLink) && $nextLink != '' ? 'True' : 'False'; 80 | print(PHP_EOL.'More users available? '.$moreAvailable.PHP_EOL.PHP_EOL); 81 | } catch (Exception $e) { 82 | print(PHP_EOL.'Error getting users: '.$e->getMessage().PHP_EOL.PHP_EOL); 83 | } 84 | } 85 | // 86 | 87 | // 88 | function makeGraphCall(): void { 89 | try { 90 | GraphHelper::makeGraphCall(); 91 | } catch (Exception $e) { 92 | print(PHP_EOL.'Error making Graph call'.PHP_EOL.PHP_EOL); 93 | } 94 | } 95 | // 96 | ?> 97 | -------------------------------------------------------------------------------- /app-auth/graphapponlytutorial/phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | excludePaths: 3 | - vendor/* 4 | -------------------------------------------------------------------------------- /qs.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceDirectory": "./user-auth", 3 | "exampleConfigFile": "./graphtutorial/.env.example", 4 | "configFile": ".env", 5 | "archiveFile": "PhpScriptQuickStart.zip", 6 | "zipReadMe": "./README.md", 7 | "excludeFiles": [ 8 | "user-auth/RegisterAppForUserAuth.ps1" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /user-auth/README.md: -------------------------------------------------------------------------------- 1 | # How to run the completed project 2 | 3 | ## Prerequisites 4 | 5 | To run the completed project in this folder, you need the following: 6 | 7 | - [PHP](https://www.php.net/) and [Composer](https://getcomposer.org/) installed on your development machine. (**Note:** This tutorial was written with PHP version 8.1.5 and Composer version 2.3.5. The steps in this guide may work with other versions, but that has not been tested.) 8 | - Either a personal Microsoft account with a mailbox on Outlook.com, or a Microsoft work or school account. If you don't have a Microsoft account, there are a couple of options to get a free account: 9 | - You can [sign up for a new personal Microsoft account](https://signup.live.com/signup?wa=wsignin1.0&rpsnv=12&ct=1454618383&rver=6.4.6456.0&wp=MBI_SSL_SHARED&wreply=https://mail.live.com/default.aspx&id=64855&cbcxt=mai&bk=1454618383&uiflavor=web&uaid=b213a65b4fdc484382b6622b3ecaa547&mkt=E-US&lc=1033&lic=1). 10 | - You can [sign up for the Microsoft 365 Developer Program](https://developer.microsoft.com/microsoft-365/dev-program) to get a free Microsoft 365 subscription. 11 | 12 | ## Register an application 13 | 14 | You can register an application using the Azure Active Directory admin center, or by using the [Microsoft Graph PowerShell SDK](https://learn.microsoft.com/graph/powershell/get-started). 15 | 16 | ### Azure Active Directory admin center 17 | 18 | 1. Open a browser and navigate to the [Azure Active Directory admin center](https://aad.portal.azure.com) and login using a **personal account** (aka: Microsoft Account) or **Work or School Account**. 19 | 20 | 1. Select **Azure Active Directory** in the left-hand navigation, then select **App registrations** under **Manage**. 21 | 22 | 1. Select **New registration**. Enter a name for your application, for example, `PHP Graph Tutorial`. 23 | 24 | 1. Set **Supported account types** as desired. The options are: 25 | 26 | | Option | Who can sign in? | 27 | |--------|------------------| 28 | | **Accounts in this organizational directory only** | Only users in your Microsoft 365 organization | 29 | | **Accounts in any organizational directory** | Users in any Microsoft 365 organization (work or school accounts) | 30 | | **Accounts in any organizational directory ... and personal Microsoft accounts** | Users in any Microsoft 365 organization (work or school accounts) and personal Microsoft accounts | 31 | 32 | 1. Leave **Redirect URI** empty. 33 | 34 | 1. Select **Register**. On the application's **Overview** page, copy the value of the **Application (client) ID** and save it, you will need it in the next step. If you chose **Accounts in this organizational directory only** for **Supported account types**, also copy the **Directory (tenant) ID** and save it. 35 | 36 | 1. Select **Authentication** under **Manage**. Locate the **Advanced settings** section and change the **Allow public client flows** toggle to **Yes**, then choose **Save**. 37 | 38 | ### PowerShell 39 | 40 | To use PowerShell, you'll need the Microsoft Graph PowerShell SDK. If you do not have it, see [Install the Microsoft Graph PowerShell SDK](https://learn.microsoft.com/graph/powershell/installation) for installation instructions. 41 | 42 | 1. Open PowerShell and run the [RegisterAppForUserAuth.ps1](RegisterAppForUserAuth.ps1) file with the following command, replacing *<audience-value>* with the desired value (see table below). 43 | 44 | > **Note:** The RegisterAppForUserAuth.ps1 script requires a work/school account with the Application administrator, Cloud application administrator, or Global administrator role. 45 | 46 | ```powershell 47 | .\RegisterAppForUserAuth.ps1 -AppName "PHP Graph Tutorial" -SignInAudience 48 | ``` 49 | 50 | | SignInAudience value | Who can sign in? | 51 | |----------------------|------------------| 52 | | `AzureADMyOrg` | Only users in your Microsoft 365 organization | 53 | | `AzureADMultipleOrgs` | Users in any Microsoft 365 organization (work or school accounts) | 54 | | `AzureADandPersonalMicrosoftAccount` | Users in any Microsoft 365 organization (work or school accounts) and personal Microsoft accounts | 55 | | `PersonalMicrosoftAccount` | Only personal Microsoft accounts | 56 | 57 | 1. Copy the **Client ID** and **Auth tenant** values from the script output. You will need these values in the next step. 58 | 59 | ```powershell 60 | SUCCESS 61 | Client ID: 2fb1652f-a9a0-4db9-b220-b224b8d9d38b 62 | Auth tenant: common 63 | ``` 64 | 65 | ## Configure the sample 66 | 67 | 1. Rename [.env.example](./graphtutorial/.env.example) to **.env** and update the values according to the following table. 68 | 69 | | Setting | Value | 70 | |---------|-------| 71 | | `CLIENT_ID` | The client ID of your app registration | 72 | | `TENANT_ID` | If you chose the option to only allow users in your organization to sign in, change this value to your tenant ID. Otherwise leave as `common`. | 73 | 74 | ## Run the sample 75 | 76 | In your command-line interface (CLI), navigate to the project directory and run the following commands. 77 | 78 | ```bash 79 | composer install 80 | php main.php 81 | ``` 82 | -------------------------------------------------------------------------------- /user-auth/RegisterAppForUserAuth.ps1: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT license. 3 | 4 | # 5 | param( 6 | [Parameter(Mandatory=$true, 7 | HelpMessage="The friendly name of the app registration")] 8 | [String] 9 | $AppName, 10 | 11 | [Parameter(Mandatory=$false, 12 | HelpMessage="The sign in audience for the app")] 13 | [ValidateSet("AzureADMyOrg", "AzureADMultipleOrgs", ` 14 | "AzureADandPersonalMicrosoftAccount", "PersonalMicrosoftAccount")] 15 | [String] 16 | $SignInAudience = "AzureADandPersonalMicrosoftAccount", 17 | 18 | [Parameter(Mandatory=$false)] 19 | [Switch] 20 | $StayConnected = $false 21 | ) 22 | 23 | # Tenant to use in authentication. 24 | # See https://learn.microsoft.com/azure/active-directory/develop/v2-oauth2-device-code#device-authorization-request 25 | $authTenant = switch ($SignInAudience) 26 | { 27 | "AzureADMyOrg" { "tenantId" } 28 | "AzureADMultipleOrgs" { "organizations" } 29 | "AzureADandPersonalMicrosoftAccount" { "common" } 30 | "PersonalMicrosoftAccount" { "consumers" } 31 | default { "invalid" } 32 | } 33 | 34 | if ($authTenant -eq "invalid") 35 | { 36 | Write-Host -ForegroundColor Red "Invalid sign in audience:" $SignInAudience 37 | Exit 38 | } 39 | 40 | # Requires an admin 41 | Connect-MgGraph -Scopes "Application.ReadWrite.All User.Read" -UseDeviceAuthentication -ErrorAction Stop 42 | 43 | # Get context for access to tenant ID 44 | $context = Get-MgContext -ErrorAction Stop 45 | 46 | if ($authTenant -eq "tenantId") 47 | { 48 | $authTenant = $context.TenantId 49 | } 50 | 51 | # Create app registration 52 | $appRegistration = New-MgApplication -DisplayName $AppName -SignInAudience $SignInAudience ` 53 | -IsFallbackPublicClient -ErrorAction Stop 54 | Write-Host -ForegroundColor Cyan "App registration created with app ID" $appRegistration.AppId 55 | 56 | # Create corresponding service principal 57 | if ($SignInAudience -ne "PersonalMicrosoftAccount") 58 | { 59 | New-MgServicePrincipal -AppId $appRegistration.AppId -ErrorAction SilentlyContinue ` 60 | -ErrorVariable SPError | Out-Null 61 | if ($SPError) 62 | { 63 | Write-Host -ForegroundColor Red "A service principal for the app could not be created." 64 | Write-Host -ForegroundColor Red $SPError 65 | Exit 66 | } 67 | 68 | Write-Host -ForegroundColor Cyan "Service principal created" 69 | } 70 | 71 | Write-Host 72 | Write-Host -ForegroundColor Green "SUCCESS" 73 | Write-Host -ForegroundColor Cyan -NoNewline "Client ID: " 74 | Write-Host -ForegroundColor Yellow $appRegistration.AppId 75 | Write-Host -ForegroundColor Cyan -NoNewline "Auth tenant: " 76 | Write-Host -ForegroundColor Yellow $authTenant 77 | 78 | if ($StayConnected -eq $false) 79 | { 80 | Disconnect-MgGraph | Out-Null 81 | Write-Host "Disconnected from Microsoft Graph" 82 | } 83 | else 84 | { 85 | Write-Host 86 | Write-Host -ForegroundColor Yellow ` 87 | "The connection to Microsoft Graph is still active. To disconnect, use Disconnect-MgGraph" 88 | } 89 | # 90 | -------------------------------------------------------------------------------- /user-auth/graphtutorial/.env.example: -------------------------------------------------------------------------------- 1 | CLIENT_ID=YOUR_CLIENT_ID_HERE 2 | TENANT_ID=common 3 | GRAPH_USER_SCOPES='user.read mail.read mail.send' 4 | -------------------------------------------------------------------------------- /user-auth/graphtutorial/DeviceCodeTokenProvider.php: -------------------------------------------------------------------------------- 1 | clientId = $clientId; 23 | $this->tenantId = $tenantId; 24 | $this->scopes = $scopes; 25 | $this->allowedHostsValidator = new AllowedHostsValidator(); 26 | $this->allowedHostsValidator->setAllowedHosts([ 27 | "graph.microsoft.com", 28 | "graph.microsoft.us", 29 | "dod-graph.microsoft.us", 30 | "graph.microsoft.de", 31 | "microsoftgraph.chinacloudapi.cn" 32 | ]); 33 | $this->tokenClient = new Client(); 34 | } 35 | 36 | public function getAuthorizationTokenAsync(string $url, array $additionalAuthenticationContext = []): Promise { 37 | $parsedUrl = parse_url($url); 38 | $scheme = $parsedUrl["scheme"] ?? null; 39 | 40 | if ($scheme !== 'https' || !$this->getAllowedHostsValidator()->isUrlHostValid($url)) { 41 | return new FulfilledPromise(null); 42 | } 43 | 44 | // If we already have a user token, just return it 45 | // Tokens are valid for one hour, after that it needs to be refreshed 46 | if (isset($this->accessToken)) { 47 | return new FulfilledPromise($this->accessToken); 48 | } 49 | 50 | // https://learn.microsoft.com/azure/active-directory/develop/v2-oauth2-device-code 51 | $deviceCodeRequestUrl = 'https://login.microsoftonline.com/'.$this->tenantId.'/oauth2/v2.0/devicecode'; 52 | $tokenRequestUrl = 'https://login.microsoftonline.com/'.$this->tenantId.'/oauth2/v2.0/token'; 53 | 54 | // First POST to /devicecode 55 | $deviceCodeResponse = json_decode($this->tokenClient->post($deviceCodeRequestUrl, [ 56 | 'form_params' => [ 57 | 'client_id' => $this->clientId, 58 | 'scope' => $this->scopes 59 | ] 60 | ])->getBody()->getContents()); 61 | 62 | // Display the user prompt 63 | print($deviceCodeResponse->message.PHP_EOL); 64 | 65 | // Response also indicates how often to poll for completion 66 | // And gives a device code to send in the polling requests 67 | $interval = (int)$deviceCodeResponse->interval; 68 | $device_code = $deviceCodeResponse->device_code; 69 | 70 | // Do polling - if attempt times out the token endpoint 71 | // returns an error 72 | while (true) { 73 | sleep($interval); 74 | 75 | // POST to the /token endpoint 76 | $tokenResponse = $this->tokenClient->post($tokenRequestUrl, [ 77 | 'form_params' => [ 78 | 'client_id' => $this->clientId, 79 | 'grant_type' => 'urn:ietf:params:oauth:grant-type:device_code', 80 | 'device_code' => $device_code 81 | ], 82 | // These options are needed to enable getting 83 | // the response body from a 4xx response 84 | 'http_errors' => false, 85 | 'curl' => [ 86 | CURLOPT_FAILONERROR => false 87 | ] 88 | ]); 89 | 90 | if ($tokenResponse->getStatusCode() == 200) { 91 | // Return the access_token 92 | $responseBody = json_decode($tokenResponse->getBody()->getContents()); 93 | $this->accessToken = $responseBody->access_token; 94 | return new FulfilledPromise($responseBody->access_token); 95 | } else if ($tokenResponse->getStatusCode() == 400) { 96 | // Check the error in the response body 97 | $responseBody = json_decode($tokenResponse->getBody()->getContents()); 98 | if (isset($responseBody->error)) { 99 | $error = $responseBody->error; 100 | // authorization_pending means we should keep polling 101 | if (strcmp($error, 'authorization_pending') != 0) { 102 | return new RejectedPromise( 103 | new Exception('Token endpoint returned '.$error, 100)); 104 | } 105 | } 106 | } 107 | } 108 | } 109 | 110 | public function getAllowedHostsValidator(): AllowedHostsValidator { 111 | return $this->allowedHostsValidator; 112 | } 113 | } 114 | ?> 115 | -------------------------------------------------------------------------------- /user-auth/graphtutorial/GraphHelper.php: -------------------------------------------------------------------------------- 1 | 6 | use Microsoft\Graph\Generated\Models; 7 | use Microsoft\Graph\Generated\Users\Item\MailFolders\Item\Messages\MessagesRequestBuilderGetQueryParameters; 8 | use Microsoft\Graph\Generated\Users\Item\MailFolders\Item\Messages\MessagesRequestBuilderGetRequestConfiguration; 9 | use Microsoft\Graph\Generated\Users\Item\SendMail\SendMailPostRequestBody; 10 | use Microsoft\Graph\Generated\Users\Item\UserItemRequestBuilderGetQueryParameters; 11 | use Microsoft\Graph\Generated\Users\Item\UserItemRequestBuilderGetRequestConfiguration; 12 | use Microsoft\Graph\GraphRequestAdapter; 13 | use Microsoft\Graph\GraphServiceClient; 14 | use Microsoft\Kiota\Abstractions\Authentication\BaseBearerTokenAuthenticationProvider; 15 | 16 | require_once 'DeviceCodeTokenProvider.php'; 17 | // 18 | 19 | class GraphHelper { 20 | // 21 | private static string $clientId = ''; 22 | private static string $tenantId = ''; 23 | private static string $graphUserScopes = ''; 24 | private static DeviceCodeTokenProvider $tokenProvider; 25 | private static GraphServiceClient $userClient; 26 | 27 | public static function initializeGraphForUserAuth(): void { 28 | GraphHelper::$clientId = $_ENV['CLIENT_ID']; 29 | GraphHelper::$tenantId = $_ENV['TENANT_ID']; 30 | GraphHelper::$graphUserScopes = $_ENV['GRAPH_USER_SCOPES']; 31 | 32 | GraphHelper::$tokenProvider = new DeviceCodeTokenProvider( 33 | GraphHelper::$clientId, 34 | GraphHelper::$tenantId, 35 | GraphHelper::$graphUserScopes); 36 | $authProvider = new BaseBearerTokenAuthenticationProvider(GraphHelper::$tokenProvider); 37 | $adapter = new GraphRequestAdapter($authProvider); 38 | GraphHelper::$userClient = GraphServiceClient::createWithRequestAdapter($adapter); 39 | } 40 | // 41 | 42 | // 43 | public static function getUserToken(): string { 44 | return GraphHelper::$tokenProvider 45 | ->getAuthorizationTokenAsync('https://graph.microsoft.com')->wait(); 46 | } 47 | // 48 | 49 | // 50 | public static function getUser(): Models\User { 51 | $configuration = new UserItemRequestBuilderGetRequestConfiguration(); 52 | $configuration->queryParameters = new UserItemRequestBuilderGetQueryParameters(); 53 | $configuration->queryParameters->select = ['displayName','mail','userPrincipalName']; 54 | return GraphHelper::$userClient->me()->get($configuration)->wait(); 55 | } 56 | // 57 | 58 | // 59 | public static function getInbox(): Models\MessageCollectionResponse { 60 | $configuration = new MessagesRequestBuilderGetRequestConfiguration(); 61 | $configuration->queryParameters = new MessagesRequestBuilderGetQueryParameters(); 62 | // Only request specific properties 63 | $configuration->queryParameters->select = ['from','isRead','receivedDateTime','subject']; 64 | // Sort by received time, newest first 65 | $configuration->queryParameters->orderby = ['receivedDateTime DESC']; 66 | // Get at most 25 results 67 | $configuration->queryParameters->top = 25; 68 | return GraphHelper::$userClient->me() 69 | ->mailFolders() 70 | ->byMailFolderId('inbox') 71 | ->messages() 72 | ->get($configuration)->wait(); 73 | } 74 | // 75 | 76 | // 77 | public static function sendMail(string $subject, string $body, string $recipient): void { 78 | $message = new Models\Message(); 79 | $message->setSubject($subject); 80 | 81 | $itemBody = new Models\ItemBody(); 82 | $itemBody->setContent($body); 83 | $itemBody->setContentType(new Models\BodyType(Models\BodyType::TEXT)); 84 | $message->setBody($itemBody); 85 | 86 | $email = new Models\EmailAddress(); 87 | $email->setAddress($recipient); 88 | $to = new Models\Recipient(); 89 | $to->setEmailAddress($email); 90 | $message->setToRecipients([$to]); 91 | 92 | $sendMailBody = new SendMailPostRequestBody(); 93 | $sendMailBody->setMessage($message); 94 | 95 | GraphHelper::$userClient->me()->sendMail()->post($sendMailBody)->wait(); 96 | } 97 | // 98 | 99 | // 100 | public static function makeGraphCall(): void { 101 | // INSERT YOUR CODE HERE 102 | } 103 | // 104 | } 105 | ?> 106 | -------------------------------------------------------------------------------- /user-auth/graphtutorial/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "microsoft/graphtutorial", 3 | "description": "Microsoft Graph PHP tutorial", 4 | "type": "project", 5 | "license": "MIT", 6 | "scripts": { 7 | "test": "./vendor/bin/phpstan analyse -c ./phpstan.neon --level 7 ./" 8 | }, 9 | "require": { 10 | "vlucas/phpdotenv": "^5.4", 11 | "microsoft/microsoft-graph": "^2.0.0", 12 | "php-http/guzzle7-adapter": "^1.0" 13 | }, 14 | "require-dev": { 15 | "phpstan/phpstan": "^1.10" 16 | }, 17 | "minimum-stability": "dev", 18 | "prefer-stable": true, 19 | "config": { 20 | "allow-plugins": { 21 | "php-http/discovery": true 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /user-auth/graphtutorial/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "4e46cf8f89e53a5f3ff8faf383fa9bd4", 8 | "packages": [ 9 | { 10 | "name": "brick/math", 11 | "version": "0.13.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/brick/math.git", 15 | "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", 20 | "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": "^8.1" 25 | }, 26 | "require-dev": { 27 | "php-coveralls/php-coveralls": "^2.2", 28 | "phpunit/phpunit": "^10.1", 29 | "vimeo/psalm": "6.8.8" 30 | }, 31 | "type": "library", 32 | "autoload": { 33 | "psr-4": { 34 | "Brick\\Math\\": "src/" 35 | } 36 | }, 37 | "notification-url": "https://packagist.org/downloads/", 38 | "license": [ 39 | "MIT" 40 | ], 41 | "description": "Arbitrary-precision arithmetic library", 42 | "keywords": [ 43 | "Arbitrary-precision", 44 | "BigInteger", 45 | "BigRational", 46 | "arithmetic", 47 | "bigdecimal", 48 | "bignum", 49 | "bignumber", 50 | "brick", 51 | "decimal", 52 | "integer", 53 | "math", 54 | "mathematics", 55 | "rational" 56 | ], 57 | "support": { 58 | "issues": "https://github.com/brick/math/issues", 59 | "source": "https://github.com/brick/math/tree/0.13.1" 60 | }, 61 | "funding": [ 62 | { 63 | "url": "https://github.com/BenMorel", 64 | "type": "github" 65 | } 66 | ], 67 | "time": "2025-03-29T13:50:30+00:00" 68 | }, 69 | { 70 | "name": "composer/semver", 71 | "version": "3.4.3", 72 | "source": { 73 | "type": "git", 74 | "url": "https://github.com/composer/semver.git", 75 | "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" 76 | }, 77 | "dist": { 78 | "type": "zip", 79 | "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", 80 | "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", 81 | "shasum": "" 82 | }, 83 | "require": { 84 | "php": "^5.3.2 || ^7.0 || ^8.0" 85 | }, 86 | "require-dev": { 87 | "phpstan/phpstan": "^1.11", 88 | "symfony/phpunit-bridge": "^3 || ^7" 89 | }, 90 | "type": "library", 91 | "extra": { 92 | "branch-alias": { 93 | "dev-main": "3.x-dev" 94 | } 95 | }, 96 | "autoload": { 97 | "psr-4": { 98 | "Composer\\Semver\\": "src" 99 | } 100 | }, 101 | "notification-url": "https://packagist.org/downloads/", 102 | "license": [ 103 | "MIT" 104 | ], 105 | "authors": [ 106 | { 107 | "name": "Nils Adermann", 108 | "email": "naderman@naderman.de", 109 | "homepage": "http://www.naderman.de" 110 | }, 111 | { 112 | "name": "Jordi Boggiano", 113 | "email": "j.boggiano@seld.be", 114 | "homepage": "http://seld.be" 115 | }, 116 | { 117 | "name": "Rob Bast", 118 | "email": "rob.bast@gmail.com", 119 | "homepage": "http://robbast.nl" 120 | } 121 | ], 122 | "description": "Semver library that offers utilities, version constraint parsing and validation.", 123 | "keywords": [ 124 | "semantic", 125 | "semver", 126 | "validation", 127 | "versioning" 128 | ], 129 | "support": { 130 | "irc": "ircs://irc.libera.chat:6697/composer", 131 | "issues": "https://github.com/composer/semver/issues", 132 | "source": "https://github.com/composer/semver/tree/3.4.3" 133 | }, 134 | "funding": [ 135 | { 136 | "url": "https://packagist.com", 137 | "type": "custom" 138 | }, 139 | { 140 | "url": "https://github.com/composer", 141 | "type": "github" 142 | }, 143 | { 144 | "url": "https://tidelift.com/funding/github/packagist/composer/composer", 145 | "type": "tidelift" 146 | } 147 | ], 148 | "time": "2024-09-19T14:15:21+00:00" 149 | }, 150 | { 151 | "name": "doctrine/annotations", 152 | "version": "2.0.2", 153 | "source": { 154 | "type": "git", 155 | "url": "https://github.com/doctrine/annotations.git", 156 | "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7" 157 | }, 158 | "dist": { 159 | "type": "zip", 160 | "url": "https://api.github.com/repos/doctrine/annotations/zipball/901c2ee5d26eb64ff43c47976e114bf00843acf7", 161 | "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7", 162 | "shasum": "" 163 | }, 164 | "require": { 165 | "doctrine/lexer": "^2 || ^3", 166 | "ext-tokenizer": "*", 167 | "php": "^7.2 || ^8.0", 168 | "psr/cache": "^1 || ^2 || ^3" 169 | }, 170 | "require-dev": { 171 | "doctrine/cache": "^2.0", 172 | "doctrine/coding-standard": "^10", 173 | "phpstan/phpstan": "^1.10.28", 174 | "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", 175 | "symfony/cache": "^5.4 || ^6.4 || ^7", 176 | "vimeo/psalm": "^4.30 || ^5.14" 177 | }, 178 | "suggest": { 179 | "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" 180 | }, 181 | "type": "library", 182 | "autoload": { 183 | "psr-4": { 184 | "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" 185 | } 186 | }, 187 | "notification-url": "https://packagist.org/downloads/", 188 | "license": [ 189 | "MIT" 190 | ], 191 | "authors": [ 192 | { 193 | "name": "Guilherme Blanco", 194 | "email": "guilhermeblanco@gmail.com" 195 | }, 196 | { 197 | "name": "Roman Borschel", 198 | "email": "roman@code-factory.org" 199 | }, 200 | { 201 | "name": "Benjamin Eberlei", 202 | "email": "kontakt@beberlei.de" 203 | }, 204 | { 205 | "name": "Jonathan Wage", 206 | "email": "jonwage@gmail.com" 207 | }, 208 | { 209 | "name": "Johannes Schmitt", 210 | "email": "schmittjoh@gmail.com" 211 | } 212 | ], 213 | "description": "Docblock Annotations Parser", 214 | "homepage": "https://www.doctrine-project.org/projects/annotations.html", 215 | "keywords": [ 216 | "annotations", 217 | "docblock", 218 | "parser" 219 | ], 220 | "support": { 221 | "issues": "https://github.com/doctrine/annotations/issues", 222 | "source": "https://github.com/doctrine/annotations/tree/2.0.2" 223 | }, 224 | "time": "2024-09-05T10:17:24+00:00" 225 | }, 226 | { 227 | "name": "doctrine/lexer", 228 | "version": "3.0.1", 229 | "source": { 230 | "type": "git", 231 | "url": "https://github.com/doctrine/lexer.git", 232 | "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" 233 | }, 234 | "dist": { 235 | "type": "zip", 236 | "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", 237 | "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", 238 | "shasum": "" 239 | }, 240 | "require": { 241 | "php": "^8.1" 242 | }, 243 | "require-dev": { 244 | "doctrine/coding-standard": "^12", 245 | "phpstan/phpstan": "^1.10", 246 | "phpunit/phpunit": "^10.5", 247 | "psalm/plugin-phpunit": "^0.18.3", 248 | "vimeo/psalm": "^5.21" 249 | }, 250 | "type": "library", 251 | "autoload": { 252 | "psr-4": { 253 | "Doctrine\\Common\\Lexer\\": "src" 254 | } 255 | }, 256 | "notification-url": "https://packagist.org/downloads/", 257 | "license": [ 258 | "MIT" 259 | ], 260 | "authors": [ 261 | { 262 | "name": "Guilherme Blanco", 263 | "email": "guilhermeblanco@gmail.com" 264 | }, 265 | { 266 | "name": "Roman Borschel", 267 | "email": "roman@code-factory.org" 268 | }, 269 | { 270 | "name": "Johannes Schmitt", 271 | "email": "schmittjoh@gmail.com" 272 | } 273 | ], 274 | "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", 275 | "homepage": "https://www.doctrine-project.org/projects/lexer.html", 276 | "keywords": [ 277 | "annotations", 278 | "docblock", 279 | "lexer", 280 | "parser", 281 | "php" 282 | ], 283 | "support": { 284 | "issues": "https://github.com/doctrine/lexer/issues", 285 | "source": "https://github.com/doctrine/lexer/tree/3.0.1" 286 | }, 287 | "funding": [ 288 | { 289 | "url": "https://www.doctrine-project.org/sponsorship.html", 290 | "type": "custom" 291 | }, 292 | { 293 | "url": "https://www.patreon.com/phpdoctrine", 294 | "type": "patreon" 295 | }, 296 | { 297 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", 298 | "type": "tidelift" 299 | } 300 | ], 301 | "time": "2024-02-05T11:56:58+00:00" 302 | }, 303 | { 304 | "name": "firebase/php-jwt", 305 | "version": "v6.11.1", 306 | "source": { 307 | "type": "git", 308 | "url": "https://github.com/firebase/php-jwt.git", 309 | "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66" 310 | }, 311 | "dist": { 312 | "type": "zip", 313 | "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", 314 | "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", 315 | "shasum": "" 316 | }, 317 | "require": { 318 | "php": "^8.0" 319 | }, 320 | "require-dev": { 321 | "guzzlehttp/guzzle": "^7.4", 322 | "phpspec/prophecy-phpunit": "^2.0", 323 | "phpunit/phpunit": "^9.5", 324 | "psr/cache": "^2.0||^3.0", 325 | "psr/http-client": "^1.0", 326 | "psr/http-factory": "^1.0" 327 | }, 328 | "suggest": { 329 | "ext-sodium": "Support EdDSA (Ed25519) signatures", 330 | "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" 331 | }, 332 | "type": "library", 333 | "autoload": { 334 | "psr-4": { 335 | "Firebase\\JWT\\": "src" 336 | } 337 | }, 338 | "notification-url": "https://packagist.org/downloads/", 339 | "license": [ 340 | "BSD-3-Clause" 341 | ], 342 | "authors": [ 343 | { 344 | "name": "Neuman Vong", 345 | "email": "neuman+pear@twilio.com", 346 | "role": "Developer" 347 | }, 348 | { 349 | "name": "Anant Narayanan", 350 | "email": "anant@php.net", 351 | "role": "Developer" 352 | } 353 | ], 354 | "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", 355 | "homepage": "https://github.com/firebase/php-jwt", 356 | "keywords": [ 357 | "jwt", 358 | "php" 359 | ], 360 | "support": { 361 | "issues": "https://github.com/firebase/php-jwt/issues", 362 | "source": "https://github.com/firebase/php-jwt/tree/v6.11.1" 363 | }, 364 | "time": "2025-04-09T20:32:01+00:00" 365 | }, 366 | { 367 | "name": "graham-campbell/result-type", 368 | "version": "v1.1.3", 369 | "source": { 370 | "type": "git", 371 | "url": "https://github.com/GrahamCampbell/Result-Type.git", 372 | "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" 373 | }, 374 | "dist": { 375 | "type": "zip", 376 | "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", 377 | "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", 378 | "shasum": "" 379 | }, 380 | "require": { 381 | "php": "^7.2.5 || ^8.0", 382 | "phpoption/phpoption": "^1.9.3" 383 | }, 384 | "require-dev": { 385 | "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" 386 | }, 387 | "type": "library", 388 | "autoload": { 389 | "psr-4": { 390 | "GrahamCampbell\\ResultType\\": "src/" 391 | } 392 | }, 393 | "notification-url": "https://packagist.org/downloads/", 394 | "license": [ 395 | "MIT" 396 | ], 397 | "authors": [ 398 | { 399 | "name": "Graham Campbell", 400 | "email": "hello@gjcampbell.co.uk", 401 | "homepage": "https://github.com/GrahamCampbell" 402 | } 403 | ], 404 | "description": "An Implementation Of The Result Type", 405 | "keywords": [ 406 | "Graham Campbell", 407 | "GrahamCampbell", 408 | "Result Type", 409 | "Result-Type", 410 | "result" 411 | ], 412 | "support": { 413 | "issues": "https://github.com/GrahamCampbell/Result-Type/issues", 414 | "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" 415 | }, 416 | "funding": [ 417 | { 418 | "url": "https://github.com/GrahamCampbell", 419 | "type": "github" 420 | }, 421 | { 422 | "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", 423 | "type": "tidelift" 424 | } 425 | ], 426 | "time": "2024-07-20T21:45:45+00:00" 427 | }, 428 | { 429 | "name": "guzzlehttp/guzzle", 430 | "version": "7.9.3", 431 | "source": { 432 | "type": "git", 433 | "url": "https://github.com/guzzle/guzzle.git", 434 | "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" 435 | }, 436 | "dist": { 437 | "type": "zip", 438 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", 439 | "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", 440 | "shasum": "" 441 | }, 442 | "require": { 443 | "ext-json": "*", 444 | "guzzlehttp/promises": "^1.5.3 || ^2.0.3", 445 | "guzzlehttp/psr7": "^2.7.0", 446 | "php": "^7.2.5 || ^8.0", 447 | "psr/http-client": "^1.0", 448 | "symfony/deprecation-contracts": "^2.2 || ^3.0" 449 | }, 450 | "provide": { 451 | "psr/http-client-implementation": "1.0" 452 | }, 453 | "require-dev": { 454 | "bamarni/composer-bin-plugin": "^1.8.2", 455 | "ext-curl": "*", 456 | "guzzle/client-integration-tests": "3.0.2", 457 | "php-http/message-factory": "^1.1", 458 | "phpunit/phpunit": "^8.5.39 || ^9.6.20", 459 | "psr/log": "^1.1 || ^2.0 || ^3.0" 460 | }, 461 | "suggest": { 462 | "ext-curl": "Required for CURL handler support", 463 | "ext-intl": "Required for Internationalized Domain Name (IDN) support", 464 | "psr/log": "Required for using the Log middleware" 465 | }, 466 | "type": "library", 467 | "extra": { 468 | "bamarni-bin": { 469 | "bin-links": true, 470 | "forward-command": false 471 | } 472 | }, 473 | "autoload": { 474 | "files": [ 475 | "src/functions_include.php" 476 | ], 477 | "psr-4": { 478 | "GuzzleHttp\\": "src/" 479 | } 480 | }, 481 | "notification-url": "https://packagist.org/downloads/", 482 | "license": [ 483 | "MIT" 484 | ], 485 | "authors": [ 486 | { 487 | "name": "Graham Campbell", 488 | "email": "hello@gjcampbell.co.uk", 489 | "homepage": "https://github.com/GrahamCampbell" 490 | }, 491 | { 492 | "name": "Michael Dowling", 493 | "email": "mtdowling@gmail.com", 494 | "homepage": "https://github.com/mtdowling" 495 | }, 496 | { 497 | "name": "Jeremy Lindblom", 498 | "email": "jeremeamia@gmail.com", 499 | "homepage": "https://github.com/jeremeamia" 500 | }, 501 | { 502 | "name": "George Mponos", 503 | "email": "gmponos@gmail.com", 504 | "homepage": "https://github.com/gmponos" 505 | }, 506 | { 507 | "name": "Tobias Nyholm", 508 | "email": "tobias.nyholm@gmail.com", 509 | "homepage": "https://github.com/Nyholm" 510 | }, 511 | { 512 | "name": "Márk Sági-Kazár", 513 | "email": "mark.sagikazar@gmail.com", 514 | "homepage": "https://github.com/sagikazarmark" 515 | }, 516 | { 517 | "name": "Tobias Schultze", 518 | "email": "webmaster@tubo-world.de", 519 | "homepage": "https://github.com/Tobion" 520 | } 521 | ], 522 | "description": "Guzzle is a PHP HTTP client library", 523 | "keywords": [ 524 | "client", 525 | "curl", 526 | "framework", 527 | "http", 528 | "http client", 529 | "psr-18", 530 | "psr-7", 531 | "rest", 532 | "web service" 533 | ], 534 | "support": { 535 | "issues": "https://github.com/guzzle/guzzle/issues", 536 | "source": "https://github.com/guzzle/guzzle/tree/7.9.3" 537 | }, 538 | "funding": [ 539 | { 540 | "url": "https://github.com/GrahamCampbell", 541 | "type": "github" 542 | }, 543 | { 544 | "url": "https://github.com/Nyholm", 545 | "type": "github" 546 | }, 547 | { 548 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", 549 | "type": "tidelift" 550 | } 551 | ], 552 | "time": "2025-03-27T13:37:11+00:00" 553 | }, 554 | { 555 | "name": "guzzlehttp/promises", 556 | "version": "2.2.0", 557 | "source": { 558 | "type": "git", 559 | "url": "https://github.com/guzzle/promises.git", 560 | "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" 561 | }, 562 | "dist": { 563 | "type": "zip", 564 | "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", 565 | "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", 566 | "shasum": "" 567 | }, 568 | "require": { 569 | "php": "^7.2.5 || ^8.0" 570 | }, 571 | "require-dev": { 572 | "bamarni/composer-bin-plugin": "^1.8.2", 573 | "phpunit/phpunit": "^8.5.39 || ^9.6.20" 574 | }, 575 | "type": "library", 576 | "extra": { 577 | "bamarni-bin": { 578 | "bin-links": true, 579 | "forward-command": false 580 | } 581 | }, 582 | "autoload": { 583 | "psr-4": { 584 | "GuzzleHttp\\Promise\\": "src/" 585 | } 586 | }, 587 | "notification-url": "https://packagist.org/downloads/", 588 | "license": [ 589 | "MIT" 590 | ], 591 | "authors": [ 592 | { 593 | "name": "Graham Campbell", 594 | "email": "hello@gjcampbell.co.uk", 595 | "homepage": "https://github.com/GrahamCampbell" 596 | }, 597 | { 598 | "name": "Michael Dowling", 599 | "email": "mtdowling@gmail.com", 600 | "homepage": "https://github.com/mtdowling" 601 | }, 602 | { 603 | "name": "Tobias Nyholm", 604 | "email": "tobias.nyholm@gmail.com", 605 | "homepage": "https://github.com/Nyholm" 606 | }, 607 | { 608 | "name": "Tobias Schultze", 609 | "email": "webmaster@tubo-world.de", 610 | "homepage": "https://github.com/Tobion" 611 | } 612 | ], 613 | "description": "Guzzle promises library", 614 | "keywords": [ 615 | "promise" 616 | ], 617 | "support": { 618 | "issues": "https://github.com/guzzle/promises/issues", 619 | "source": "https://github.com/guzzle/promises/tree/2.2.0" 620 | }, 621 | "funding": [ 622 | { 623 | "url": "https://github.com/GrahamCampbell", 624 | "type": "github" 625 | }, 626 | { 627 | "url": "https://github.com/Nyholm", 628 | "type": "github" 629 | }, 630 | { 631 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", 632 | "type": "tidelift" 633 | } 634 | ], 635 | "time": "2025-03-27T13:27:01+00:00" 636 | }, 637 | { 638 | "name": "guzzlehttp/psr7", 639 | "version": "2.7.1", 640 | "source": { 641 | "type": "git", 642 | "url": "https://github.com/guzzle/psr7.git", 643 | "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" 644 | }, 645 | "dist": { 646 | "type": "zip", 647 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", 648 | "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", 649 | "shasum": "" 650 | }, 651 | "require": { 652 | "php": "^7.2.5 || ^8.0", 653 | "psr/http-factory": "^1.0", 654 | "psr/http-message": "^1.1 || ^2.0", 655 | "ralouphie/getallheaders": "^3.0" 656 | }, 657 | "provide": { 658 | "psr/http-factory-implementation": "1.0", 659 | "psr/http-message-implementation": "1.0" 660 | }, 661 | "require-dev": { 662 | "bamarni/composer-bin-plugin": "^1.8.2", 663 | "http-interop/http-factory-tests": "0.9.0", 664 | "phpunit/phpunit": "^8.5.39 || ^9.6.20" 665 | }, 666 | "suggest": { 667 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" 668 | }, 669 | "type": "library", 670 | "extra": { 671 | "bamarni-bin": { 672 | "bin-links": true, 673 | "forward-command": false 674 | } 675 | }, 676 | "autoload": { 677 | "psr-4": { 678 | "GuzzleHttp\\Psr7\\": "src/" 679 | } 680 | }, 681 | "notification-url": "https://packagist.org/downloads/", 682 | "license": [ 683 | "MIT" 684 | ], 685 | "authors": [ 686 | { 687 | "name": "Graham Campbell", 688 | "email": "hello@gjcampbell.co.uk", 689 | "homepage": "https://github.com/GrahamCampbell" 690 | }, 691 | { 692 | "name": "Michael Dowling", 693 | "email": "mtdowling@gmail.com", 694 | "homepage": "https://github.com/mtdowling" 695 | }, 696 | { 697 | "name": "George Mponos", 698 | "email": "gmponos@gmail.com", 699 | "homepage": "https://github.com/gmponos" 700 | }, 701 | { 702 | "name": "Tobias Nyholm", 703 | "email": "tobias.nyholm@gmail.com", 704 | "homepage": "https://github.com/Nyholm" 705 | }, 706 | { 707 | "name": "Márk Sági-Kazár", 708 | "email": "mark.sagikazar@gmail.com", 709 | "homepage": "https://github.com/sagikazarmark" 710 | }, 711 | { 712 | "name": "Tobias Schultze", 713 | "email": "webmaster@tubo-world.de", 714 | "homepage": "https://github.com/Tobion" 715 | }, 716 | { 717 | "name": "Márk Sági-Kazár", 718 | "email": "mark.sagikazar@gmail.com", 719 | "homepage": "https://sagikazarmark.hu" 720 | } 721 | ], 722 | "description": "PSR-7 message implementation that also provides common utility methods", 723 | "keywords": [ 724 | "http", 725 | "message", 726 | "psr-7", 727 | "request", 728 | "response", 729 | "stream", 730 | "uri", 731 | "url" 732 | ], 733 | "support": { 734 | "issues": "https://github.com/guzzle/psr7/issues", 735 | "source": "https://github.com/guzzle/psr7/tree/2.7.1" 736 | }, 737 | "funding": [ 738 | { 739 | "url": "https://github.com/GrahamCampbell", 740 | "type": "github" 741 | }, 742 | { 743 | "url": "https://github.com/Nyholm", 744 | "type": "github" 745 | }, 746 | { 747 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", 748 | "type": "tidelift" 749 | } 750 | ], 751 | "time": "2025-03-27T12:30:47+00:00" 752 | }, 753 | { 754 | "name": "league/oauth2-client", 755 | "version": "2.8.1", 756 | "source": { 757 | "type": "git", 758 | "url": "https://github.com/thephpleague/oauth2-client.git", 759 | "reference": "9df2924ca644736c835fc60466a3a60390d334f9" 760 | }, 761 | "dist": { 762 | "type": "zip", 763 | "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/9df2924ca644736c835fc60466a3a60390d334f9", 764 | "reference": "9df2924ca644736c835fc60466a3a60390d334f9", 765 | "shasum": "" 766 | }, 767 | "require": { 768 | "ext-json": "*", 769 | "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", 770 | "php": "^7.1 || >=8.0.0 <8.5.0" 771 | }, 772 | "require-dev": { 773 | "mockery/mockery": "^1.3.5", 774 | "php-parallel-lint/php-parallel-lint": "^1.4", 775 | "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", 776 | "squizlabs/php_codesniffer": "^3.11" 777 | }, 778 | "type": "library", 779 | "autoload": { 780 | "psr-4": { 781 | "League\\OAuth2\\Client\\": "src/" 782 | } 783 | }, 784 | "notification-url": "https://packagist.org/downloads/", 785 | "license": [ 786 | "MIT" 787 | ], 788 | "authors": [ 789 | { 790 | "name": "Alex Bilbie", 791 | "email": "hello@alexbilbie.com", 792 | "homepage": "http://www.alexbilbie.com", 793 | "role": "Developer" 794 | }, 795 | { 796 | "name": "Woody Gilk", 797 | "homepage": "https://github.com/shadowhand", 798 | "role": "Contributor" 799 | } 800 | ], 801 | "description": "OAuth 2.0 Client Library", 802 | "keywords": [ 803 | "Authentication", 804 | "SSO", 805 | "authorization", 806 | "identity", 807 | "idp", 808 | "oauth", 809 | "oauth2", 810 | "single sign on" 811 | ], 812 | "support": { 813 | "issues": "https://github.com/thephpleague/oauth2-client/issues", 814 | "source": "https://github.com/thephpleague/oauth2-client/tree/2.8.1" 815 | }, 816 | "time": "2025-02-26T04:37:30+00:00" 817 | }, 818 | { 819 | "name": "microsoft/kiota-abstractions", 820 | "version": "1.5.0", 821 | "source": { 822 | "type": "git", 823 | "url": "https://github.com/microsoft/kiota-abstractions-php.git", 824 | "reference": "53beaf41d810cd757a89f55152aa686aa74565bb" 825 | }, 826 | "dist": { 827 | "type": "zip", 828 | "url": "https://api.github.com/repos/microsoft/kiota-abstractions-php/zipball/53beaf41d810cd757a89f55152aa686aa74565bb", 829 | "reference": "53beaf41d810cd757a89f55152aa686aa74565bb", 830 | "shasum": "" 831 | }, 832 | "require": { 833 | "doctrine/annotations": "^1.13 || ^2.0", 834 | "open-telemetry/sdk": "^1.0.0", 835 | "php": "^7.4 || ^8.0", 836 | "php-http/promise": "~1.2.0", 837 | "psr/http-message": "^1.1 || ^2.0", 838 | "ramsey/uuid": "^4.2.3", 839 | "stduritemplate/stduritemplate": "^0.0.53 || ^0.0.54 || ^0.0.55 || ^0.0.56 || ^0.0.57 || ^0.0.59 || ^1.0.0 || ^2.0.0" 840 | }, 841 | "require-dev": { 842 | "phpstan/phpstan": "^1.12.16", 843 | "phpunit/phpunit": "^9.6.22" 844 | }, 845 | "type": "library", 846 | "autoload": { 847 | "psr-4": { 848 | "Microsoft\\Kiota\\Abstractions\\": "src/" 849 | } 850 | }, 851 | "notification-url": "https://packagist.org/downloads/", 852 | "license": [ 853 | "MIT" 854 | ], 855 | "authors": [ 856 | { 857 | "name": "Microsoft Graph Client Tooling", 858 | "email": "graphtooling@service.microsoft.com", 859 | "role": "Developer" 860 | } 861 | ], 862 | "description": "Abstractions for Kiota", 863 | "support": { 864 | "source": "https://github.com/microsoft/kiota-abstractions-php/tree/1.5.0" 865 | }, 866 | "time": "2025-02-17T16:44:43+00:00" 867 | }, 868 | { 869 | "name": "microsoft/kiota-authentication-phpleague", 870 | "version": "1.5.0", 871 | "source": { 872 | "type": "git", 873 | "url": "https://github.com/microsoft/kiota-authentication-phpleague-php.git", 874 | "reference": "2d8e1e200ead2d883f494d767d6a0a57eff62a8b" 875 | }, 876 | "dist": { 877 | "type": "zip", 878 | "url": "https://api.github.com/repos/microsoft/kiota-authentication-phpleague-php/zipball/2d8e1e200ead2d883f494d767d6a0a57eff62a8b", 879 | "reference": "2d8e1e200ead2d883f494d767d6a0a57eff62a8b", 880 | "shasum": "" 881 | }, 882 | "require": { 883 | "ext-json": "*", 884 | "ext-openssl": "*", 885 | "firebase/php-jwt": "^v6.0.0", 886 | "league/oauth2-client": "^2.6.1", 887 | "microsoft/kiota-abstractions": "^1.5.0", 888 | "php": "^7.4 || ^8.0", 889 | "ramsey/uuid": "^4.2.3" 890 | }, 891 | "require-dev": { 892 | "phpstan/phpstan": "^1.12.16", 893 | "phpunit/phpunit": "^9.6.22" 894 | }, 895 | "type": "library", 896 | "autoload": { 897 | "psr-4": { 898 | "Microsoft\\Kiota\\Authentication\\": "src/" 899 | } 900 | }, 901 | "notification-url": "https://packagist.org/downloads/", 902 | "license": [ 903 | "MIT" 904 | ], 905 | "authors": [ 906 | { 907 | "name": "Microsoft Graph Client Tooling", 908 | "email": "graphtooling@service.microsoft.com" 909 | } 910 | ], 911 | "description": "Authentication provider for Kiota using the PHP League OAuth 2.0 client to authenticate against the Microsoft Identity platform", 912 | "support": { 913 | "source": "https://github.com/microsoft/kiota-authentication-phpleague-php/tree/1.5.0" 914 | }, 915 | "time": "2025-02-19T06:24:55+00:00" 916 | }, 917 | { 918 | "name": "microsoft/kiota-http-guzzle", 919 | "version": "1.5.0", 920 | "source": { 921 | "type": "git", 922 | "url": "https://github.com/microsoft/kiota-http-guzzle-php.git", 923 | "reference": "4a9c4b69819712af5c62c2b978a0123ecf8f1208" 924 | }, 925 | "dist": { 926 | "type": "zip", 927 | "url": "https://api.github.com/repos/microsoft/kiota-http-guzzle-php/zipball/4a9c4b69819712af5c62c2b978a0123ecf8f1208", 928 | "reference": "4a9c4b69819712af5c62c2b978a0123ecf8f1208", 929 | "shasum": "" 930 | }, 931 | "require": { 932 | "ext-json": "*", 933 | "ext-zlib": "*", 934 | "guzzlehttp/guzzle": "^7.4.5", 935 | "microsoft/kiota-abstractions": "^1.5.0", 936 | "php": "^7.4 || ^8.0" 937 | }, 938 | "require-dev": { 939 | "phpstan/phpstan": "^1.12.16", 940 | "phpunit/phpunit": "^9.6.22" 941 | }, 942 | "type": "library", 943 | "autoload": { 944 | "psr-4": { 945 | "Microsoft\\Kiota\\Http\\": "src/" 946 | } 947 | }, 948 | "notification-url": "https://packagist.org/downloads/", 949 | "license": [ 950 | "MIT" 951 | ], 952 | "authors": [ 953 | { 954 | "name": "Microsoft Graph Client Tooling", 955 | "email": "graphtooling@service.microsoft.com" 956 | } 957 | ], 958 | "description": "Kiota HTTP Request Adapter implementation", 959 | "support": { 960 | "source": "https://github.com/microsoft/kiota-http-guzzle-php/tree/1.5.0" 961 | }, 962 | "time": "2025-02-19T06:27:54+00:00" 963 | }, 964 | { 965 | "name": "microsoft/kiota-serialization-form", 966 | "version": "1.5.0", 967 | "source": { 968 | "type": "git", 969 | "url": "https://github.com/microsoft/kiota-serialization-form-php.git", 970 | "reference": "d26a199a2a5ca5cae3654a6106ff4f9560809277" 971 | }, 972 | "dist": { 973 | "type": "zip", 974 | "url": "https://api.github.com/repos/microsoft/kiota-serialization-form-php/zipball/d26a199a2a5ca5cae3654a6106ff4f9560809277", 975 | "reference": "d26a199a2a5ca5cae3654a6106ff4f9560809277", 976 | "shasum": "" 977 | }, 978 | "require": { 979 | "ext-json": "*", 980 | "guzzlehttp/psr7": "^1.6 || ^2", 981 | "microsoft/kiota-abstractions": "^1.5.0", 982 | "php": "^7.4 || ^8.0" 983 | }, 984 | "require-dev": { 985 | "phpstan/phpstan": "^1.12.16", 986 | "phpunit/phpunit": "^9.6.22", 987 | "roave/security-advisories": "dev-latest" 988 | }, 989 | "type": "library", 990 | "autoload": { 991 | "psr-4": { 992 | "Microsoft\\Kiota\\Serialization\\Form\\": "src" 993 | } 994 | }, 995 | "notification-url": "https://packagist.org/downloads/", 996 | "license": [ 997 | "MIT" 998 | ], 999 | "authors": [ 1000 | { 1001 | "name": "Microsoft Graph Client Tooling", 1002 | "email": "graphtooling@service.microsoft.com", 1003 | "role": "Developer" 1004 | } 1005 | ], 1006 | "description": "Form implementation of Kiota abstractions serialization.", 1007 | "support": { 1008 | "source": "https://github.com/microsoft/kiota-serialization-form-php/tree/1.5.0" 1009 | }, 1010 | "time": "2025-02-19T06:29:35+00:00" 1011 | }, 1012 | { 1013 | "name": "microsoft/kiota-serialization-json", 1014 | "version": "1.5.0", 1015 | "source": { 1016 | "type": "git", 1017 | "url": "https://github.com/microsoft/kiota-serialization-json-php.git", 1018 | "reference": "ec99e2c22c5229b1b39f5957abcb430f28cc448c" 1019 | }, 1020 | "dist": { 1021 | "type": "zip", 1022 | "url": "https://api.github.com/repos/microsoft/kiota-serialization-json-php/zipball/ec99e2c22c5229b1b39f5957abcb430f28cc448c", 1023 | "reference": "ec99e2c22c5229b1b39f5957abcb430f28cc448c", 1024 | "shasum": "" 1025 | }, 1026 | "require": { 1027 | "ext-json": "*", 1028 | "guzzlehttp/psr7": "^1.6 || ^2", 1029 | "microsoft/kiota-abstractions": "^1.5.0", 1030 | "php": "^7.4 || ^8.0" 1031 | }, 1032 | "require-dev": { 1033 | "phpstan/phpstan": "^1.12.16", 1034 | "phpunit/phpunit": "^9.6.22", 1035 | "roave/security-advisories": "dev-latest" 1036 | }, 1037 | "type": "library", 1038 | "autoload": { 1039 | "psr-4": { 1040 | "Microsoft\\Kiota\\Serialization\\Json\\": "src" 1041 | } 1042 | }, 1043 | "notification-url": "https://packagist.org/downloads/", 1044 | "license": [ 1045 | "MIT" 1046 | ], 1047 | "authors": [ 1048 | { 1049 | "name": "Microsoft Graph Client Tooling", 1050 | "email": "graphtooling@service.microsoft.com", 1051 | "role": "Developer" 1052 | } 1053 | ], 1054 | "description": "Implementation of Kiota serialization abstractions using Json.", 1055 | "support": { 1056 | "source": "https://github.com/microsoft/kiota-serialization-json-php/tree/1.5.0" 1057 | }, 1058 | "time": "2025-02-19T06:28:58+00:00" 1059 | }, 1060 | { 1061 | "name": "microsoft/kiota-serialization-multipart", 1062 | "version": "1.5.0", 1063 | "source": { 1064 | "type": "git", 1065 | "url": "https://github.com/microsoft/kiota-serialization-multipart-php.git", 1066 | "reference": "6668768223cf0760a5cfab76232883eae85e7c15" 1067 | }, 1068 | "dist": { 1069 | "type": "zip", 1070 | "url": "https://api.github.com/repos/microsoft/kiota-serialization-multipart-php/zipball/6668768223cf0760a5cfab76232883eae85e7c15", 1071 | "reference": "6668768223cf0760a5cfab76232883eae85e7c15", 1072 | "shasum": "" 1073 | }, 1074 | "require": { 1075 | "ext-json": "*", 1076 | "guzzlehttp/psr7": "^1.6 || ^2", 1077 | "microsoft/kiota-abstractions": "^1.5.0", 1078 | "php": "^7.4 || ^8.0" 1079 | }, 1080 | "require-dev": { 1081 | "phpstan/phpstan": "^1.12.16", 1082 | "phpunit/phpunit": "^9.6.22", 1083 | "roave/security-advisories": "dev-latest" 1084 | }, 1085 | "type": "library", 1086 | "autoload": { 1087 | "psr-4": { 1088 | "Microsoft\\Kiota\\Serialization\\Multipart\\": "src" 1089 | } 1090 | }, 1091 | "notification-url": "https://packagist.org/downloads/", 1092 | "license": [ 1093 | "MIT" 1094 | ], 1095 | "authors": [ 1096 | { 1097 | "name": "Microsoft Graph Client Tooling", 1098 | "email": "graphtooling@service.microsoft.com", 1099 | "role": "Developer" 1100 | } 1101 | ], 1102 | "description": "Multipart implementation of Kiota abstractions serialization.", 1103 | "support": { 1104 | "source": "https://github.com/microsoft/kiota-serialization-multipart-php/tree/1.5.0" 1105 | }, 1106 | "time": "2025-02-19T06:29:47+00:00" 1107 | }, 1108 | { 1109 | "name": "microsoft/kiota-serialization-text", 1110 | "version": "1.5.0", 1111 | "source": { 1112 | "type": "git", 1113 | "url": "https://github.com/microsoft/kiota-serialization-text-php.git", 1114 | "reference": "341ae866e50341f63f1b0320cb6c08582ae6709a" 1115 | }, 1116 | "dist": { 1117 | "type": "zip", 1118 | "url": "https://api.github.com/repos/microsoft/kiota-serialization-text-php/zipball/341ae866e50341f63f1b0320cb6c08582ae6709a", 1119 | "reference": "341ae866e50341f63f1b0320cb6c08582ae6709a", 1120 | "shasum": "" 1121 | }, 1122 | "require": { 1123 | "guzzlehttp/psr7": "^1.6 || ^2", 1124 | "microsoft/kiota-abstractions": "^1.5.0", 1125 | "php": "^7.4 || ^8.0" 1126 | }, 1127 | "require-dev": { 1128 | "phpstan/phpstan": "^1.12.16", 1129 | "phpunit/phpunit": "^9.6.22" 1130 | }, 1131 | "type": "library", 1132 | "autoload": { 1133 | "psr-4": { 1134 | "Microsoft\\Kiota\\Serialization\\Text\\": "src/" 1135 | } 1136 | }, 1137 | "notification-url": "https://packagist.org/downloads/", 1138 | "license": [ 1139 | "MIT" 1140 | ], 1141 | "authors": [ 1142 | { 1143 | "name": "Microsoft Graph Client Tooling", 1144 | "email": "graphtooling@service.microsoft.com" 1145 | } 1146 | ], 1147 | "description": "Implementation of Serialization Abstractions for text/plain content", 1148 | "support": { 1149 | "source": "https://github.com/microsoft/kiota-serialization-text-php/tree/1.5.0" 1150 | }, 1151 | "time": "2025-02-19T06:29:21+00:00" 1152 | }, 1153 | { 1154 | "name": "microsoft/microsoft-graph", 1155 | "version": "v2.36.0", 1156 | "source": { 1157 | "type": "git", 1158 | "url": "https://github.com/microsoftgraph/msgraph-sdk-php.git", 1159 | "reference": "744bcbd446ea64434f1f075500668d8c5b626320" 1160 | }, 1161 | "dist": { 1162 | "type": "zip", 1163 | "url": "https://api.github.com/repos/microsoftgraph/msgraph-sdk-php/zipball/744bcbd446ea64434f1f075500668d8c5b626320", 1164 | "reference": "744bcbd446ea64434f1f075500668d8c5b626320", 1165 | "shasum": "" 1166 | }, 1167 | "require": { 1168 | "microsoft/microsoft-graph-core": "^2.2.1", 1169 | "php": "^8.0 || ^7.4" 1170 | }, 1171 | "require-dev": { 1172 | "phpstan/phpstan": "^0.12.90 || ^1.0.0", 1173 | "phpunit/phpunit": "^8.0 || ^9.0" 1174 | }, 1175 | "type": "library", 1176 | "autoload": { 1177 | "psr-4": { 1178 | "Microsoft\\Graph\\": "src/" 1179 | } 1180 | }, 1181 | "notification-url": "https://packagist.org/downloads/", 1182 | "license": [ 1183 | "MIT" 1184 | ], 1185 | "authors": [ 1186 | { 1187 | "name": "Microsoft Graph Client Tooling", 1188 | "email": "graphtooling@service.microsoft.com", 1189 | "role": "Developer" 1190 | } 1191 | ], 1192 | "description": "The Microsoft Graph SDK for PHP", 1193 | "homepage": "https://developer.microsoft.com/en-us/graph", 1194 | "support": { 1195 | "issues": "https://github.com/microsoftgraph/msgraph-sdk-php/issues", 1196 | "source": "https://github.com/microsoftgraph/msgraph-sdk-php/tree/v2.36.0" 1197 | }, 1198 | "time": "2025-06-03T16:17:28+00:00" 1199 | }, 1200 | { 1201 | "name": "microsoft/microsoft-graph-core", 1202 | "version": "v2.3.1", 1203 | "source": { 1204 | "type": "git", 1205 | "url": "https://github.com/microsoftgraph/msgraph-sdk-php-core.git", 1206 | "reference": "783111f9e81db9da20cc2dbd48aa1876b500ba15" 1207 | }, 1208 | "dist": { 1209 | "type": "zip", 1210 | "url": "https://api.github.com/repos/microsoftgraph/msgraph-sdk-php-core/zipball/783111f9e81db9da20cc2dbd48aa1876b500ba15", 1211 | "reference": "783111f9e81db9da20cc2dbd48aa1876b500ba15", 1212 | "shasum": "" 1213 | }, 1214 | "require": { 1215 | "ext-json": "*", 1216 | "microsoft/kiota-authentication-phpleague": "^1.5.0", 1217 | "microsoft/kiota-http-guzzle": "^1.5.0", 1218 | "microsoft/kiota-serialization-form": "^1.5.0", 1219 | "microsoft/kiota-serialization-json": "^1.5.0", 1220 | "microsoft/kiota-serialization-multipart": "^1.5.0", 1221 | "microsoft/kiota-serialization-text": "^1.5.0", 1222 | "php": "^8.0 || ^7.4" 1223 | }, 1224 | "require-dev": { 1225 | "mikey179/vfsstream": "^1.2", 1226 | "phpstan/phpstan": "^0.12.90 || ^1.0.0", 1227 | "phpunit/phpunit": "^9.0" 1228 | }, 1229 | "type": "library", 1230 | "autoload": { 1231 | "psr-4": { 1232 | "Microsoft\\Graph\\Core\\": "src/" 1233 | } 1234 | }, 1235 | "notification-url": "https://packagist.org/downloads/", 1236 | "license": [ 1237 | "MIT" 1238 | ], 1239 | "authors": [ 1240 | { 1241 | "name": "Microsoft Graph Client Tooling", 1242 | "email": "graphtooling@service.microsoft.com", 1243 | "role": "Developer" 1244 | } 1245 | ], 1246 | "description": "The Microsoft Graph Core SDK for PHP", 1247 | "homepage": "https://developer.microsoft.com/en-us/graph", 1248 | "support": { 1249 | "issues": "https://github.com/microsoftgraph/msgraph-sdk-php-core/issues", 1250 | "source": "https://github.com/microsoftgraph/msgraph-sdk-php-core/tree/v2.3.1" 1251 | }, 1252 | "time": "2025-03-18T14:27:59+00:00" 1253 | }, 1254 | { 1255 | "name": "nyholm/psr7-server", 1256 | "version": "1.1.0", 1257 | "source": { 1258 | "type": "git", 1259 | "url": "https://github.com/Nyholm/psr7-server.git", 1260 | "reference": "4335801d851f554ca43fa6e7d2602141538854dc" 1261 | }, 1262 | "dist": { 1263 | "type": "zip", 1264 | "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/4335801d851f554ca43fa6e7d2602141538854dc", 1265 | "reference": "4335801d851f554ca43fa6e7d2602141538854dc", 1266 | "shasum": "" 1267 | }, 1268 | "require": { 1269 | "php": "^7.1 || ^8.0", 1270 | "psr/http-factory": "^1.0", 1271 | "psr/http-message": "^1.0 || ^2.0" 1272 | }, 1273 | "require-dev": { 1274 | "nyholm/nsa": "^1.1", 1275 | "nyholm/psr7": "^1.3", 1276 | "phpunit/phpunit": "^7.0 || ^8.5 || ^9.3" 1277 | }, 1278 | "type": "library", 1279 | "autoload": { 1280 | "psr-4": { 1281 | "Nyholm\\Psr7Server\\": "src/" 1282 | } 1283 | }, 1284 | "notification-url": "https://packagist.org/downloads/", 1285 | "license": [ 1286 | "MIT" 1287 | ], 1288 | "authors": [ 1289 | { 1290 | "name": "Tobias Nyholm", 1291 | "email": "tobias.nyholm@gmail.com" 1292 | }, 1293 | { 1294 | "name": "Martijn van der Ven", 1295 | "email": "martijn@vanderven.se" 1296 | } 1297 | ], 1298 | "description": "Helper classes to handle PSR-7 server requests", 1299 | "homepage": "http://tnyholm.se", 1300 | "keywords": [ 1301 | "psr-17", 1302 | "psr-7" 1303 | ], 1304 | "support": { 1305 | "issues": "https://github.com/Nyholm/psr7-server/issues", 1306 | "source": "https://github.com/Nyholm/psr7-server/tree/1.1.0" 1307 | }, 1308 | "funding": [ 1309 | { 1310 | "url": "https://github.com/Zegnat", 1311 | "type": "github" 1312 | }, 1313 | { 1314 | "url": "https://github.com/nyholm", 1315 | "type": "github" 1316 | } 1317 | ], 1318 | "time": "2023-11-08T09:30:43+00:00" 1319 | }, 1320 | { 1321 | "name": "open-telemetry/api", 1322 | "version": "1.3.0", 1323 | "source": { 1324 | "type": "git", 1325 | "url": "https://github.com/opentelemetry-php/api.git", 1326 | "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86" 1327 | }, 1328 | "dist": { 1329 | "type": "zip", 1330 | "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/4e3bb38e069876fb73c2ce85c89583bf2b28cd86", 1331 | "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86", 1332 | "shasum": "" 1333 | }, 1334 | "require": { 1335 | "open-telemetry/context": "^1.0", 1336 | "php": "^8.1", 1337 | "psr/log": "^1.1|^2.0|^3.0", 1338 | "symfony/polyfill-php82": "^1.26" 1339 | }, 1340 | "conflict": { 1341 | "open-telemetry/sdk": "<=1.0.8" 1342 | }, 1343 | "type": "library", 1344 | "extra": { 1345 | "spi": { 1346 | "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ 1347 | "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" 1348 | ] 1349 | }, 1350 | "branch-alias": { 1351 | "dev-main": "1.1.x-dev" 1352 | } 1353 | }, 1354 | "autoload": { 1355 | "files": [ 1356 | "Trace/functions.php" 1357 | ], 1358 | "psr-4": { 1359 | "OpenTelemetry\\API\\": "." 1360 | } 1361 | }, 1362 | "notification-url": "https://packagist.org/downloads/", 1363 | "license": [ 1364 | "Apache-2.0" 1365 | ], 1366 | "authors": [ 1367 | { 1368 | "name": "opentelemetry-php contributors", 1369 | "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" 1370 | } 1371 | ], 1372 | "description": "API for OpenTelemetry PHP.", 1373 | "keywords": [ 1374 | "Metrics", 1375 | "api", 1376 | "apm", 1377 | "logging", 1378 | "opentelemetry", 1379 | "otel", 1380 | "tracing" 1381 | ], 1382 | "support": { 1383 | "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", 1384 | "docs": "https://opentelemetry.io/docs/php", 1385 | "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", 1386 | "source": "https://github.com/open-telemetry/opentelemetry-php" 1387 | }, 1388 | "time": "2025-05-07T12:32:21+00:00" 1389 | }, 1390 | { 1391 | "name": "open-telemetry/context", 1392 | "version": "1.2.1", 1393 | "source": { 1394 | "type": "git", 1395 | "url": "https://github.com/opentelemetry-php/context.git", 1396 | "reference": "1eb2b837ee9362db064a6b65d5ecce15a9f9f020" 1397 | }, 1398 | "dist": { 1399 | "type": "zip", 1400 | "url": "https://api.github.com/repos/opentelemetry-php/context/zipball/1eb2b837ee9362db064a6b65d5ecce15a9f9f020", 1401 | "reference": "1eb2b837ee9362db064a6b65d5ecce15a9f9f020", 1402 | "shasum": "" 1403 | }, 1404 | "require": { 1405 | "php": "^8.1", 1406 | "symfony/polyfill-php82": "^1.26" 1407 | }, 1408 | "suggest": { 1409 | "ext-ffi": "To allow context switching in Fibers" 1410 | }, 1411 | "type": "library", 1412 | "extra": { 1413 | "branch-alias": { 1414 | "dev-main": "1.0.x-dev" 1415 | } 1416 | }, 1417 | "autoload": { 1418 | "files": [ 1419 | "fiber/initialize_fiber_handler.php" 1420 | ], 1421 | "psr-4": { 1422 | "OpenTelemetry\\Context\\": "." 1423 | } 1424 | }, 1425 | "notification-url": "https://packagist.org/downloads/", 1426 | "license": [ 1427 | "Apache-2.0" 1428 | ], 1429 | "authors": [ 1430 | { 1431 | "name": "opentelemetry-php contributors", 1432 | "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" 1433 | } 1434 | ], 1435 | "description": "Context implementation for OpenTelemetry PHP.", 1436 | "keywords": [ 1437 | "Context", 1438 | "opentelemetry", 1439 | "otel" 1440 | ], 1441 | "support": { 1442 | "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", 1443 | "docs": "https://opentelemetry.io/docs/php", 1444 | "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", 1445 | "source": "https://github.com/open-telemetry/opentelemetry-php" 1446 | }, 1447 | "time": "2025-05-07T23:36:50+00:00" 1448 | }, 1449 | { 1450 | "name": "open-telemetry/sdk", 1451 | "version": "1.5.0", 1452 | "source": { 1453 | "type": "git", 1454 | "url": "https://github.com/opentelemetry-php/sdk.git", 1455 | "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657" 1456 | }, 1457 | "dist": { 1458 | "type": "zip", 1459 | "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/cd0d7367599717fc29e04eb8838ec061e6c2c657", 1460 | "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657", 1461 | "shasum": "" 1462 | }, 1463 | "require": { 1464 | "ext-json": "*", 1465 | "nyholm/psr7-server": "^1.1", 1466 | "open-telemetry/api": "~1.0 || ~1.1", 1467 | "open-telemetry/context": "^1.0", 1468 | "open-telemetry/sem-conv": "^1.0", 1469 | "php": "^8.1", 1470 | "php-http/discovery": "^1.14", 1471 | "psr/http-client": "^1.0", 1472 | "psr/http-client-implementation": "^1.0", 1473 | "psr/http-factory-implementation": "^1.0", 1474 | "psr/http-message": "^1.0.1|^2.0", 1475 | "psr/log": "^1.1|^2.0|^3.0", 1476 | "ramsey/uuid": "^3.0 || ^4.0", 1477 | "symfony/polyfill-mbstring": "^1.23", 1478 | "symfony/polyfill-php82": "^1.26", 1479 | "tbachert/spi": "^1.0.1" 1480 | }, 1481 | "suggest": { 1482 | "ext-gmp": "To support unlimited number of synchronous metric readers", 1483 | "ext-mbstring": "To increase performance of string operations", 1484 | "open-telemetry/sdk-configuration": "File-based OpenTelemetry SDK configuration" 1485 | }, 1486 | "type": "library", 1487 | "extra": { 1488 | "spi": { 1489 | "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ 1490 | "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" 1491 | ] 1492 | }, 1493 | "branch-alias": { 1494 | "dev-main": "1.0.x-dev" 1495 | } 1496 | }, 1497 | "autoload": { 1498 | "files": [ 1499 | "Common/Util/functions.php", 1500 | "Logs/Exporter/_register.php", 1501 | "Metrics/MetricExporter/_register.php", 1502 | "Propagation/_register.php", 1503 | "Trace/SpanExporter/_register.php", 1504 | "Common/Dev/Compatibility/_load.php", 1505 | "_autoload.php" 1506 | ], 1507 | "psr-4": { 1508 | "OpenTelemetry\\SDK\\": "." 1509 | } 1510 | }, 1511 | "notification-url": "https://packagist.org/downloads/", 1512 | "license": [ 1513 | "Apache-2.0" 1514 | ], 1515 | "authors": [ 1516 | { 1517 | "name": "opentelemetry-php contributors", 1518 | "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" 1519 | } 1520 | ], 1521 | "description": "SDK for OpenTelemetry PHP.", 1522 | "keywords": [ 1523 | "Metrics", 1524 | "apm", 1525 | "logging", 1526 | "opentelemetry", 1527 | "otel", 1528 | "sdk", 1529 | "tracing" 1530 | ], 1531 | "support": { 1532 | "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", 1533 | "docs": "https://opentelemetry.io/docs/php", 1534 | "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", 1535 | "source": "https://github.com/open-telemetry/opentelemetry-php" 1536 | }, 1537 | "time": "2025-05-22T02:33:34+00:00" 1538 | }, 1539 | { 1540 | "name": "open-telemetry/sem-conv", 1541 | "version": "1.32.0", 1542 | "source": { 1543 | "type": "git", 1544 | "url": "https://github.com/opentelemetry-php/sem-conv.git", 1545 | "reference": "16585cc0dbc3032a318e274043454679430d2ebf" 1546 | }, 1547 | "dist": { 1548 | "type": "zip", 1549 | "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/16585cc0dbc3032a318e274043454679430d2ebf", 1550 | "reference": "16585cc0dbc3032a318e274043454679430d2ebf", 1551 | "shasum": "" 1552 | }, 1553 | "require": { 1554 | "php": "^8.0" 1555 | }, 1556 | "type": "library", 1557 | "extra": { 1558 | "branch-alias": { 1559 | "dev-main": "1.x-dev" 1560 | } 1561 | }, 1562 | "autoload": { 1563 | "psr-4": { 1564 | "OpenTelemetry\\SemConv\\": "." 1565 | } 1566 | }, 1567 | "notification-url": "https://packagist.org/downloads/", 1568 | "license": [ 1569 | "Apache-2.0" 1570 | ], 1571 | "authors": [ 1572 | { 1573 | "name": "opentelemetry-php contributors", 1574 | "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" 1575 | } 1576 | ], 1577 | "description": "Semantic conventions for OpenTelemetry PHP.", 1578 | "keywords": [ 1579 | "Metrics", 1580 | "apm", 1581 | "logging", 1582 | "opentelemetry", 1583 | "otel", 1584 | "semantic conventions", 1585 | "semconv", 1586 | "tracing" 1587 | ], 1588 | "support": { 1589 | "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", 1590 | "docs": "https://opentelemetry.io/docs/php", 1591 | "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", 1592 | "source": "https://github.com/open-telemetry/opentelemetry-php" 1593 | }, 1594 | "time": "2025-05-05T03:58:53+00:00" 1595 | }, 1596 | { 1597 | "name": "php-http/discovery", 1598 | "version": "1.20.0", 1599 | "source": { 1600 | "type": "git", 1601 | "url": "https://github.com/php-http/discovery.git", 1602 | "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d" 1603 | }, 1604 | "dist": { 1605 | "type": "zip", 1606 | "url": "https://api.github.com/repos/php-http/discovery/zipball/82fe4c73ef3363caed49ff8dd1539ba06044910d", 1607 | "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d", 1608 | "shasum": "" 1609 | }, 1610 | "require": { 1611 | "composer-plugin-api": "^1.0|^2.0", 1612 | "php": "^7.1 || ^8.0" 1613 | }, 1614 | "conflict": { 1615 | "nyholm/psr7": "<1.0", 1616 | "zendframework/zend-diactoros": "*" 1617 | }, 1618 | "provide": { 1619 | "php-http/async-client-implementation": "*", 1620 | "php-http/client-implementation": "*", 1621 | "psr/http-client-implementation": "*", 1622 | "psr/http-factory-implementation": "*", 1623 | "psr/http-message-implementation": "*" 1624 | }, 1625 | "require-dev": { 1626 | "composer/composer": "^1.0.2|^2.0", 1627 | "graham-campbell/phpspec-skip-example-extension": "^5.0", 1628 | "php-http/httplug": "^1.0 || ^2.0", 1629 | "php-http/message-factory": "^1.0", 1630 | "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", 1631 | "sebastian/comparator": "^3.0.5 || ^4.0.8", 1632 | "symfony/phpunit-bridge": "^6.4.4 || ^7.0.1" 1633 | }, 1634 | "type": "composer-plugin", 1635 | "extra": { 1636 | "class": "Http\\Discovery\\Composer\\Plugin", 1637 | "plugin-optional": true 1638 | }, 1639 | "autoload": { 1640 | "psr-4": { 1641 | "Http\\Discovery\\": "src/" 1642 | }, 1643 | "exclude-from-classmap": [ 1644 | "src/Composer/Plugin.php" 1645 | ] 1646 | }, 1647 | "notification-url": "https://packagist.org/downloads/", 1648 | "license": [ 1649 | "MIT" 1650 | ], 1651 | "authors": [ 1652 | { 1653 | "name": "Márk Sági-Kazár", 1654 | "email": "mark.sagikazar@gmail.com" 1655 | } 1656 | ], 1657 | "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", 1658 | "homepage": "http://php-http.org", 1659 | "keywords": [ 1660 | "adapter", 1661 | "client", 1662 | "discovery", 1663 | "factory", 1664 | "http", 1665 | "message", 1666 | "psr17", 1667 | "psr7" 1668 | ], 1669 | "support": { 1670 | "issues": "https://github.com/php-http/discovery/issues", 1671 | "source": "https://github.com/php-http/discovery/tree/1.20.0" 1672 | }, 1673 | "time": "2024-10-02T11:20:13+00:00" 1674 | }, 1675 | { 1676 | "name": "php-http/guzzle7-adapter", 1677 | "version": "1.1.0", 1678 | "source": { 1679 | "type": "git", 1680 | "url": "https://github.com/php-http/guzzle7-adapter.git", 1681 | "reference": "03a415fde709c2f25539790fecf4d9a31bc3d0eb" 1682 | }, 1683 | "dist": { 1684 | "type": "zip", 1685 | "url": "https://api.github.com/repos/php-http/guzzle7-adapter/zipball/03a415fde709c2f25539790fecf4d9a31bc3d0eb", 1686 | "reference": "03a415fde709c2f25539790fecf4d9a31bc3d0eb", 1687 | "shasum": "" 1688 | }, 1689 | "require": { 1690 | "guzzlehttp/guzzle": "^7.0", 1691 | "php": "^7.3 | ^8.0", 1692 | "php-http/httplug": "^2.0", 1693 | "psr/http-client": "^1.0" 1694 | }, 1695 | "provide": { 1696 | "php-http/async-client-implementation": "1.0", 1697 | "php-http/client-implementation": "1.0", 1698 | "psr/http-client-implementation": "1.0" 1699 | }, 1700 | "require-dev": { 1701 | "php-http/client-integration-tests": "^3.0", 1702 | "php-http/message-factory": "^1.1", 1703 | "phpspec/prophecy-phpunit": "^2.0", 1704 | "phpunit/phpunit": "^8.0|^9.3" 1705 | }, 1706 | "type": "library", 1707 | "autoload": { 1708 | "psr-4": { 1709 | "Http\\Adapter\\Guzzle7\\": "src/" 1710 | } 1711 | }, 1712 | "notification-url": "https://packagist.org/downloads/", 1713 | "license": [ 1714 | "MIT" 1715 | ], 1716 | "authors": [ 1717 | { 1718 | "name": "Tobias Nyholm", 1719 | "email": "tobias.nyholm@gmail.com" 1720 | } 1721 | ], 1722 | "description": "Guzzle 7 HTTP Adapter", 1723 | "homepage": "http://httplug.io", 1724 | "keywords": [ 1725 | "Guzzle", 1726 | "http" 1727 | ], 1728 | "support": { 1729 | "issues": "https://github.com/php-http/guzzle7-adapter/issues", 1730 | "source": "https://github.com/php-http/guzzle7-adapter/tree/1.1.0" 1731 | }, 1732 | "time": "2024-11-26T11:14:36+00:00" 1733 | }, 1734 | { 1735 | "name": "php-http/httplug", 1736 | "version": "2.4.1", 1737 | "source": { 1738 | "type": "git", 1739 | "url": "https://github.com/php-http/httplug.git", 1740 | "reference": "5cad731844891a4c282f3f3e1b582c46839d22f4" 1741 | }, 1742 | "dist": { 1743 | "type": "zip", 1744 | "url": "https://api.github.com/repos/php-http/httplug/zipball/5cad731844891a4c282f3f3e1b582c46839d22f4", 1745 | "reference": "5cad731844891a4c282f3f3e1b582c46839d22f4", 1746 | "shasum": "" 1747 | }, 1748 | "require": { 1749 | "php": "^7.1 || ^8.0", 1750 | "php-http/promise": "^1.1", 1751 | "psr/http-client": "^1.0", 1752 | "psr/http-message": "^1.0 || ^2.0" 1753 | }, 1754 | "require-dev": { 1755 | "friends-of-phpspec/phpspec-code-coverage": "^4.1 || ^5.0 || ^6.0", 1756 | "phpspec/phpspec": "^5.1 || ^6.0 || ^7.0" 1757 | }, 1758 | "type": "library", 1759 | "autoload": { 1760 | "psr-4": { 1761 | "Http\\Client\\": "src/" 1762 | } 1763 | }, 1764 | "notification-url": "https://packagist.org/downloads/", 1765 | "license": [ 1766 | "MIT" 1767 | ], 1768 | "authors": [ 1769 | { 1770 | "name": "Eric GELOEN", 1771 | "email": "geloen.eric@gmail.com" 1772 | }, 1773 | { 1774 | "name": "Márk Sági-Kazár", 1775 | "email": "mark.sagikazar@gmail.com", 1776 | "homepage": "https://sagikazarmark.hu" 1777 | } 1778 | ], 1779 | "description": "HTTPlug, the HTTP client abstraction for PHP", 1780 | "homepage": "http://httplug.io", 1781 | "keywords": [ 1782 | "client", 1783 | "http" 1784 | ], 1785 | "support": { 1786 | "issues": "https://github.com/php-http/httplug/issues", 1787 | "source": "https://github.com/php-http/httplug/tree/2.4.1" 1788 | }, 1789 | "time": "2024-09-23T11:39:58+00:00" 1790 | }, 1791 | { 1792 | "name": "php-http/promise", 1793 | "version": "1.2.1", 1794 | "source": { 1795 | "type": "git", 1796 | "url": "https://github.com/php-http/promise.git", 1797 | "reference": "44a67cb59f708f826f3bec35f22030b3edb90119" 1798 | }, 1799 | "dist": { 1800 | "type": "zip", 1801 | "url": "https://api.github.com/repos/php-http/promise/zipball/44a67cb59f708f826f3bec35f22030b3edb90119", 1802 | "reference": "44a67cb59f708f826f3bec35f22030b3edb90119", 1803 | "shasum": "" 1804 | }, 1805 | "require": { 1806 | "php": "^7.1 || ^8.0" 1807 | }, 1808 | "require-dev": { 1809 | "friends-of-phpspec/phpspec-code-coverage": "^4.3.2 || ^6.3", 1810 | "phpspec/phpspec": "^5.1.2 || ^6.2 || ^7.4" 1811 | }, 1812 | "type": "library", 1813 | "autoload": { 1814 | "psr-4": { 1815 | "Http\\Promise\\": "src/" 1816 | } 1817 | }, 1818 | "notification-url": "https://packagist.org/downloads/", 1819 | "license": [ 1820 | "MIT" 1821 | ], 1822 | "authors": [ 1823 | { 1824 | "name": "Joel Wurtz", 1825 | "email": "joel.wurtz@gmail.com" 1826 | }, 1827 | { 1828 | "name": "Márk Sági-Kazár", 1829 | "email": "mark.sagikazar@gmail.com" 1830 | } 1831 | ], 1832 | "description": "Promise used for asynchronous HTTP requests", 1833 | "homepage": "http://httplug.io", 1834 | "keywords": [ 1835 | "promise" 1836 | ], 1837 | "support": { 1838 | "issues": "https://github.com/php-http/promise/issues", 1839 | "source": "https://github.com/php-http/promise/tree/1.2.1" 1840 | }, 1841 | "time": "2023-11-08T12:57:08+00:00" 1842 | }, 1843 | { 1844 | "name": "phpoption/phpoption", 1845 | "version": "1.9.3", 1846 | "source": { 1847 | "type": "git", 1848 | "url": "https://github.com/schmittjoh/php-option.git", 1849 | "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" 1850 | }, 1851 | "dist": { 1852 | "type": "zip", 1853 | "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", 1854 | "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", 1855 | "shasum": "" 1856 | }, 1857 | "require": { 1858 | "php": "^7.2.5 || ^8.0" 1859 | }, 1860 | "require-dev": { 1861 | "bamarni/composer-bin-plugin": "^1.8.2", 1862 | "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" 1863 | }, 1864 | "type": "library", 1865 | "extra": { 1866 | "bamarni-bin": { 1867 | "bin-links": true, 1868 | "forward-command": false 1869 | }, 1870 | "branch-alias": { 1871 | "dev-master": "1.9-dev" 1872 | } 1873 | }, 1874 | "autoload": { 1875 | "psr-4": { 1876 | "PhpOption\\": "src/PhpOption/" 1877 | } 1878 | }, 1879 | "notification-url": "https://packagist.org/downloads/", 1880 | "license": [ 1881 | "Apache-2.0" 1882 | ], 1883 | "authors": [ 1884 | { 1885 | "name": "Johannes M. Schmitt", 1886 | "email": "schmittjoh@gmail.com", 1887 | "homepage": "https://github.com/schmittjoh" 1888 | }, 1889 | { 1890 | "name": "Graham Campbell", 1891 | "email": "hello@gjcampbell.co.uk", 1892 | "homepage": "https://github.com/GrahamCampbell" 1893 | } 1894 | ], 1895 | "description": "Option Type for PHP", 1896 | "keywords": [ 1897 | "language", 1898 | "option", 1899 | "php", 1900 | "type" 1901 | ], 1902 | "support": { 1903 | "issues": "https://github.com/schmittjoh/php-option/issues", 1904 | "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" 1905 | }, 1906 | "funding": [ 1907 | { 1908 | "url": "https://github.com/GrahamCampbell", 1909 | "type": "github" 1910 | }, 1911 | { 1912 | "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", 1913 | "type": "tidelift" 1914 | } 1915 | ], 1916 | "time": "2024-07-20T21:41:07+00:00" 1917 | }, 1918 | { 1919 | "name": "psr/cache", 1920 | "version": "3.0.0", 1921 | "source": { 1922 | "type": "git", 1923 | "url": "https://github.com/php-fig/cache.git", 1924 | "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" 1925 | }, 1926 | "dist": { 1927 | "type": "zip", 1928 | "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", 1929 | "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", 1930 | "shasum": "" 1931 | }, 1932 | "require": { 1933 | "php": ">=8.0.0" 1934 | }, 1935 | "type": "library", 1936 | "extra": { 1937 | "branch-alias": { 1938 | "dev-master": "1.0.x-dev" 1939 | } 1940 | }, 1941 | "autoload": { 1942 | "psr-4": { 1943 | "Psr\\Cache\\": "src/" 1944 | } 1945 | }, 1946 | "notification-url": "https://packagist.org/downloads/", 1947 | "license": [ 1948 | "MIT" 1949 | ], 1950 | "authors": [ 1951 | { 1952 | "name": "PHP-FIG", 1953 | "homepage": "https://www.php-fig.org/" 1954 | } 1955 | ], 1956 | "description": "Common interface for caching libraries", 1957 | "keywords": [ 1958 | "cache", 1959 | "psr", 1960 | "psr-6" 1961 | ], 1962 | "support": { 1963 | "source": "https://github.com/php-fig/cache/tree/3.0.0" 1964 | }, 1965 | "time": "2021-02-03T23:26:27+00:00" 1966 | }, 1967 | { 1968 | "name": "psr/http-client", 1969 | "version": "1.0.3", 1970 | "source": { 1971 | "type": "git", 1972 | "url": "https://github.com/php-fig/http-client.git", 1973 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" 1974 | }, 1975 | "dist": { 1976 | "type": "zip", 1977 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", 1978 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", 1979 | "shasum": "" 1980 | }, 1981 | "require": { 1982 | "php": "^7.0 || ^8.0", 1983 | "psr/http-message": "^1.0 || ^2.0" 1984 | }, 1985 | "type": "library", 1986 | "extra": { 1987 | "branch-alias": { 1988 | "dev-master": "1.0.x-dev" 1989 | } 1990 | }, 1991 | "autoload": { 1992 | "psr-4": { 1993 | "Psr\\Http\\Client\\": "src/" 1994 | } 1995 | }, 1996 | "notification-url": "https://packagist.org/downloads/", 1997 | "license": [ 1998 | "MIT" 1999 | ], 2000 | "authors": [ 2001 | { 2002 | "name": "PHP-FIG", 2003 | "homepage": "https://www.php-fig.org/" 2004 | } 2005 | ], 2006 | "description": "Common interface for HTTP clients", 2007 | "homepage": "https://github.com/php-fig/http-client", 2008 | "keywords": [ 2009 | "http", 2010 | "http-client", 2011 | "psr", 2012 | "psr-18" 2013 | ], 2014 | "support": { 2015 | "source": "https://github.com/php-fig/http-client" 2016 | }, 2017 | "time": "2023-09-23T14:17:50+00:00" 2018 | }, 2019 | { 2020 | "name": "psr/http-factory", 2021 | "version": "1.1.0", 2022 | "source": { 2023 | "type": "git", 2024 | "url": "https://github.com/php-fig/http-factory.git", 2025 | "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" 2026 | }, 2027 | "dist": { 2028 | "type": "zip", 2029 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", 2030 | "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", 2031 | "shasum": "" 2032 | }, 2033 | "require": { 2034 | "php": ">=7.1", 2035 | "psr/http-message": "^1.0 || ^2.0" 2036 | }, 2037 | "type": "library", 2038 | "extra": { 2039 | "branch-alias": { 2040 | "dev-master": "1.0.x-dev" 2041 | } 2042 | }, 2043 | "autoload": { 2044 | "psr-4": { 2045 | "Psr\\Http\\Message\\": "src/" 2046 | } 2047 | }, 2048 | "notification-url": "https://packagist.org/downloads/", 2049 | "license": [ 2050 | "MIT" 2051 | ], 2052 | "authors": [ 2053 | { 2054 | "name": "PHP-FIG", 2055 | "homepage": "https://www.php-fig.org/" 2056 | } 2057 | ], 2058 | "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", 2059 | "keywords": [ 2060 | "factory", 2061 | "http", 2062 | "message", 2063 | "psr", 2064 | "psr-17", 2065 | "psr-7", 2066 | "request", 2067 | "response" 2068 | ], 2069 | "support": { 2070 | "source": "https://github.com/php-fig/http-factory" 2071 | }, 2072 | "time": "2024-04-15T12:06:14+00:00" 2073 | }, 2074 | { 2075 | "name": "psr/http-message", 2076 | "version": "2.0", 2077 | "source": { 2078 | "type": "git", 2079 | "url": "https://github.com/php-fig/http-message.git", 2080 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" 2081 | }, 2082 | "dist": { 2083 | "type": "zip", 2084 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", 2085 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", 2086 | "shasum": "" 2087 | }, 2088 | "require": { 2089 | "php": "^7.2 || ^8.0" 2090 | }, 2091 | "type": "library", 2092 | "extra": { 2093 | "branch-alias": { 2094 | "dev-master": "2.0.x-dev" 2095 | } 2096 | }, 2097 | "autoload": { 2098 | "psr-4": { 2099 | "Psr\\Http\\Message\\": "src/" 2100 | } 2101 | }, 2102 | "notification-url": "https://packagist.org/downloads/", 2103 | "license": [ 2104 | "MIT" 2105 | ], 2106 | "authors": [ 2107 | { 2108 | "name": "PHP-FIG", 2109 | "homepage": "https://www.php-fig.org/" 2110 | } 2111 | ], 2112 | "description": "Common interface for HTTP messages", 2113 | "homepage": "https://github.com/php-fig/http-message", 2114 | "keywords": [ 2115 | "http", 2116 | "http-message", 2117 | "psr", 2118 | "psr-7", 2119 | "request", 2120 | "response" 2121 | ], 2122 | "support": { 2123 | "source": "https://github.com/php-fig/http-message/tree/2.0" 2124 | }, 2125 | "time": "2023-04-04T09:54:51+00:00" 2126 | }, 2127 | { 2128 | "name": "psr/log", 2129 | "version": "3.0.2", 2130 | "source": { 2131 | "type": "git", 2132 | "url": "https://github.com/php-fig/log.git", 2133 | "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" 2134 | }, 2135 | "dist": { 2136 | "type": "zip", 2137 | "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", 2138 | "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", 2139 | "shasum": "" 2140 | }, 2141 | "require": { 2142 | "php": ">=8.0.0" 2143 | }, 2144 | "type": "library", 2145 | "extra": { 2146 | "branch-alias": { 2147 | "dev-master": "3.x-dev" 2148 | } 2149 | }, 2150 | "autoload": { 2151 | "psr-4": { 2152 | "Psr\\Log\\": "src" 2153 | } 2154 | }, 2155 | "notification-url": "https://packagist.org/downloads/", 2156 | "license": [ 2157 | "MIT" 2158 | ], 2159 | "authors": [ 2160 | { 2161 | "name": "PHP-FIG", 2162 | "homepage": "https://www.php-fig.org/" 2163 | } 2164 | ], 2165 | "description": "Common interface for logging libraries", 2166 | "homepage": "https://github.com/php-fig/log", 2167 | "keywords": [ 2168 | "log", 2169 | "psr", 2170 | "psr-3" 2171 | ], 2172 | "support": { 2173 | "source": "https://github.com/php-fig/log/tree/3.0.2" 2174 | }, 2175 | "time": "2024-09-11T13:17:53+00:00" 2176 | }, 2177 | { 2178 | "name": "ralouphie/getallheaders", 2179 | "version": "3.0.3", 2180 | "source": { 2181 | "type": "git", 2182 | "url": "https://github.com/ralouphie/getallheaders.git", 2183 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 2184 | }, 2185 | "dist": { 2186 | "type": "zip", 2187 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 2188 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 2189 | "shasum": "" 2190 | }, 2191 | "require": { 2192 | "php": ">=5.6" 2193 | }, 2194 | "require-dev": { 2195 | "php-coveralls/php-coveralls": "^2.1", 2196 | "phpunit/phpunit": "^5 || ^6.5" 2197 | }, 2198 | "type": "library", 2199 | "autoload": { 2200 | "files": [ 2201 | "src/getallheaders.php" 2202 | ] 2203 | }, 2204 | "notification-url": "https://packagist.org/downloads/", 2205 | "license": [ 2206 | "MIT" 2207 | ], 2208 | "authors": [ 2209 | { 2210 | "name": "Ralph Khattar", 2211 | "email": "ralph.khattar@gmail.com" 2212 | } 2213 | ], 2214 | "description": "A polyfill for getallheaders.", 2215 | "support": { 2216 | "issues": "https://github.com/ralouphie/getallheaders/issues", 2217 | "source": "https://github.com/ralouphie/getallheaders/tree/develop" 2218 | }, 2219 | "time": "2019-03-08T08:55:37+00:00" 2220 | }, 2221 | { 2222 | "name": "ramsey/collection", 2223 | "version": "2.1.1", 2224 | "source": { 2225 | "type": "git", 2226 | "url": "https://github.com/ramsey/collection.git", 2227 | "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" 2228 | }, 2229 | "dist": { 2230 | "type": "zip", 2231 | "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", 2232 | "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", 2233 | "shasum": "" 2234 | }, 2235 | "require": { 2236 | "php": "^8.1" 2237 | }, 2238 | "require-dev": { 2239 | "captainhook/plugin-composer": "^5.3", 2240 | "ergebnis/composer-normalize": "^2.45", 2241 | "fakerphp/faker": "^1.24", 2242 | "hamcrest/hamcrest-php": "^2.0", 2243 | "jangregor/phpstan-prophecy": "^2.1", 2244 | "mockery/mockery": "^1.6", 2245 | "php-parallel-lint/php-console-highlighter": "^1.0", 2246 | "php-parallel-lint/php-parallel-lint": "^1.4", 2247 | "phpspec/prophecy-phpunit": "^2.3", 2248 | "phpstan/extension-installer": "^1.4", 2249 | "phpstan/phpstan": "^2.1", 2250 | "phpstan/phpstan-mockery": "^2.0", 2251 | "phpstan/phpstan-phpunit": "^2.0", 2252 | "phpunit/phpunit": "^10.5", 2253 | "ramsey/coding-standard": "^2.3", 2254 | "ramsey/conventional-commits": "^1.6", 2255 | "roave/security-advisories": "dev-latest" 2256 | }, 2257 | "type": "library", 2258 | "extra": { 2259 | "captainhook": { 2260 | "force-install": true 2261 | }, 2262 | "ramsey/conventional-commits": { 2263 | "configFile": "conventional-commits.json" 2264 | } 2265 | }, 2266 | "autoload": { 2267 | "psr-4": { 2268 | "Ramsey\\Collection\\": "src/" 2269 | } 2270 | }, 2271 | "notification-url": "https://packagist.org/downloads/", 2272 | "license": [ 2273 | "MIT" 2274 | ], 2275 | "authors": [ 2276 | { 2277 | "name": "Ben Ramsey", 2278 | "email": "ben@benramsey.com", 2279 | "homepage": "https://benramsey.com" 2280 | } 2281 | ], 2282 | "description": "A PHP library for representing and manipulating collections.", 2283 | "keywords": [ 2284 | "array", 2285 | "collection", 2286 | "hash", 2287 | "map", 2288 | "queue", 2289 | "set" 2290 | ], 2291 | "support": { 2292 | "issues": "https://github.com/ramsey/collection/issues", 2293 | "source": "https://github.com/ramsey/collection/tree/2.1.1" 2294 | }, 2295 | "time": "2025-03-22T05:38:12+00:00" 2296 | }, 2297 | { 2298 | "name": "ramsey/uuid", 2299 | "version": "4.8.1", 2300 | "source": { 2301 | "type": "git", 2302 | "url": "https://github.com/ramsey/uuid.git", 2303 | "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" 2304 | }, 2305 | "dist": { 2306 | "type": "zip", 2307 | "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", 2308 | "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", 2309 | "shasum": "" 2310 | }, 2311 | "require": { 2312 | "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", 2313 | "ext-json": "*", 2314 | "php": "^8.0", 2315 | "ramsey/collection": "^1.2 || ^2.0" 2316 | }, 2317 | "replace": { 2318 | "rhumsaa/uuid": "self.version" 2319 | }, 2320 | "require-dev": { 2321 | "captainhook/captainhook": "^5.25", 2322 | "captainhook/plugin-composer": "^5.3", 2323 | "dealerdirect/phpcodesniffer-composer-installer": "^1.0", 2324 | "ergebnis/composer-normalize": "^2.47", 2325 | "mockery/mockery": "^1.6", 2326 | "paragonie/random-lib": "^2", 2327 | "php-mock/php-mock": "^2.6", 2328 | "php-mock/php-mock-mockery": "^1.5", 2329 | "php-parallel-lint/php-parallel-lint": "^1.4.0", 2330 | "phpbench/phpbench": "^1.2.14", 2331 | "phpstan/extension-installer": "^1.4", 2332 | "phpstan/phpstan": "^2.1", 2333 | "phpstan/phpstan-mockery": "^2.0", 2334 | "phpstan/phpstan-phpunit": "^2.0", 2335 | "phpunit/phpunit": "^9.6", 2336 | "slevomat/coding-standard": "^8.18", 2337 | "squizlabs/php_codesniffer": "^3.13" 2338 | }, 2339 | "suggest": { 2340 | "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", 2341 | "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", 2342 | "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", 2343 | "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", 2344 | "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." 2345 | }, 2346 | "type": "library", 2347 | "extra": { 2348 | "captainhook": { 2349 | "force-install": true 2350 | } 2351 | }, 2352 | "autoload": { 2353 | "files": [ 2354 | "src/functions.php" 2355 | ], 2356 | "psr-4": { 2357 | "Ramsey\\Uuid\\": "src/" 2358 | } 2359 | }, 2360 | "notification-url": "https://packagist.org/downloads/", 2361 | "license": [ 2362 | "MIT" 2363 | ], 2364 | "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", 2365 | "keywords": [ 2366 | "guid", 2367 | "identifier", 2368 | "uuid" 2369 | ], 2370 | "support": { 2371 | "issues": "https://github.com/ramsey/uuid/issues", 2372 | "source": "https://github.com/ramsey/uuid/tree/4.8.1" 2373 | }, 2374 | "time": "2025-06-01T06:28:46+00:00" 2375 | }, 2376 | { 2377 | "name": "stduritemplate/stduritemplate", 2378 | "version": "2.0.5", 2379 | "source": { 2380 | "type": "git", 2381 | "url": "https://github.com/std-uritemplate/std-uritemplate-php.git", 2382 | "reference": "57f10976540d2fba3df5475c84dad6243eb3f36e" 2383 | }, 2384 | "dist": { 2385 | "type": "zip", 2386 | "url": "https://api.github.com/repos/std-uritemplate/std-uritemplate-php/zipball/57f10976540d2fba3df5475c84dad6243eb3f36e", 2387 | "reference": "57f10976540d2fba3df5475c84dad6243eb3f36e", 2388 | "shasum": "" 2389 | }, 2390 | "require": { 2391 | "php": "^7.4 || ^8.0" 2392 | }, 2393 | "type": "library", 2394 | "autoload": { 2395 | "psr-4": { 2396 | "StdUriTemplate\\": "src/" 2397 | } 2398 | }, 2399 | "notification-url": "https://packagist.org/downloads/", 2400 | "license": [ 2401 | "Apache-2.0" 2402 | ], 2403 | "authors": [ 2404 | { 2405 | "name": "Andrea Peruffo", 2406 | "email": "andrea.peruffo1982@gmail.com" 2407 | } 2408 | ], 2409 | "description": "Std UriTemplate, RFC 6570 implementation", 2410 | "support": { 2411 | "source": "https://github.com/std-uritemplate/std-uritemplate-php/tree/2.0.5" 2412 | }, 2413 | "time": "2025-05-14T13:10:06+00:00" 2414 | }, 2415 | { 2416 | "name": "symfony/deprecation-contracts", 2417 | "version": "v3.6.0", 2418 | "source": { 2419 | "type": "git", 2420 | "url": "https://github.com/symfony/deprecation-contracts.git", 2421 | "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" 2422 | }, 2423 | "dist": { 2424 | "type": "zip", 2425 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", 2426 | "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", 2427 | "shasum": "" 2428 | }, 2429 | "require": { 2430 | "php": ">=8.1" 2431 | }, 2432 | "type": "library", 2433 | "extra": { 2434 | "thanks": { 2435 | "url": "https://github.com/symfony/contracts", 2436 | "name": "symfony/contracts" 2437 | }, 2438 | "branch-alias": { 2439 | "dev-main": "3.6-dev" 2440 | } 2441 | }, 2442 | "autoload": { 2443 | "files": [ 2444 | "function.php" 2445 | ] 2446 | }, 2447 | "notification-url": "https://packagist.org/downloads/", 2448 | "license": [ 2449 | "MIT" 2450 | ], 2451 | "authors": [ 2452 | { 2453 | "name": "Nicolas Grekas", 2454 | "email": "p@tchwork.com" 2455 | }, 2456 | { 2457 | "name": "Symfony Community", 2458 | "homepage": "https://symfony.com/contributors" 2459 | } 2460 | ], 2461 | "description": "A generic function and convention to trigger deprecation notices", 2462 | "homepage": "https://symfony.com", 2463 | "support": { 2464 | "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" 2465 | }, 2466 | "funding": [ 2467 | { 2468 | "url": "https://symfony.com/sponsor", 2469 | "type": "custom" 2470 | }, 2471 | { 2472 | "url": "https://github.com/fabpot", 2473 | "type": "github" 2474 | }, 2475 | { 2476 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2477 | "type": "tidelift" 2478 | } 2479 | ], 2480 | "time": "2024-09-25T14:21:43+00:00" 2481 | }, 2482 | { 2483 | "name": "symfony/polyfill-ctype", 2484 | "version": "v1.32.0", 2485 | "source": { 2486 | "type": "git", 2487 | "url": "https://github.com/symfony/polyfill-ctype.git", 2488 | "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" 2489 | }, 2490 | "dist": { 2491 | "type": "zip", 2492 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", 2493 | "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", 2494 | "shasum": "" 2495 | }, 2496 | "require": { 2497 | "php": ">=7.2" 2498 | }, 2499 | "provide": { 2500 | "ext-ctype": "*" 2501 | }, 2502 | "suggest": { 2503 | "ext-ctype": "For best performance" 2504 | }, 2505 | "type": "library", 2506 | "extra": { 2507 | "thanks": { 2508 | "url": "https://github.com/symfony/polyfill", 2509 | "name": "symfony/polyfill" 2510 | } 2511 | }, 2512 | "autoload": { 2513 | "files": [ 2514 | "bootstrap.php" 2515 | ], 2516 | "psr-4": { 2517 | "Symfony\\Polyfill\\Ctype\\": "" 2518 | } 2519 | }, 2520 | "notification-url": "https://packagist.org/downloads/", 2521 | "license": [ 2522 | "MIT" 2523 | ], 2524 | "authors": [ 2525 | { 2526 | "name": "Gert de Pagter", 2527 | "email": "BackEndTea@gmail.com" 2528 | }, 2529 | { 2530 | "name": "Symfony Community", 2531 | "homepage": "https://symfony.com/contributors" 2532 | } 2533 | ], 2534 | "description": "Symfony polyfill for ctype functions", 2535 | "homepage": "https://symfony.com", 2536 | "keywords": [ 2537 | "compatibility", 2538 | "ctype", 2539 | "polyfill", 2540 | "portable" 2541 | ], 2542 | "support": { 2543 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" 2544 | }, 2545 | "funding": [ 2546 | { 2547 | "url": "https://symfony.com/sponsor", 2548 | "type": "custom" 2549 | }, 2550 | { 2551 | "url": "https://github.com/fabpot", 2552 | "type": "github" 2553 | }, 2554 | { 2555 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2556 | "type": "tidelift" 2557 | } 2558 | ], 2559 | "time": "2024-09-09T11:45:10+00:00" 2560 | }, 2561 | { 2562 | "name": "symfony/polyfill-mbstring", 2563 | "version": "v1.32.0", 2564 | "source": { 2565 | "type": "git", 2566 | "url": "https://github.com/symfony/polyfill-mbstring.git", 2567 | "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" 2568 | }, 2569 | "dist": { 2570 | "type": "zip", 2571 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", 2572 | "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", 2573 | "shasum": "" 2574 | }, 2575 | "require": { 2576 | "ext-iconv": "*", 2577 | "php": ">=7.2" 2578 | }, 2579 | "provide": { 2580 | "ext-mbstring": "*" 2581 | }, 2582 | "suggest": { 2583 | "ext-mbstring": "For best performance" 2584 | }, 2585 | "type": "library", 2586 | "extra": { 2587 | "thanks": { 2588 | "url": "https://github.com/symfony/polyfill", 2589 | "name": "symfony/polyfill" 2590 | } 2591 | }, 2592 | "autoload": { 2593 | "files": [ 2594 | "bootstrap.php" 2595 | ], 2596 | "psr-4": { 2597 | "Symfony\\Polyfill\\Mbstring\\": "" 2598 | } 2599 | }, 2600 | "notification-url": "https://packagist.org/downloads/", 2601 | "license": [ 2602 | "MIT" 2603 | ], 2604 | "authors": [ 2605 | { 2606 | "name": "Nicolas Grekas", 2607 | "email": "p@tchwork.com" 2608 | }, 2609 | { 2610 | "name": "Symfony Community", 2611 | "homepage": "https://symfony.com/contributors" 2612 | } 2613 | ], 2614 | "description": "Symfony polyfill for the Mbstring extension", 2615 | "homepage": "https://symfony.com", 2616 | "keywords": [ 2617 | "compatibility", 2618 | "mbstring", 2619 | "polyfill", 2620 | "portable", 2621 | "shim" 2622 | ], 2623 | "support": { 2624 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" 2625 | }, 2626 | "funding": [ 2627 | { 2628 | "url": "https://symfony.com/sponsor", 2629 | "type": "custom" 2630 | }, 2631 | { 2632 | "url": "https://github.com/fabpot", 2633 | "type": "github" 2634 | }, 2635 | { 2636 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2637 | "type": "tidelift" 2638 | } 2639 | ], 2640 | "time": "2024-12-23T08:48:59+00:00" 2641 | }, 2642 | { 2643 | "name": "symfony/polyfill-php80", 2644 | "version": "v1.32.0", 2645 | "source": { 2646 | "type": "git", 2647 | "url": "https://github.com/symfony/polyfill-php80.git", 2648 | "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" 2649 | }, 2650 | "dist": { 2651 | "type": "zip", 2652 | "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", 2653 | "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", 2654 | "shasum": "" 2655 | }, 2656 | "require": { 2657 | "php": ">=7.2" 2658 | }, 2659 | "type": "library", 2660 | "extra": { 2661 | "thanks": { 2662 | "url": "https://github.com/symfony/polyfill", 2663 | "name": "symfony/polyfill" 2664 | } 2665 | }, 2666 | "autoload": { 2667 | "files": [ 2668 | "bootstrap.php" 2669 | ], 2670 | "psr-4": { 2671 | "Symfony\\Polyfill\\Php80\\": "" 2672 | }, 2673 | "classmap": [ 2674 | "Resources/stubs" 2675 | ] 2676 | }, 2677 | "notification-url": "https://packagist.org/downloads/", 2678 | "license": [ 2679 | "MIT" 2680 | ], 2681 | "authors": [ 2682 | { 2683 | "name": "Ion Bazan", 2684 | "email": "ion.bazan@gmail.com" 2685 | }, 2686 | { 2687 | "name": "Nicolas Grekas", 2688 | "email": "p@tchwork.com" 2689 | }, 2690 | { 2691 | "name": "Symfony Community", 2692 | "homepage": "https://symfony.com/contributors" 2693 | } 2694 | ], 2695 | "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", 2696 | "homepage": "https://symfony.com", 2697 | "keywords": [ 2698 | "compatibility", 2699 | "polyfill", 2700 | "portable", 2701 | "shim" 2702 | ], 2703 | "support": { 2704 | "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" 2705 | }, 2706 | "funding": [ 2707 | { 2708 | "url": "https://symfony.com/sponsor", 2709 | "type": "custom" 2710 | }, 2711 | { 2712 | "url": "https://github.com/fabpot", 2713 | "type": "github" 2714 | }, 2715 | { 2716 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2717 | "type": "tidelift" 2718 | } 2719 | ], 2720 | "time": "2025-01-02T08:10:11+00:00" 2721 | }, 2722 | { 2723 | "name": "symfony/polyfill-php82", 2724 | "version": "v1.32.0", 2725 | "source": { 2726 | "type": "git", 2727 | "url": "https://github.com/symfony/polyfill-php82.git", 2728 | "reference": "5d2ed36f7734637dacc025f179698031951b1692" 2729 | }, 2730 | "dist": { 2731 | "type": "zip", 2732 | "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/5d2ed36f7734637dacc025f179698031951b1692", 2733 | "reference": "5d2ed36f7734637dacc025f179698031951b1692", 2734 | "shasum": "" 2735 | }, 2736 | "require": { 2737 | "php": ">=7.2" 2738 | }, 2739 | "type": "library", 2740 | "extra": { 2741 | "thanks": { 2742 | "url": "https://github.com/symfony/polyfill", 2743 | "name": "symfony/polyfill" 2744 | } 2745 | }, 2746 | "autoload": { 2747 | "files": [ 2748 | "bootstrap.php" 2749 | ], 2750 | "psr-4": { 2751 | "Symfony\\Polyfill\\Php82\\": "" 2752 | }, 2753 | "classmap": [ 2754 | "Resources/stubs" 2755 | ] 2756 | }, 2757 | "notification-url": "https://packagist.org/downloads/", 2758 | "license": [ 2759 | "MIT" 2760 | ], 2761 | "authors": [ 2762 | { 2763 | "name": "Nicolas Grekas", 2764 | "email": "p@tchwork.com" 2765 | }, 2766 | { 2767 | "name": "Symfony Community", 2768 | "homepage": "https://symfony.com/contributors" 2769 | } 2770 | ], 2771 | "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions", 2772 | "homepage": "https://symfony.com", 2773 | "keywords": [ 2774 | "compatibility", 2775 | "polyfill", 2776 | "portable", 2777 | "shim" 2778 | ], 2779 | "support": { 2780 | "source": "https://github.com/symfony/polyfill-php82/tree/v1.32.0" 2781 | }, 2782 | "funding": [ 2783 | { 2784 | "url": "https://symfony.com/sponsor", 2785 | "type": "custom" 2786 | }, 2787 | { 2788 | "url": "https://github.com/fabpot", 2789 | "type": "github" 2790 | }, 2791 | { 2792 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2793 | "type": "tidelift" 2794 | } 2795 | ], 2796 | "time": "2024-09-09T11:45:10+00:00" 2797 | }, 2798 | { 2799 | "name": "tbachert/spi", 2800 | "version": "v1.0.3", 2801 | "source": { 2802 | "type": "git", 2803 | "url": "https://github.com/Nevay/spi.git", 2804 | "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a" 2805 | }, 2806 | "dist": { 2807 | "type": "zip", 2808 | "url": "https://api.github.com/repos/Nevay/spi/zipball/506a79c98e1a51522e76ee921ccb6c62d52faf3a", 2809 | "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a", 2810 | "shasum": "" 2811 | }, 2812 | "require": { 2813 | "composer-plugin-api": "^2.0", 2814 | "composer/semver": "^1.0 || ^2.0 || ^3.0", 2815 | "php": "^8.1" 2816 | }, 2817 | "require-dev": { 2818 | "composer/composer": "^2.0", 2819 | "infection/infection": "^0.27.9", 2820 | "phpunit/phpunit": "^10.5", 2821 | "psalm/phar": "^5.18" 2822 | }, 2823 | "type": "composer-plugin", 2824 | "extra": { 2825 | "class": "Nevay\\SPI\\Composer\\Plugin", 2826 | "branch-alias": { 2827 | "dev-main": "0.2.x-dev" 2828 | }, 2829 | "plugin-optional": true 2830 | }, 2831 | "autoload": { 2832 | "psr-4": { 2833 | "Nevay\\SPI\\": "src/" 2834 | } 2835 | }, 2836 | "notification-url": "https://packagist.org/downloads/", 2837 | "license": [ 2838 | "Apache-2.0" 2839 | ], 2840 | "description": "Service provider loading facility", 2841 | "keywords": [ 2842 | "service provider" 2843 | ], 2844 | "support": { 2845 | "issues": "https://github.com/Nevay/spi/issues", 2846 | "source": "https://github.com/Nevay/spi/tree/v1.0.3" 2847 | }, 2848 | "time": "2025-04-02T19:38:14+00:00" 2849 | }, 2850 | { 2851 | "name": "vlucas/phpdotenv", 2852 | "version": "v5.6.2", 2853 | "source": { 2854 | "type": "git", 2855 | "url": "https://github.com/vlucas/phpdotenv.git", 2856 | "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" 2857 | }, 2858 | "dist": { 2859 | "type": "zip", 2860 | "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", 2861 | "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", 2862 | "shasum": "" 2863 | }, 2864 | "require": { 2865 | "ext-pcre": "*", 2866 | "graham-campbell/result-type": "^1.1.3", 2867 | "php": "^7.2.5 || ^8.0", 2868 | "phpoption/phpoption": "^1.9.3", 2869 | "symfony/polyfill-ctype": "^1.24", 2870 | "symfony/polyfill-mbstring": "^1.24", 2871 | "symfony/polyfill-php80": "^1.24" 2872 | }, 2873 | "require-dev": { 2874 | "bamarni/composer-bin-plugin": "^1.8.2", 2875 | "ext-filter": "*", 2876 | "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" 2877 | }, 2878 | "suggest": { 2879 | "ext-filter": "Required to use the boolean validator." 2880 | }, 2881 | "type": "library", 2882 | "extra": { 2883 | "bamarni-bin": { 2884 | "bin-links": true, 2885 | "forward-command": false 2886 | }, 2887 | "branch-alias": { 2888 | "dev-master": "5.6-dev" 2889 | } 2890 | }, 2891 | "autoload": { 2892 | "psr-4": { 2893 | "Dotenv\\": "src/" 2894 | } 2895 | }, 2896 | "notification-url": "https://packagist.org/downloads/", 2897 | "license": [ 2898 | "BSD-3-Clause" 2899 | ], 2900 | "authors": [ 2901 | { 2902 | "name": "Graham Campbell", 2903 | "email": "hello@gjcampbell.co.uk", 2904 | "homepage": "https://github.com/GrahamCampbell" 2905 | }, 2906 | { 2907 | "name": "Vance Lucas", 2908 | "email": "vance@vancelucas.com", 2909 | "homepage": "https://github.com/vlucas" 2910 | } 2911 | ], 2912 | "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", 2913 | "keywords": [ 2914 | "dotenv", 2915 | "env", 2916 | "environment" 2917 | ], 2918 | "support": { 2919 | "issues": "https://github.com/vlucas/phpdotenv/issues", 2920 | "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" 2921 | }, 2922 | "funding": [ 2923 | { 2924 | "url": "https://github.com/GrahamCampbell", 2925 | "type": "github" 2926 | }, 2927 | { 2928 | "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", 2929 | "type": "tidelift" 2930 | } 2931 | ], 2932 | "time": "2025-04-30T23:37:27+00:00" 2933 | } 2934 | ], 2935 | "packages-dev": [ 2936 | { 2937 | "name": "phpstan/phpstan", 2938 | "version": "1.12.7", 2939 | "source": { 2940 | "type": "git", 2941 | "url": "https://github.com/phpstan/phpstan.git", 2942 | "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0" 2943 | }, 2944 | "dist": { 2945 | "type": "zip", 2946 | "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", 2947 | "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", 2948 | "shasum": "" 2949 | }, 2950 | "require": { 2951 | "php": "^7.2|^8.0" 2952 | }, 2953 | "conflict": { 2954 | "phpstan/phpstan-shim": "*" 2955 | }, 2956 | "bin": [ 2957 | "phpstan", 2958 | "phpstan.phar" 2959 | ], 2960 | "type": "library", 2961 | "autoload": { 2962 | "files": [ 2963 | "bootstrap.php" 2964 | ] 2965 | }, 2966 | "notification-url": "https://packagist.org/downloads/", 2967 | "license": [ 2968 | "MIT" 2969 | ], 2970 | "description": "PHPStan - PHP Static Analysis Tool", 2971 | "keywords": [ 2972 | "dev", 2973 | "static analysis" 2974 | ], 2975 | "support": { 2976 | "docs": "https://phpstan.org/user-guide/getting-started", 2977 | "forum": "https://github.com/phpstan/phpstan/discussions", 2978 | "issues": "https://github.com/phpstan/phpstan/issues", 2979 | "security": "https://github.com/phpstan/phpstan/security/policy", 2980 | "source": "https://github.com/phpstan/phpstan-src" 2981 | }, 2982 | "funding": [ 2983 | { 2984 | "url": "https://github.com/ondrejmirtes", 2985 | "type": "github" 2986 | }, 2987 | { 2988 | "url": "https://github.com/phpstan", 2989 | "type": "github" 2990 | } 2991 | ], 2992 | "time": "2024-10-18T11:12:07+00:00" 2993 | } 2994 | ], 2995 | "aliases": [], 2996 | "minimum-stability": "dev", 2997 | "stability-flags": [], 2998 | "prefer-stable": true, 2999 | "prefer-lowest": false, 3000 | "platform": [], 3001 | "platform-dev": [], 3002 | "plugin-api-version": "2.3.0" 3003 | } 3004 | -------------------------------------------------------------------------------- /user-auth/graphtutorial/main.php: -------------------------------------------------------------------------------- 1 | 6 | // Enable loading of Composer dependencies 7 | require_once realpath(__DIR__ . '/vendor/autoload.php'); 8 | require_once 'GraphHelper.php'; 9 | 10 | print('PHP Graph Tutorial'.PHP_EOL.PHP_EOL); 11 | 12 | // Load .env file 13 | $dotenv = Dotenv\Dotenv::createImmutable(__DIR__); 14 | $dotenv->load(); 15 | $dotenv->required(['CLIENT_ID', 'TENANT_ID', 'GRAPH_USER_SCOPES']); 16 | 17 | initializeGraph(); 18 | 19 | greetUser(); 20 | 21 | $choice = -1; 22 | 23 | while ($choice != 0) { 24 | echo('Please choose one of the following options:'.PHP_EOL); 25 | echo('0. Exit'.PHP_EOL); 26 | echo('1. Display access token'.PHP_EOL); 27 | echo('2. List my inbox'.PHP_EOL); 28 | echo('3. Send mail'.PHP_EOL); 29 | echo('4. Make a Graph call'.PHP_EOL); 30 | 31 | $choice = (int)readline(''); 32 | 33 | switch ($choice) { 34 | case 1: 35 | displayAccessToken(); 36 | break; 37 | case 2: 38 | listInbox(); 39 | break; 40 | case 3: 41 | sendMail(); 42 | break; 43 | case 4: 44 | makeGraphCall(); 45 | break; 46 | case 0: 47 | default: 48 | print('Goodbye...'.PHP_EOL); 49 | } 50 | } 51 | // 52 | 53 | // 54 | function initializeGraph(): void { 55 | GraphHelper::initializeGraphForUserAuth(); 56 | } 57 | // 58 | 59 | // 60 | function greetUser(): void { 61 | try { 62 | $user = GraphHelper::getUser(); 63 | print('Hello, '.$user->getDisplayName().'!'.PHP_EOL); 64 | 65 | // For Work/school accounts, email is in Mail property 66 | // Personal accounts, email is in UserPrincipalName 67 | $email = $user->getMail(); 68 | if (empty($email)) { 69 | $email = $user->getUserPrincipalName(); 70 | } 71 | print('Email: '.$email.PHP_EOL.PHP_EOL); 72 | } catch (Exception $e) { 73 | print('Error getting user: '.$e->getMessage().PHP_EOL.PHP_EOL); 74 | } 75 | } 76 | // 77 | 78 | // 79 | function displayAccessToken(): void { 80 | try { 81 | $token = GraphHelper::getUserToken(); 82 | print('User token: '.$token.PHP_EOL.PHP_EOL); 83 | } catch (Exception $e) { 84 | print('Error getting access token: '.$e->getMessage().PHP_EOL.PHP_EOL); 85 | } 86 | } 87 | // 88 | 89 | // 90 | function listInbox(): void { 91 | try { 92 | $messages = GraphHelper::getInbox(); 93 | 94 | // Output each message's details 95 | foreach ($messages->getValue() as $message) { 96 | print('Message: '.$message->getSubject().PHP_EOL); 97 | print(' From: '.$message->getFrom()->getEmailAddress()->getName().PHP_EOL); 98 | $status = $message->getIsRead() ? "Read" : "Unread"; 99 | print(' Status: '.$status.PHP_EOL); 100 | print(' Received: '.$message->getReceivedDateTime()->format(\DateTimeInterface::RFC2822).PHP_EOL); 101 | } 102 | 103 | $nextLink = $messages->getOdataNextLink(); 104 | $moreAvailable = isset($nextLink) && $nextLink != '' ? 'True' : 'False'; 105 | print(PHP_EOL.'More messages available? '.$moreAvailable.PHP_EOL.PHP_EOL); 106 | } catch (Exception $e) { 107 | print('Error getting user\'s inbox: '.$e->getMessage().PHP_EOL.PHP_EOL); 108 | } 109 | } 110 | // 111 | 112 | // 113 | function sendMail(): void { 114 | try { 115 | // Send mail to the signed-in user 116 | // Get the user for their email address 117 | $user = GraphHelper::getUser(); 118 | 119 | // For Work/school accounts, email is in Mail property 120 | // Personal accounts, email is in UserPrincipalName 121 | $email = $user->getMail(); 122 | if (empty($email)) { 123 | $email = $user->getUserPrincipalName(); 124 | } 125 | 126 | GraphHelper::sendMail('Testing Microsoft Graph', 'Hello world!', $email); 127 | 128 | print(PHP_EOL.'Mail sent.'.PHP_EOL.PHP_EOL); 129 | } catch (Exception $e) { 130 | print('Error sending mail: '.$e->getMessage().PHP_EOL.PHP_EOL); 131 | } 132 | } 133 | // 134 | 135 | // 136 | function makeGraphCall(): void { 137 | try { 138 | GraphHelper::makeGraphCall(); 139 | } catch (Exception $e) { 140 | print(PHP_EOL.'Error making Graph call'.PHP_EOL.PHP_EOL); 141 | } 142 | } 143 | // 144 | ?> 145 | -------------------------------------------------------------------------------- /user-auth/graphtutorial/phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | excludePaths: 3 | - vendor/* 4 | -------------------------------------------------------------------------------- /user-auth/version: -------------------------------------------------------------------------------- 1 | 1.2 2 | --------------------------------------------------------------------------------