Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractOffice365
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
5 / 5
17
100.00% covered (success)
100.00%
1 / 1
 createClient
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
3
 setTenantId
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getTenantId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasTenantId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 requestToken
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
11
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <dev@noladev.com>
8 * @copyright  Copyright (c) 2009-2027 NOLA Interactive, LLC.
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Mail\Api;
16
17use Pop\Http;
18
19/**
20 * Abstract Office 365 Mail API class
21 *
22 * @category   Pop
23 * @package    Pop\Mail
24 * @author     Nick Sagona, III <dev@noladev.com>
25 * @copyright  Copyright (c) 2009-2027 NOLA Interactive, LLC.
26 * @license    https://www.popphp.org/license     New BSD License
27 * @version    5.0.0
28 */
29abstract class AbstractOffice365 extends AbstractHttpClient
30{
31
32    /**
33     * Tenant ID
34     * @var ?string
35     */
36    protected ?string $tenantId = null;
37
38    /**
39     * Token request URI
40     * @var ?string
41     */
42    protected ?string $tokenRequestUri = 'https://login.microsoftonline.com/[{tenant_id}]/oauth2/v2.0/token';
43
44    /**
45     * Base URL
46     * @var ?string
47     */
48    protected ?string $baseUri = 'https://graph.microsoft.com/v1.0/users';
49
50    /**
51     * Create client
52     *
53     * @param  array|string $options
54     * @throws Exception
55     * @return AbstractOffice365
56     */
57    public function createClient(array|string $options): AbstractOffice365
58    {
59        if (is_string($options)) {
60            $options = $this->parseOptions($options);
61        }
62
63        $this->clientId     = $options['client_id'] ?? null;
64        $this->clientSecret = $options['client_secret'] ?? null;
65        $this->scope        = $options['scope'] ?? null;
66        $this->tenantId     = $options['tenant_id'] ?? null;
67        $this->accountId    = $options['account_id'] ?? null;
68        $this->username     = $options['username'] ?? null;
69
70        if ($this->accountId === null) {
71            throw new Exception('Error: The account ID is required to create the client object.');
72        }
73
74        $this->client = new Http\Client([
75            'base_uri' => $this->baseUri
76        ]);
77
78        return $this;
79    }
80
81    /**
82     * Set tenant ID
83     *
84     * @param  string $tenantId
85     * @return AbstractOffice365
86     */
87    public function setTenantId(string $tenantId): AbstractOffice365
88    {
89        $this->tenantId = $tenantId;
90        return $this;
91    }
92
93    /**
94     * Get tenant ID
95     *
96     * @return ?string
97     */
98    public function getTenantId(): ?string
99    {
100        return $this->tenantId;
101    }
102
103    /**
104     * Has tenant ID
105     *
106     * @return bool
107     */
108    public function hasTenantId(): bool
109    {
110        return ($this->tenantId !== null);
111    }
112
113    /**
114     * Request token
115     *
116     * @throws Exception|Http\Exception|Http\Client\Exception|Http\Client\Handler\Exception
117     * @return AbstractOffice365
118     */
119    public function requestToken(): AbstractOffice365
120    {
121        if (empty($this->tenantId) || empty($this->clientId) || empty($this->scope) || empty($this->clientSecret)) {
122            throw new Exception('Error: The required credentials have not been set.');
123        } else {
124            if (isset($this->token) && isset($this->tokenExpires) && !$this->isTokenExpired()) {
125                return $this;
126            }
127        }
128
129        $tokenRequestUri = str_replace('[{tenant_id}]', $this->tenantId, $this->tokenRequestUri);
130
131        $client = new Http\Client($tokenRequestUri, [
132            'method' => 'POST',
133            'auto'   => true,
134            'data'   => [
135                'grant_type'    => 'client_credentials',
136                'client_id'     => $this->clientId,
137                'scope'         => $this->scope,
138                'client_secret' => $this->clientSecret,
139            ]
140        ], $this->handler);
141
142        $response = $client->send();
143
144        if (is_array($response) && isset($response['access_token']) && isset($response['expires_in'])) {
145            $this->setToken($response['access_token'])
146                ->setTokenExpires((string)(time() + $response['expires_in']));
147        }
148
149        return $this;
150    }
151
152}