Skip to content

Commit 07a320e

Browse files
authored
Merge pull request #116 from 5am-code/feature/resolve
add the ability to resolve users and parents
2 parents ca767a0 + f945728 commit 07a320e

26 files changed

+1403
-22
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ vendor
33
.phpunit.result.cache
44
coverage/
55
.phpunit.cache/
6-
.env*
6+
.env*
7+
coverage-report

composer.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,13 @@
4949
},
5050
"scripts": {
5151
"test": "vendor/bin/pest",
52-
"test-coverage": "vendor/bin/pest --coverage-html coverage"
52+
"test-coverage": "phpdbg -qrr ./vendor/bin/pest --coverage-html ./coverage-report"
5353
},
5454
"config": {
55-
"sort-packages": true
55+
"sort-packages": true,
56+
"allow-plugins": {
57+
"pestphp/pest-plugin": true
58+
}
5659
},
5760
"extra": {
5861
"laravel": {

src/Endpoints/Comments.php

+10-8
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@ public function __construct(Notion $notion)
3838
}
3939

4040
/**
41-
* Retrieve a list of comments
42-
* url: https://api.notion.com/{version}/comments?block_id=* [get]
43-
* notion-api-docs: https://developers.notion.com/reference/retrieve-a-comment.
41+
* Retrieve a list of comments.
42+
*
43+
* @url https://api.notion.com/{version}/comments?block_id=* [get]
44+
*
45+
* @reference https://developers.notion.com/reference/retrieve-a-comment.
4446
*
4547
* @param string $blockId
4648
* @return CommentCollection
4749
*
48-
* @throws HandlingException
4950
* @throws NotionException
5051
*/
5152
public function ofBlock(string $blockId): CommentCollection
@@ -88,14 +89,15 @@ public function onPage(string $pageId): self
8889
}
8990

9091
/**
91-
* Create a comment
92-
* url: https://api.notion.com/{version}/comments [post]
93-
* notion-api-docs: https://developers.notion.com/reference/create-a-comment.
92+
* Create a comment.
93+
*
94+
* @url https://api.notion.com/{version}/comments [post]
95+
*
96+
* @reference https://developers.notion.com/reference/create-a-comment.
9497
*
9598
* @param CommentEntity $comment
9699
* @return CommentEntity
97100
*
98-
* @throws HandlingException
99101
* @throws NotionException
100102
*/
101103
public function create($comment): CommentEntity

src/Endpoints/Resolve.php

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
3+
namespace FiveamCode\LaravelNotionApi\Endpoints;
4+
5+
use FiveamCode\LaravelNotionApi\Entities\Blocks\Block;
6+
use FiveamCode\LaravelNotionApi\Entities\Database;
7+
use FiveamCode\LaravelNotionApi\Entities\Entity;
8+
use FiveamCode\LaravelNotionApi\Entities\NotionParent;
9+
use FiveamCode\LaravelNotionApi\Entities\Page;
10+
use FiveamCode\LaravelNotionApi\Entities\Properties\Relation;
11+
use FiveamCode\LaravelNotionApi\Entities\User;
12+
use FiveamCode\LaravelNotionApi\Exceptions\HandlingException;
13+
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
14+
use FiveamCode\LaravelNotionApi\Notion;
15+
use FiveamCode\LaravelNotionApi\Traits\HasParent;
16+
use Illuminate\Support\Collection;
17+
18+
/**
19+
* Class Resolve.
20+
*/
21+
class Resolve extends Endpoint
22+
{
23+
/**
24+
* Block constructor.
25+
*
26+
* @param Notion $notion
27+
*
28+
* @throws HandlingException
29+
* @throws \FiveamCode\LaravelNotionApi\Exceptions\LaravelNotionAPIException
30+
*/
31+
public function __construct(Notion $notion)
32+
{
33+
parent::__construct($notion);
34+
}
35+
36+
/**
37+
* Resolve User.
38+
*
39+
* @param User $user
40+
* @return User
41+
*
42+
* @throws HandlingException
43+
* @throws NotionException
44+
*/
45+
public function user(User $user): User
46+
{
47+
return $this->notion->users()->find($user->getId());
48+
}
49+
50+
/**
51+
* Resolve Parent of an entity.
52+
*
53+
* @param Entity $entity
54+
* @return Page|Database|Block
55+
*
56+
* @throws HandlingException
57+
* @throws NotionException
58+
*/
59+
public function parentOf(Entity $entity)
60+
{
61+
if (! in_array(HasParent::class, class_uses_recursive(get_class($entity)))) {
62+
throw new HandlingException("The given entity '{$entity->getObjectType()}' does not have a parent.");
63+
}
64+
65+
return $this->parent($entity->getParent());
66+
}
67+
68+
/**
69+
* Resolve Parent.
70+
*
71+
* @param NotionParent $parent
72+
* @return Page|Database|Block
73+
*
74+
* @throws HandlingException
75+
* @throws NotionException
76+
*/
77+
public function parent(NotionParent $parent): Page|Database|Block|NotionParent
78+
{
79+
switch ($parent->getObjectType()) {
80+
case 'page_id':
81+
return $this->notion->pages()->find($parent->getId());
82+
case 'database_id':
83+
return $this->notion->databases()->find($parent->getId());
84+
case 'block_id':
85+
return $this->notion->block($parent->getId())->retrieve();
86+
case 'workspace':
87+
return $parent;
88+
// throw new HandlingException('A Notion Workspace cannot be resolved by the Notion API.');
89+
default:
90+
throw new HandlingException('Unknown parent type while resolving the notion parent');
91+
}
92+
}
93+
94+
/**
95+
* Resolve Relations.
96+
*
97+
* @param Relation $relation
98+
* @return Collection<Page>
99+
*
100+
* @throws HandlingException
101+
* @throws NotionException
102+
*/
103+
public function relations(Relation $relation, bool $onlyTitles = false): Collection
104+
{
105+
$pages = collect();
106+
$relationIds = $relation->getRelation()->map(function ($o) {
107+
return $o['id'];
108+
});
109+
110+
foreach ($relationIds as $relationId) {
111+
if ($onlyTitles) {
112+
$pages->add($this->notion->pages()->find($relationId)->getTitle());
113+
} else {
114+
$pages->add($this->notion->pages()->find($relationId));
115+
}
116+
}
117+
118+
return $pages;
119+
}
120+
}

src/Entities/NotionParent.php

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace FiveamCode\LaravelNotionApi\Entities;
4+
5+
use FiveamCode\LaravelNotionApi\Exceptions\HandlingException;
6+
7+
/**
8+
* Class NotionParent.
9+
*/
10+
class NotionParent extends Entity
11+
{
12+
/**
13+
* @param array $responseData
14+
*
15+
* @throws HandlingException
16+
* @throws \FiveamCode\LaravelNotionApi\Exceptions\NotionException
17+
*/
18+
protected function setResponseData(array $responseData): void
19+
{
20+
parent::setResponseData($responseData);
21+
22+
if (
23+
$responseData['object'] !== 'page_id'
24+
&& $responseData['object'] !== 'database_id'
25+
&& $responseData['object'] !== 'workspace'
26+
&& $responseData['object'] !== 'block_id'
27+
) {
28+
throw HandlingException::instance('invalid json-array: the given object is not a valid parent');
29+
}
30+
31+
$this->fillFromRaw();
32+
}
33+
34+
private function fillFromRaw(): void
35+
{
36+
parent::fillEssentials();
37+
}
38+
39+
/**
40+
* @return bool
41+
*/
42+
public function isBlock(): bool
43+
{
44+
return $this->getObjectType() === 'block_id';
45+
}
46+
47+
/**
48+
* @return bool
49+
*/
50+
public function isPage(): bool
51+
{
52+
return $this->getObjectType() === 'page_id';
53+
}
54+
55+
/**
56+
* @return bool
57+
*/
58+
public function isDatabase(): bool
59+
{
60+
return $this->getObjectType() === 'database_id';
61+
}
62+
63+
/**
64+
* @return bool
65+
*/
66+
public function isWorkspace(): bool
67+
{
68+
return $this->getObjectType() === 'workspace';
69+
}
70+
}

src/Macros/PestHttpRecorder.php

+19-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use GuzzleHttp\Client;
66
use Illuminate\Http\Client\Request;
7+
use Illuminate\Support\Arr;
78
use Illuminate\Support\Facades\File;
89
use Illuminate\Support\Facades\Http;
910
use Illuminate\Support\Str;
@@ -37,6 +38,8 @@ class HttpRecorder
3738

3839
private $usePrettyJson = true;
3940

41+
private $requestNames = [];
42+
4043
public function storeIn($directory)
4144
{
4245
$this->snapshotDirectory = $directory;
@@ -51,21 +54,32 @@ public function minifyJson()
5154
return $this;
5255
}
5356

57+
public function nameForNextRequest($name)
58+
{
59+
array_push($this->requestNames, $name);
60+
}
61+
5462
public function handle(Request $request)
5563
{
5664
$forceRecording = in_array('--force-recording', $_SERVER['argv']);
5765

5866
$urlInfo = parse_url($request->url());
67+
$payload = null;
5968

6069
// create specific filename for storing snapshots
70+
$header = $request->headers();
6171
$method = Str::lower($request->method());
6272
$name = Str::slug(Str::replace('/', '-', $urlInfo['path']));
63-
$query = Str::slug(Str::replace('&', '_', Str::replace('=', '-', $urlInfo['query'])));
73+
$payload = ($method === 'get') ? ($urlInfo['query'] ?? null) : $request->body();
74+
$queryName = array_pop($this->requestNames) ?? hash('adler32', $payload);
6475

65-
$fileName = "{$method}_{$name}_{$query}.json";
76+
$fileName = "{$method}_{$name}_{$queryName}.json";
6677
$directoryPath = "tests/{$this->snapshotDirectory}";
6778
$filePath = "{$directoryPath}/{$fileName}";
6879

80+
// filter out Notion API Token Header
81+
$header = Arr::except($header, ['Authorization']);
82+
6983
if ($forceRecording || ! File::exists($filePath)) {
7084
File::makeDirectory($directoryPath, 0744, true, true);
7185

@@ -77,7 +91,10 @@ public function handle(Request $request)
7791
]);
7892

7993
$recordedResponse = [
94+
'header' => $header,
95+
'method' => $method,
8096
'status' => $response->getStatusCode(),
97+
'payload' => ($method === 'get') ? $payload : json_decode($payload, true),
8198
'data' => json_decode($response->getBody()->getContents(), true),
8299
];
83100

src/Notion.php

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use FiveamCode\LaravelNotionApi\Endpoints\Databases;
99
use FiveamCode\LaravelNotionApi\Endpoints\Endpoint;
1010
use FiveamCode\LaravelNotionApi\Endpoints\Pages;
11+
use FiveamCode\LaravelNotionApi\Endpoints\Resolve;
1112
use FiveamCode\LaravelNotionApi\Endpoints\Search;
1213
use FiveamCode\LaravelNotionApi\Endpoints\Users;
1314
use FiveamCode\LaravelNotionApi\Exceptions\HandlingException;
@@ -196,6 +197,11 @@ public function comments(): Comments
196197
return new Comments($this);
197198
}
198199

200+
public function resolve(): Resolve
201+
{
202+
return new Resolve($this);
203+
}
204+
199205
/**
200206
* @return string
201207
*/

src/Traits/HasParent.php

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace FiveamCode\LaravelNotionApi\Traits;
44

5+
use FiveamCode\LaravelNotionApi\Entities\NotionParent;
56
use Illuminate\Support\Arr;
67

78
/**
@@ -54,4 +55,15 @@ public function getParentType(): string
5455
{
5556
return $this->parentType;
5657
}
58+
59+
/**
60+
* @return NotionParent
61+
*/
62+
public function getParent()
63+
{
64+
return new NotionParent([
65+
'id' => $this->getParentId(),
66+
'object' => $this->getParentType(),
67+
]);
68+
}
5769
}

0 commit comments

Comments
 (0)