Skip to content

Commit

Permalink
Merge pull request #91 from netglue/feature/api-routes
Browse files Browse the repository at this point in the history
Implement API Resolved Document & Link URLs
  • Loading branch information
gsteel authored Jan 20, 2022
2 parents c529098 + 4b7ae32 commit 08a2b94
Show file tree
Hide file tree
Showing 21 changed files with 498 additions and 16 deletions.
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 2.0.0 - TBD

### Added

- [#91](https://github.com/netglue/prismic-client/pull/91) Adds `\Prismic\Document::url(): ?string` method to the interface so this will break any existing implementors, however, if you had been using `Prismic\Document\DocumentDataConsumer` trait to fulfill most of the methods in `Document` you shouldn't need to do anything unless the method name or signature conflicts with your own implementation. The `Prismic\Document\Fragment\DocumentLink::url(): ?string` method has been added as document links might have a pre-made url available now.
- [#91](https://github.com/netglue/prismic-client/pull/91) Adds `\Prismic\Value\RouteResolverSpec` - a value object that defines the shape of a single route as required by the remote API
- [#91](https://github.com/netglue/prismic-client/pull/91) Adds the method `\Prismic\Query::routes()` that accepts a list of `\Prismic\Value\RouteResolverSpec` instances. Routes are populated automatically when the API client is initialised with an appropriate Json encoded string _(Query parameter)_.

### Changed

- [#91](https://github.com/netglue/prismic-client/pull/91) Changes the behaviour of the abstract `Prismic\DefaultLinkResolver` so that document links with an url provided by the remote api will not be passed the custom resolver method, effectively preferring the url received in the payload.
- [#91](https://github.com/netglue/prismic-client/pull/91) Changes the behaviour of the defined "form" specifications ensuring that it is always possible to submit a 'routes' parameter with a query enabling you to define server side resolved routes as part of the query parameters regardless of whether those routes have been defined up-front during api-client initialisation.

### Deprecated

- Nothing.

### Removed

- Nothing.

### Fixed

- Nothing.

## 1.1.0 - 2022-01-07

### Added
Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true">
<coverage processUncoveredFiles="true">
Expand Down
2 changes: 1 addition & 1 deletion src/DefaultLinkResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public function resolve(Link $link): ?string
}

if ($link instanceof DocumentLink) {
return $this->resolveDocumentLink($link);
return $link->url() ?? $this->resolveDocumentLink($link);
}

return null;
Expand Down
5 changes: 5 additions & 0 deletions src/Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ public function asLink(): DocumentLink;
* Return the value object containing all of the document content fragments
*/
public function data(): DocumentData;

/**
* If the api has been configured with a route for this type of document, the url might be a string
*/
public function url(): ?string;
}
5 changes: 5 additions & 0 deletions src/Document/DocumentDataConsumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,9 @@ public function data(): DocumentData
{
return $this->data;
}

public function url(): ?string
{
return $this->data->url();
}
}
19 changes: 15 additions & 4 deletions src/Document/Fragment/DocumentLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ final class DocumentLink implements Fragment, Link
private $lang;
/** @var bool */
private $isBroken;
/** @var string|null */
private $url;

/** @param string[] $tags */
private function __construct(
Expand All @@ -30,13 +32,15 @@ private function __construct(
string $type,
string $lang,
bool $isBroken,
iterable $tags
iterable $tags,
?string $url
) {
$this->id = $id;
$this->uid = $uid;
$this->type = $type;
$this->lang = $lang;
$this->isBroken = $isBroken;
$this->url = $url;
$this->tags = [];
foreach ($tags as $tag) {
$this->addTag($tag);
Expand All @@ -55,9 +59,10 @@ public static function new(
string $type,
string $lang,
bool $isBroken = false,
iterable $tags = []
iterable $tags = [],
?string $url = null
): self {
return new self($id, $uid, $type, $lang, $isBroken, $tags);
return new self($id, $uid, $type, $lang, $isBroken, $tags, $url);
}

public static function withDocument(Document $document): self
Expand All @@ -68,7 +73,8 @@ public static function withDocument(Document $document): self
$document->type(),
$document->lang(),
false,
$document->tags()
$document->tags(),
$document->url()
);
}

Expand Down Expand Up @@ -112,4 +118,9 @@ public function isEmpty(): bool
{
return false;
}

public function url(): ?string
{
return $this->url;
}
}
3 changes: 2 additions & 1 deletion src/Document/Fragment/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ private static function linkFactory(object $data): Link
self::assertObjectPropertyIsString($data, 'type'),
$lang,
$isBroken,
self::assertObjectPropertyAllString($data, 'tags')
self::assertObjectPropertyAllString($data, 'tags'),
self::optionalStringProperty($data, 'url')
);
}

Expand Down
25 changes: 19 additions & 6 deletions src/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Prismic\Value\FormSpec;
use Prismic\Value\Ref;
use Prismic\Value\RouteResolverSpec;

use function array_filter;
use function array_map;
Expand Down Expand Up @@ -49,21 +50,21 @@ public function toUrl(): string
/** @psalm-return QueryParams */
private function mergeWithDefaults(): array
{
$parameters = $this->defaultParameters();
$defaults = $this->defaultParameters();
foreach ($this->parameters as $name => $value) {
if (is_scalar($value)) {
$parameters[$name] = $value;
$defaults[$name] = $value;
continue;
}

$merged = isset($parameters[$name]) && is_array($parameters[$name])
? array_merge($parameters[$name], (array) $value)
$merged = isset($defaults[$name]) && is_array($defaults[$name])
? array_merge($defaults[$name], (array) $value)
: $value;

$parameters[$name] = $merged;
$defaults[$name] = $merged;
}

return $parameters;
return $defaults;
}

private function buildQuery(): string
Expand Down Expand Up @@ -231,6 +232,18 @@ public function ref(Ref $ref): self
return $this->set('ref', (string) $ref);
}

/**
* Override or set Route Resolvers used to return document and link urls in received payloads
*
* If the api was initialised with a `routes` parameter, the query will be pre-populated with that value.
*
* @param list<RouteResolverSpec> $routes
*/
public function routes(array $routes): self
{
return $this->set('routes', Json::encode($routes));
}

/**
* Order results
*
Expand Down
10 changes: 10 additions & 0 deletions src/Value/DocumentData.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ final class DocumentData implements Document
private $body;
/** @var Translation[] */
private $translations;
/** @var string|null */
private $url;

/**
* @param string[] $tags
Expand All @@ -51,6 +53,7 @@ private function __construct(
string $lang,
DateTimeImmutable $firstPublished,
DateTimeImmutable $lastPublished,
?string $url,
iterable $tags,
iterable $translations,
FragmentCollection $body
Expand All @@ -61,6 +64,7 @@ private function __construct(
$this->lang = $lang;
$this->firstPublished = $firstPublished;
$this->lastPublished = $lastPublished;
$this->url = $url;
$this->setTags(...$tags);
$this->setTranslations(...$translations);
$this->body = $body;
Expand Down Expand Up @@ -96,6 +100,7 @@ public static function factory(object $data): self
self::assertObjectPropertyIsString($data, 'lang'),
self::assertObjectPropertyIsUtcDateTime($data, 'first_publication_date'),
self::assertObjectPropertyIsUtcDateTime($data, 'last_publication_date'),
self::optionalStringProperty($data, 'url'),
self::assertObjectPropertyAllString($data, 'tags'),
$translations,
$body
Expand Down Expand Up @@ -168,4 +173,9 @@ public function data(): DocumentData
{
return $this;
}

public function url(): ?string
{
return $this->url;
}
}
8 changes: 7 additions & 1 deletion src/Value/FormSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ private function __construct(
$this->encType = $encType;
$this->action = $action;
$this->fields = $fields;

if ($this->hasField('routes')) {
return;
}

$this->fields[] = FormField::new('routes', FormField::TYPE_STRING, false, null);
}

public static function factory(string $id, object $object): self
Expand Down Expand Up @@ -124,7 +130,7 @@ public function field(string $name): FormField
}

/**
* @return FormField[]
* @return Traversable<array-key, FormField>
* @psalm-return ArrayIterator<array-key, FormField>
*/
public function getIterator(): Traversable
Expand Down
56 changes: 56 additions & 0 deletions src/Value/RouteResolverSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Prismic\Value;

use JsonSerializable;
use Prismic\Json;
use Stringable;

use const JSON_FORCE_OBJECT;

final class RouteResolverSpec implements JsonSerializable, Stringable
{
/** @var string */
private $type;

/** @var string */
private $path;

/** @var array<string, string> */
private $resolvers;

/** @param array<string, string> $resolvers */
public function __construct(string $type, string $path, array $resolvers)
{
$this->type = $type;
$this->path = $path;
$this->resolvers = $resolvers;
}

public function __toString(): string
{
return Json::encode($this, JSON_FORCE_OBJECT);
}

/** @return array{type: string, path: string, resolvers: array<string, string>} */
public function jsonSerialize(): array
{
return [
'type' => $this->type,
'path' => $this->path,
'resolvers' => $this->resolvers,
];
}

/** @param array{type: string, path: string, resolvers: array<string, string>} $data */
public static function __set_state(array $data): self
{
return new self(
$data['type'],
$data['path'],
$data['resolvers']
);
}
}
57 changes: 57 additions & 0 deletions test/Unit/DefaultLinkResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

namespace PrismicTest;

use PHPUnit\Framework\TestCase;
use Prismic\DefaultLinkResolver;
use Prismic\Document\Fragment\DocumentLink;
use Prismic\Document\Fragment\MediaLink;
use Prismic\Link;

class DefaultLinkResolverTest extends TestCase
{
/** @var DefaultLinkResolver */
private $linkResolver;

protected function setUp(): void
{
parent::setUp();

$this->linkResolver = new class extends DefaultLinkResolver {
protected function resolveDocumentLink(DocumentLink $link): ?string
{
return '/some/url';
}
};
}

public function testMediaUrlsReturnTheExpectedUrl(): void
{
$media = MediaLink::new('/foo', 'whatever.jpg', 1234);

self::assertSame('/foo', $this->linkResolver->resolve($media));
}

public function testDocLinksWillYieldStoredUrlWhenPresent(): void
{
$docLink = DocumentLink::new('id', 'uid', 'foo', 'en-gb', false, [], '/special');

self::assertSame('/special', $this->linkResolver->resolve($docLink));
}

public function testDocLinksWillUseCustomResolveWhenNull(): void
{
$docLink = DocumentLink::new('id', 'uid', 'foo', 'en-gb', false, [], null);

self::assertSame('/some/url', $this->linkResolver->resolve($docLink));
}

public function testUnknownLinkTypesWillYieldNull(): void
{
$link = $this->createMock(Link::class);

self::assertNull($this->linkResolver->resolve($link));
}
}
1 change: 1 addition & 0 deletions test/Unit/Document/DocumentDataConsumerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function testProxyMethods(): void
$this->assertSame($this->document->type(), $this->subject->type());
$this->assertSame($this->document->tags(), $this->subject->tags());
$this->assertSame($this->document->lang(), $this->subject->lang());
$this->assertSame($this->document->url(), $this->subject->url());
$this->assertSame($this->document->firstPublished(), $this->subject->firstPublished());
$this->assertSame($this->document->lastPublished(), $this->subject->lastPublished());
$this->assertSame($this->document->translations(), $this->subject->translations());
Expand Down
Loading

0 comments on commit 08a2b94

Please sign in to comment.