Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/retrieve page property items #167

Open
wants to merge 12 commits into
base: dev
Choose a base branch
from
74 changes: 74 additions & 0 deletions src/Endpoints/Page.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace FiveamCode\LaravelNotionApi\Endpoints;

use FiveamCode\LaravelNotionApi\Entities\Collections\EntityCollection;
use FiveamCode\LaravelNotionApi\Entities\Collections\UserCollection;
use FiveamCode\LaravelNotionApi\Entities\Properties\Property;
use FiveamCode\LaravelNotionApi\Exceptions\HandlingException;
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
use FiveamCode\LaravelNotionApi\Notion;

/**
* Class Page.
*/
class Page extends Endpoint
{
/**
* @var ?string
*/
private ?string $pageId = null;

public function __construct(Notion $notion, string $pageId)
{
parent::__construct($notion);
$this->pageId = $pageId;
}

/**
* Retrieve a page property item.
*
* @url https://api.notion.com/{version}/pages/{page_id}/properties/{property_id} [get]
*
* @reference https://developers.notion.com/reference/retrieve-a-page-property.
*
* @param string $propertyId
* @return Page
*
* @throws HandlingException
* @throws NotionException
*/
public function property(string $propertyId): Property|EntityCollection
{
$response = $this->get(
$this->url(Endpoint::PAGES.'/'.$this->pageId.'/'.'properties'.'/'.rawurlencode(rawurldecode($propertyId)))
);

$rawContent = $response->json();

if ($rawContent['object'] === 'list') {
if (count($rawContent['results']) === 0) {
return new EntityCollection();
}

$type = $rawContent['type'] ?? $rawContent['results'][0]['type'];

// if($type === 'rollup'){
// dd($rawContent['type']);
// }
// if($)
// dd("HI");

return match ($type) {
'people' => new UserCollection($rawContent),
// 'rollup' => new Collection
default => dd($rawContent) && new EntityCollection($rawContent)
};
}

return Property::fromObjectResponse(
id: $propertyId,
rawContent: $rawContent
);
}
}
5 changes: 5 additions & 0 deletions src/Entities/Collections/UserCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ protected function collectChildren(): void
{
$this->collection = new Collection();
foreach ($this->rawResults as $userChild) {
//TODO: create a new type for 'people' (outer layer for user)
if ($userChild['type'] === 'people') {
$userChild = $userChild['people'];
}

$this->collection->add(new User($userChild));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Entities/Properties/People.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ protected function fillFromRaw(): void
{
parent::fillFromRaw();
if (! is_array($this->rawContent)) {
throw HandlingException::instance('The property-type is people, however the raw data-structure does not reprecent this type (= array of items). Please check the raw response-data.');
throw HandlingException::instance('The property-type is people, however the raw data-structure does not represent this type (= array of items). Please check the raw response-data.');
}

$this->content = new Collection();
Expand Down
71 changes: 66 additions & 5 deletions src/Entities/Properties/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,21 @@ public function __construct(string $title = null)
protected function setResponseData(array $responseData): void
{
if (! Arr::exists($responseData, 'id')) {
throw HandlingException::instance('invalid json-array: no id provided');
throw HandlingException::instance('invalid json-array for property: no id provided');
}
$this->responseData = $responseData;
$this->fillFromRaw();
}

/**
* @param array $responseData
*
* @throws HandlingException
*/
protected function setObjectResponseData(array $responseData): void
{
if (! Arr::exists($responseData, 'object') || ! Arr::exists($responseData, 'id')) {
throw HandlingException::instance('invalid json-array for property: no object or id provided');
}
$this->responseData = $responseData;
$this->fillFromRaw();
Expand All @@ -90,16 +104,23 @@ protected function fillFromRaw(): void

private function fillType(): void
{
if (Arr::exists($this->responseData, 'type')) {
$this->type = $this->responseData['type'];
}
$this->type = self::extractType($this->responseData);
}

private function fillContent(): void
{
if (Arr::exists($this->responseData, $this->getType())) {
$this->rawContent = $this->responseData[$this->getType()];
$this->content = $this->rawContent;

return;
}

if (Arr::exists($this->responseData, 'object') && Arr::exists($this->responseData, $this->getObjectType())) {
$this->rawContent = $this->responseData[$this->getObjectType()];
$this->content = $this->rawContent;

return;
}
}

Expand Down Expand Up @@ -166,7 +187,7 @@ public function getContent()
*
* @throws HandlingException
*/
public static function fromResponse(string $propertyKey, $rawContent): Property
public static function fromResponse(?string $propertyKey, array $rawContent): Property
{
$propertyClass = self::mapTypeToClass($rawContent['type']);
$property = new $propertyClass($propertyKey);
Expand All @@ -176,6 +197,46 @@ public static function fromResponse(string $propertyKey, $rawContent): Property
return $property;
}

/**
* @param string $id
* @param $rawContent
* @return Property
*
* @throws HandlingException
*/
public static function fromObjectResponse(string $id, array $rawContent): Property|EntityCollection
{
$propertyClass = self::mapTypeToClass(self::extractType($rawContent));
$property = new $propertyClass();
$rawContent['id'] = $id;

$property->setObjectResponseData($rawContent);

return $property;
}

// private static function

public static function extractType(array $rawContent)
{
if (Arr::exists($rawContent, 'type')) {
return $rawContent['type'];
}

if (
Arr::exists($rawContent, 'object')
&& $rawContent['object'] == 'list'
&& Arr::exists($rawContent, 'results')
&& is_array($rawContent['results'])
&& count($rawContent['results']) > 0
&& Arr::exists($rawContent['results'][0], 'type')
) {
return $rawContent['results'][0]['type'];
}

return null;
}

/**
* Maps the type of a property to the corresponding package class by converting the type name.
*
Expand Down
8 changes: 6 additions & 2 deletions src/Macros/PestHttpRecorder.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,13 @@ public function handle(Request $request)
$method = Str::lower($request->method());
$name = Str::slug(Str::replace('/', '-', $urlInfo['path']));
$payload = ($method === 'get') ? ($urlInfo['query'] ?? null) : $request->body();
$queryName = array_pop($this->requestNames) ?? hash('adler32', $payload);
$queryName = array_pop($this->requestNames) ?? ($payload ? hash('adler32', $payload) : '');

$fileName = "{$method}_{$name}_{$queryName}.json";
if ($queryName != '') {
$queryName = '_'.$queryName;
}

$fileName = "{$method}_{$name}{$queryName}.json";
$directoryPath = "tests/{$this->snapshotDirectory}";
$filePath = "{$directoryPath}/{$fileName}";

Expand Down
11 changes: 11 additions & 0 deletions src/Notion.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use FiveamCode\LaravelNotionApi\Endpoints\Database;
use FiveamCode\LaravelNotionApi\Endpoints\Databases;
use FiveamCode\LaravelNotionApi\Endpoints\Endpoint;
use FiveamCode\LaravelNotionApi\Endpoints\Page;
use FiveamCode\LaravelNotionApi\Endpoints\Pages;
use FiveamCode\LaravelNotionApi\Endpoints\Resolve;
use FiveamCode\LaravelNotionApi\Endpoints\Search;
Expand Down Expand Up @@ -152,6 +153,16 @@ public function pages(): Pages
return new Pages($this);
}

/**
* @return Page
*
* @throws HandlingException
*/
public function page(string $pageId): Page
{
return new Page($this, $pageId);
}

/**
* @param string $blockId
* @return Block
Expand Down
46 changes: 46 additions & 0 deletions tests/RecordedEndpointPageTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

use FiveamCode\LaravelNotionApi\Entities\Collections\EntityCollection;
use FiveamCode\LaravelNotionApi\Entities\Properties\Property;
use FiveamCode\LaravelNotionApi\Entities\Properties\Rollup;
use Illuminate\Support\Facades\Http;

$httpRecorder = null;

beforeEach(function () {
$this->httpRecorder = Http::recordAndFakeLater([
'https://api.notion.com/v1/pages*',
'https://api.notion.com/v1/databases*',
])->storeIn('snapshots/page-property-items');
});

it('should fetch specific property items of a page', function () {
$this->httpRecorder->nameForNextRequest('database-for-properties');
$databaseStructure = \Notion::databases()->find('cdd4befe814144f7b1eecb9c123bd4fb');

$propertyKeys = $databaseStructure->getProperties()->map(fn ($o) => $o->getTitle());

// dd($propertyKeys);

expect($propertyKeys)->toBeInstanceOf(\Illuminate\Support\Collection::class);
expect($propertyKeys)->toHaveCount(16);

// dd($propertyKeys);

foreach ($propertyKeys as $propertyKey) {
$id = $databaseStructure->getProperty($propertyKey)->getId();
$property = \Notion::page('f1884dca3885460e93f52bf4da7cce8e')->property($id);

match ($propertyKey) {
'Rollup' => dd($property->asCollection()) && expect($property->asCollection()->first())->toBeInstanceOf(Rollup::class),
// default => throw new \Exception('Unknown property key')
default => null
};

if ($propertyKey == 'Rollup' || $propertyKey == 'Person' || $propertyKey == 'Name') {
expect($property)->toBeInstanceOf(EntityCollection::class);
} else {
expect($property)->toBeInstanceOf(Property::class);
}
}
});
Loading
Loading