├── .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 | [](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 |
--------------------------------------------------------------------------------