diff --git a/src/MsGraph.php b/src/MsGraph.php index cae0207..2094237 100755 --- a/src/MsGraph.php +++ b/src/MsGraph.php @@ -9,7 +9,7 @@ use Dcblogdev\MsGraph\Events\NewMicrosoft365SignInEvent; use Dcblogdev\MsGraph\Models\MsGraphToken; use Dcblogdev\MsGraph\Resources\Contacts; -use Dcblogdev\MsGraph\Resources\Emails; +use Dcblogdev\MsGraph\Resources\Emails\Emails; use Dcblogdev\MsGraph\Resources\Files; use Dcblogdev\MsGraph\Resources\Sites; use Dcblogdev\MsGraph\Resources\Tasks\TaskLists; @@ -340,7 +340,8 @@ protected function guzzle(string $type, string $request, array $data = [], array return $responseObject; } catch (ClientException $e) { - return json_decode(($e->getResponse()->getBody()->getContents())); + throw new Exception($e->getMessage()); + //return json_decode(($e->getResponse()->getBody()->getContents())); } catch (Exception $e) { throw new Exception($e->getMessage()); } diff --git a/src/Resources/Emails.php b/src/Resources/Emails/Emails.php similarity index 98% rename from src/Resources/Emails.php rename to src/Resources/Emails/Emails.php index 73ff4e2..f76d07d 100644 --- a/src/Resources/Emails.php +++ b/src/Resources/Emails/Emails.php @@ -1,12 +1,17 @@ fetchSubfolders($folders['value']); + + if ($sort) { + $allFolders = $this->sortFolders($allFolders, $priorityOrder); + } + + return array_merge($folders, ['value' => $allFolders]); + } + + public function find(string $id): array + { + return MsGraph::get('me/mailFolders/'.$id); + } + + public function store(array $data): array + { + EmailFolderStoreValidator::validate($data); + + return MsGraph::post('me/mailFolders', $data); + } + + public function update(array $data, string $id): array + { + EmailFolderUpdateValidator::validate($data); + + return MsGraph::patch('me/mailFolders/'.$id, $data); + } + + public function copy(array $data, string $id): array + { + EmailFolderCopyValidator::validate($data); + + return MsGraph::post('me/mailFolders/'.$id.'/copy', $data); + } + + public function move(array $data, string $id): array + { + EmailFolderCopyValidator::validate($data); + + return MsGraph::post('me/mailFolders/'.$id.'/copy', $data); + } + + public function delete(string $id): void + { + MsGraph::delete('me/mailFolders/'.$id); + } + + protected function fetchSubfolders(array $folders): array + { + foreach ($folders as &$folder) { + $subfolders = MsGraph::get("me/mailFolders/{$folder['id']}/childFolders?\$top=500"); + $folder['subfolders'] = ! empty($subfolders['value']) ? $this->fetchSubfolders($subfolders['value']) : []; + } + + return $folders; + } + + protected function sortFolders(array $folders, array $priorityOrder = []): array + { + // Default folder priority if none provided + $defaultPriority = [ + 'Inbox' => 1, + 'Archive' => 2, + 'Drafts' => 3, + 'Sent Items' => 4, + 'Deleted Items' => 5, + 'Conversation History' => 6, + 'Junk Email' => 7, + ]; + + // Use provided priority order or fallback to default + $priority = ! empty($priorityOrder) ? $priorityOrder : $defaultPriority; + + usort($folders, function ($a, $b) use ($priority) { + $aPriority = $priority[$a['displayName']] ?? 100; + $bPriority = $priority[$b['displayName']] ?? 100; + + return $aPriority === $bPriority + ? strcmp($a['displayName'], $b['displayName']) + : $aPriority <=> $bPriority; + }); + + // Sort subfolders recursively + foreach ($folders as &$folder) { + if (! empty($folder['subfolders'])) { + $folder['subfolders'] = $this->sortFolders($folder['subfolders']); + } + } + + return $folders; + } +} \ No newline at end of file diff --git a/src/Validators/EmailFolderCopyValidator.php b/src/Validators/EmailFolderCopyValidator.php new file mode 100644 index 0000000..efc09f2 --- /dev/null +++ b/src/Validators/EmailFolderCopyValidator.php @@ -0,0 +1,25 @@ + 'demo' + ]); + + expect($response)->toEqual([ + 'destinationId' => 'demo' + ]); +}); + +test('throws exception for unrecognized parameters', function () { + EmailFolderCopyValidator::validate([ + '$top' => 10, + ]); +})->throws(InvalidArgumentException::class, 'Invalid parameters: $top. Allowed parameters: destinationId.'); + +test('throws exception if destinationId is not a string', function () { + EmailFolderCopyValidator::validate(['destinationId' => 1]); +})->throws(InvalidArgumentException::class, 'The destinationId must be a string.'); + +test('allows empty input without throwing an exception', function () { + $response = EmailFolderCopyValidator::validate([]); + expect($response)->toBe([]); +}); diff --git a/tests/Validators/EmailFolderMoveValidatorTest.php b/tests/Validators/EmailFolderMoveValidatorTest.php new file mode 100644 index 0000000..3de3dfe --- /dev/null +++ b/tests/Validators/EmailFolderMoveValidatorTest.php @@ -0,0 +1,28 @@ + 'demo', + ]); + + expect($response)->toEqual([ + 'destinationId' => 'demo', + ]); +}); + +test('throws exception for unrecognized parameters', function () { + EmailFolderMoveValidator::validate([ + '$top' => 10, + ]); +})->throws(InvalidArgumentException::class, 'Invalid parameters: $top. Allowed parameters: destinationId.'); + +test('throws exception if destinationId is not a string', function () { + EmailFolderMoveValidator::validate(['destinationId' => 1]); +})->throws(InvalidArgumentException::class, 'The destinationId must be a string.'); + +test('allows empty input without throwing an exception', function () { + $response = EmailFolderMoveValidator::validate([]); + expect($response)->toBe([]); +}); diff --git a/tests/Validators/EmailFolderStoreValidatorTest.php b/tests/Validators/EmailFolderStoreValidatorTest.php new file mode 100644 index 0000000..67c31ae --- /dev/null +++ b/tests/Validators/EmailFolderStoreValidatorTest.php @@ -0,0 +1,38 @@ + 'demo', + 'isHidden' => false, + ]); + + expect($response)->toEqual([ + 'displayName' => 'demo', + 'isHidden' => false, + ]); +}); + +test('throws exception for unrecognized parameters', function () { + EmailFolderStoreValidator::validate([ + '$top' => 10, + ]); +})->throws(InvalidArgumentException::class, 'Invalid parameters: $top. Allowed parameters: displayName, isHidden.'); + +test('throws exception if displayName is not a string', function () { + EmailFolderStoreValidator::validate(['displayName' => 1]); +})->throws(InvalidArgumentException::class, 'The displayName must be a string.'); + +test('throws exception if isHidden is not a boolean', function () { + EmailFolderStoreValidator::validate(['isHidden' => 'true']); +})->throws(InvalidArgumentException::class, 'The isHidden must be a boolean.'); + +test('throws exception if isHidden is an integer', function () { + EmailFolderStoreValidator::validate(['isHidden' => 1]); +})->throws(InvalidArgumentException::class, 'The isHidden must be a boolean.'); + +test('allows empty input without throwing an exception', function () { + $response = EmailFolderStoreValidator::validate([]); + expect($response)->toBe([]); +}); diff --git a/tests/Validators/EmailFolderUpdateValidatorTest.php b/tests/Validators/EmailFolderUpdateValidatorTest.php new file mode 100644 index 0000000..b04ba8a --- /dev/null +++ b/tests/Validators/EmailFolderUpdateValidatorTest.php @@ -0,0 +1,28 @@ + 'demo' + ]); + + expect($response)->toEqual([ + 'displayName' => 'demo' + ]); +}); + +test('throws exception for unrecognized parameters', function () { + EmailFolderUpdateValidator::validate([ + '$top' => 10, + ]); +})->throws(InvalidArgumentException::class, 'Invalid parameters: $top. Allowed parameters: displayName.'); + +test('throws exception if displayName is not a string', function () { + EmailFolderUpdateValidator::validate(['displayName' => 1]); +})->throws(InvalidArgumentException::class, 'The displayName must be a string.'); + +test('allows empty input without throwing an exception', function () { + $response = EmailFolderUpdateValidator::validate([]); + expect($response)->toBe([]); +}); diff --git a/tests/Validators/GraphQueryValidatorTest.php b/tests/Validators/GraphQueryValidatorTest.php new file mode 100644 index 0000000..b3d87ad --- /dev/null +++ b/tests/Validators/GraphQueryValidatorTest.php @@ -0,0 +1,43 @@ + 10, + '$skip' => 5, + '$filter' => 'name eq \'test\'', + '$orderby' => 'name asc', + '$select' => 'name', + '$expand' => 'children', + '$count' => 'true', + '$search' => 'test', + '$format' => 'pdf', + ]); + + expect($response)->toEqual([ + '$top' => 10, + '$skip' => 5, + '$filter' => 'name eq \'test\'', + '$orderby' => 'name asc', + '$select' => 'name', + '$expand' => 'children', + '$count' => 'true', + '$search' => 'test', + '$format' => 'pdf', + ]); +}); + +test('cannot validate none existing params', function () { + GraphQueryValidator::validate([ + '$tops' => 10, + '$skip' => 5, + '$filter' => 'name eq \'test\'', + '$orderby' => 'name asc', + '$select' => 'name', + '$expand' => 'children', + '$count' => 'true', + '$search' => 'test', + '$format' => 'pdf', + ]); +})->throws(InvalidArgumentException::class, 'Invalid parameters: $tops. Allowed parameters: $top, $skip, $filter, $orderby, $select, $expand, $count, $search, $format.'); \ No newline at end of file diff --git a/tests/Validators/ValidatorTest.php b/tests/Validators/ValidatorTest.php new file mode 100644 index 0000000..701777e --- /dev/null +++ b/tests/Validators/ValidatorTest.php @@ -0,0 +1,15 @@ +toEqual([]); +}); + +test('cannot validate none existing params', function () { + Validator::validate([ + '$top' => 10 + ]); +})->throws(InvalidArgumentException::class, 'Invalid parameters: $top. Allowed parameters: .'); \ No newline at end of file