Skip to content

Commit 6d9f005

Browse files
Merge branch 'dcblogdev:master' into master
2 parents 18674e5 + c34d9fc commit 6d9f005

File tree

13 files changed

+252
-38
lines changed

13 files changed

+252
-38
lines changed

.github/workflows/php.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
run: composer install --prefer-dist --no-progress
3131

3232
- name: Run Pint
33-
run: ./vendor/bin/pint --test
33+
run: ./vendor/bin/pint
3434

3535
- name: Run test suite
3636
run: ./vendor/bin/pest --parallel

docs/v3/msgraph/emails.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ To view an email call **->find($id)** followed by the id of the email.
134134
MsGraph::emails()->find($id);
135135
```
136136

137+
Retrieve the emails using singleValueExtendedProperties.
138+
139+
```php
140+
MsGraph::emails()->get([
141+
'\$filter' => 'singleValueExtendedProperties/Any(ep: ep/id eq \'String {00020329-0000-0000-C000-000000000046} Name CustomProperty\' and ep/value eq \'CustomValue\')'
142+
]);
143+
```
144+
137145
## Send Email
138146

139147
To send an email the format is different to normal calls. The format is to call multiple methods to set the email properties.
@@ -172,6 +180,22 @@ MsGraph::emails()
172180
->send()
173181
```
174182

183+
singleValueExtendedProperties() can be used to add custom properties to the email.
184+
185+
```php
186+
MsGraph::emails()
187+
->to(['email@domains.com'])
188+
->subject('the subject')
189+
->body('the content')
190+
->singleValueExtendedProperties([
191+
[
192+
"id" => "String {00020329-0000-0000-C000-000000000046} Name CustomProperty",
193+
"value" => "CustomValue"
194+
]
195+
])
196+
->send()
197+
```
198+
175199
## Forward Email
176200

177201
To forward to an email call **->forward()** and use **->comment()** instead of **->body()**.
@@ -205,7 +229,3 @@ To delete an email call **->delete($id)** followed by the id of the email.
205229
```php
206230
MsGraph::emails()->delete($id);
207231
```
208-
209-
210-
211-

docs/v3/msgraph/queues.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
title: Queues
3+
---
4+
5+
When using `MsGraph` within jobs, commands, or other queued processes, you need to authenticate the user explicitly. Ensure the user model has `access_token` and `refresh_token` stored in the database. Use the `login` method to authenticate the user before making any API calls:
6+
7+
```php
8+
MsGraph::login(User::find(1));
9+
MsGraph::get('me');
10+
```
11+
12+
Here's an example of how to structure a job that uses `MsGraph`:
13+
14+
```php
15+
<?php
16+
17+
namespace App\Jobs;
18+
19+
use App\Models\User;
20+
use Dcblogdev\MsGraph\Facades\MsGraph;
21+
use Illuminate\Bus\Queueable;
22+
use Illuminate\Contracts\Queue\ShouldQueue;
23+
use Illuminate\Foundation\Bus\Dispatchable;
24+
use Illuminate\Queue\InteractsWithQueue;
25+
use Illuminate\Queue\SerializesModels;
26+
27+
class ExampleMsGraphJob implements ShouldQueue
28+
{
29+
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
30+
31+
protected $user;
32+
33+
public function __construct(User $user)
34+
{
35+
$this->user = $user;
36+
}
37+
38+
public function handle(): void
39+
{
40+
MsGraph::login($this->user);
41+
$userData = MsGraph::get('me');
42+
// Process $userData as needed
43+
}
44+
}
45+
```
46+
47+
Dispatch this job with a user instance:
48+
49+
```php
50+
ExampleMsGraphJob::dispatch($user);
51+
```
52+
53+
This approach ensures that the Microsoft Graph API calls are made with the correct user context, even in background processes.

docs/v3/nav.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
'name' => 'Middleware',
2626
'url' => 'msgraph/middleware',
2727
],
28+
[
29+
'name' => 'Queues',
30+
'url' => 'msgraph/queues',
31+
],
2832
[
2933
'name' => 'Login with MsGraph',
3034
'url' => 'msgraph/login-with-msgraph',

src/Events/NewMicrosoft365SignInEvent.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,5 @@ class NewMicrosoft365SignInEvent
1414

1515
public function __construct(public array $token)
1616
{
17-
1817
}
1918
}

src/MsGraph.php

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,36 @@ class MsGraph
2828
{
2929
public function contacts(): Contacts
3030
{
31-
return new Contacts();
31+
return new Contacts;
3232
}
3333

3434
public function emails(): Emails
3535
{
36-
return new Emails();
36+
return new Emails;
3737
}
3838

3939
public function files(): Files
4040
{
41-
return new Files();
41+
return new Files;
4242
}
4343

4444
public function sites(): Sites
4545
{
46-
return new Sites();
46+
return new Sites;
4747
}
4848

4949
public function tasklists(): TaskLists
5050
{
51-
return new TaskLists();
51+
return new TaskLists;
5252
}
5353

5454
public function tasks(): Tasks
5555
{
56-
return new Tasks();
56+
return new Tasks;
5757
}
5858

59+
protected static $user;
60+
5961
protected static string $baseUrl = 'https://graph.microsoft.com/v1.0/';
6062

6163
protected static string $userModel = '';
@@ -83,7 +85,17 @@ public static function setUserModel(string $model): static
8385
{
8486
self::$userModel = $model;
8587

86-
return new static();
88+
return new static;
89+
}
90+
91+
public static function login($user)
92+
{
93+
self::$user = $user;
94+
}
95+
96+
public static function getUser()
97+
{
98+
return self::$user;
8799
}
88100

89101
/**
@@ -116,7 +128,18 @@ public function connect(?string $id = null): Redirector|RedirectResponse
116128

117129
if (request()->has('code')) {
118130

119-
$accessToken = $provider->getAccessToken('authorization_code', ['code' => request('code')]);
131+
try {
132+
$accessToken = $provider->getAccessToken('authorization_code', ['code' => request('code')]);
133+
} catch (IdentityProviderException $e) {
134+
135+
$response = $e->getResponseBody();
136+
137+
$errorMessage = "{$response['error']} {$response['error_description']}\n".
138+
'Error Code: '.($response['error_codes'][0] ?? 'N/A')."\n".
139+
'More Info: '.($response['error_uri'] ?? 'N/A');
140+
141+
throw new Exception($errorMessage);
142+
}
120143

121144
if (auth()->check()) {
122145
$this->storeToken(
@@ -171,8 +194,8 @@ public function getAccessToken(?string $id = null, bool $redirectWhenNotConnecte
171194
$token = $this->getTokenData($id);
172195
$id = $this->getUserId($id);
173196

174-
if ($redirectWhenNotConnected) {
175-
if (! $this->isConnected()) {
197+
if ($this->getUser() === null && $redirectWhenNotConnected) {
198+
if (! $this->isConnected($id)) {
176199
return redirect()->away(config('msgraph.redirectUri'));
177200
}
178201
}
@@ -197,7 +220,7 @@ public function getTokenData(?string $id = null): ?MsGraphToken
197220
return MsGraphToken::where('user_id', $id)->where('refresh_token', '<>', '')->first();
198221
}
199222

200-
public function storeToken(string $access_token, string $refresh_token, string $expires, int $id, string $email): MsGraphToken
223+
public function storeToken(string $access_token, string $refresh_token, string $expires, string $id, string $email): MsGraphToken
201224
{
202225
return MsGraphToken::updateOrCreate(['user_id' => $id], [
203226
'user_id' => $id,
@@ -324,6 +347,10 @@ protected function isJson(string $string): bool
324347

325348
protected function getUserId(?string $id = null): ?string
326349
{
350+
if ($this->getUser() !== null) {
351+
$id = $this->getUser()->id;
352+
}
353+
327354
if ($id === null) {
328355
$id = auth()->id();
329356
}
@@ -334,6 +361,9 @@ protected function getUserId(?string $id = null): ?string
334361
protected function getProvider(): GenericProvider
335362
{
336363
app()->singleton(GenericProvider::class, function () {
364+
365+
$codeVerifier = bin2hex(random_bytes(32));
366+
337367
return new GenericProvider([
338368
'clientId' => config('msgraph.clientId'),
339369
'clientSecret' => config('msgraph.clientSecret'),
@@ -342,6 +372,10 @@ protected function getProvider(): GenericProvider
342372
'urlAccessToken' => config('msgraph.urlAccessToken'),
343373
'urlResourceOwnerDetails' => config('msgraph.urlResourceOwnerDetails'),
344374
'scopes' => config('msgraph.scopes'),
375+
'code_challenge_method' => 'S256',
376+
'code_challenge' => rtrim(
377+
strtr(base64_encode(hash('sha256', $codeVerifier, true)), '+/', '-_'), '='
378+
),
345379
]);
346380
});
347381

src/MsGraphAdmin.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ protected function isJson(string $data): bool
170170
/**
171171
* @throws Exception
172172
*/
173-
protected function guzzle(string $type, string $request, array $data = []): mixed
173+
protected function guzzle(string $type, string $request, ?array $data = []): mixed
174174
{
175175
try {
176176
$client = new Client;

src/Resources/Contacts.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function update(string $id, array $data): array
4040
return MsGraph::patch("me/contacts/$id", $data);
4141
}
4242

43-
public function delete(string $id): array
43+
public function delete(string $id): string
4444
{
4545
return MsGraph::delete("me/contacts/$id");
4646
}

src/Resources/Emails.php

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class Emails extends MsGraph
2727

2828
private array $attachments = [];
2929

30+
private array $singleValueExtendedProperties = [];
31+
3032
public function id(string $id): static
3133
{
3234
$this->id = $id;
@@ -83,6 +85,13 @@ public function attachments(array $attachments): static
8385
return $this;
8486
}
8587

88+
public function singleValueExtendedProperties(array $singleValueExtendedProperties): static
89+
{
90+
$this->singleValueExtendedProperties = $singleValueExtendedProperties;
91+
92+
return $this;
93+
}
94+
8695
public function top(string $top): static
8796
{
8897
$this->top = $top;
@@ -246,6 +255,7 @@ protected function prepareEmail(): array
246255
$cc = $this->cc;
247256
$bcc = $this->bcc;
248257
$attachments = $this->attachments;
258+
$singleValueExtendedProperties = $this->singleValueExtendedProperties;
249259

250260
$toArray = [];
251261
foreach ($to as $email) {
@@ -264,13 +274,29 @@ protected function prepareEmail(): array
264274

265275
$attachmentArray = [];
266276
foreach ($attachments as $file) {
267-
$path = pathinfo($file);
277+
if (array_key_exists('name', $file) && array_key_exists('contentBytes', $file)) {
278+
$attachmentArray[] = [
279+
'@odata.type' => '#microsoft.graph.fileAttachment',
280+
'name' => $file['name'],
281+
'contentBytes' => $file['contentBytes'],
282+
];
283+
} else {
284+
$path = pathinfo($file);
285+
286+
$attachmentArray[] = [
287+
'@odata.type' => '#microsoft.graph.fileAttachment',
288+
'name' => $path['basename'],
289+
'contentType' => mime_content_type($file),
290+
'contentBytes' => base64_encode(file_get_contents($file)),
291+
];
292+
}
293+
}
268294

269-
$attachmentArray[] = [
270-
'@odata.type' => '#microsoft.graph.fileAttachment',
271-
'name' => $path['basename'],
272-
'contentType' => mime_content_type($file),
273-
'contentBytes' => base64_encode(file_get_contents($file)),
295+
$singleValueExtendedPropertiesarray = [];
296+
foreach ($singleValueExtendedProperties as $value) {
297+
$singleValueExtendedPropertiesarray[] = [
298+
'id' => $value['id'],
299+
'value' => $value['value'],
274300
];
275301
}
276302

src/Resources/Files.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ public function downloadFile(string $id, string $type = 'me'): object
4242
return redirect()->away($id['@microsoft.graph.downloadUrl']);
4343
}
4444

45-
public function deleteFile(string $id, string $type = 'me'): array
45+
public function deleteFile(string $id, string $type = 'me'): string
4646
{
4747
return MsGraph::delete($type."/drive/items/$id");
4848
}
4949

50-
public function createFolder(string $name, string $path, string $type = 'me', string $behavior = 'rename'): array
50+
public function createFolder(string $name, string $path = '', string $type = 'me', string $behavior = 'rename'): array
5151
{
5252
$path = $path === '' ? $type.'/drive/root/children' : $type.'/drive/root:'.$this->forceStartingSlash($path).':/children';
5353

@@ -75,6 +75,7 @@ public function rename(string $name, string $id, string $type = 'me'): array
7575
public function upload(string $name, string $uploadPath, string $path = '', string $type = 'me', string $behavior = 'rename'): void
7676
{
7777
$uploadSession = $this->createUploadSession($name, $path, $type, $behavior);
78+
dd($uploadSession);
7879
$uploadUrl = $uploadSession['uploadUrl'];
7980

8081
$fragSize = 320 * 1024;

0 commit comments

Comments
 (0)