Skip to content

Commit

Permalink
Merge pull request #8 from hyvor/more-tests
Browse files Browse the repository at this point in the history
More tests
  • Loading branch information
supun-io authored Oct 22, 2024
2 parents c832c9e + 06bcfe6 commit 076723c
Show file tree
Hide file tree
Showing 31 changed files with 502 additions and 453 deletions.
45 changes: 24 additions & 21 deletions src/Embed/Embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,42 @@

namespace Hyvor\Unfold\Embed;

use Hyvor\Unfold\Embed\Exception\ParserException;
use Hyvor\Unfold\Embed\Exception\UnableToResolveEmbedException;
use Hyvor\Unfold\Embed\Platforms\Reddit;
use Hyvor\Unfold\Embed\Platforms\Tiktok;
use Hyvor\Unfold\Embed\Platforms\Twitter;
use Hyvor\Unfold\Embed\Platforms\Youtube;
use Hyvor\Unfold\UnfoldConfigObject;
//use Hyvor\Unfold\Embed\Platforms\GithubGist;
//use Hyvor\Unfold\Embed\Platforms\Reddit;
//use Hyvor\Unfold\Embed\Platforms\Tiktok;
//use Hyvor\Unfold\Embed\Platforms\Twitter;
//use Hyvor\Unfold\Embed\Platforms\Youtube;
use Hyvor\Unfold\Exception\EmbedUnableToResolveException;
use Hyvor\Unfold\Exception\EmbedParserException;
use Hyvor\Unfold\Exception\UnfoldException;
use Hyvor\Unfold\UnfoldCallContext;
use Hyvor\Unfold\UnfoldConfig;
use Hyvor\Unfold\Unfolded\Unfolded;
use Hyvor\Unfold\UnfoldException;
use Hyvor\Unfold\UnfoldMethod;
use Hyvor\Unfold\UnfoldCallContext;

class Embed
{

/**
* @var EmbedParserAbstract[]
* @return string[]
*/
public const PARSERS = [
Youtube::class,
Reddit::class,
Tiktok::class,
Twitter::class,
Reddit::class,
];
public static function getParsers(): array
{
$namespace = __NAMESPACE__ . '\\Platforms\\';
return array_map(
fn($file) => $namespace . pathinfo($file, PATHINFO_FILENAME),
glob(__DIR__ . '/Platforms/*.php')

Check failure on line 29 in src/Embed/Embed.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Parameter #2 $array of function array_map expects array, array<int, string>|false given.
);
}

/**
* @throws ParserException
* @throws EmbedParserException
*/
public static function parse(
string $url,
?UnfoldConfigObject $config = null,
?UnfoldConfig $config = null,
): ?EmbedResponseObject {
foreach (self::PARSERS as $parserClass) {
foreach (self::getParsers() as $parserClass) {
$parser = new $parserClass($url, $config);
if ($parser->match()) {

Check failure on line 42 in src/Embed/Embed.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Call to an undefined method object::match().
return $parser->parse();

Check failure on line 43 in src/Embed/Embed.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Call to an undefined method object::parse().
Expand All @@ -55,7 +58,7 @@ public static function getUnfoldedObject(

if ($oembed === null) {
if ($context->method === UnfoldMethod::EMBED) {
throw new UnableToResolveEmbedException();
throw new EmbedUnableToResolveException();
} else {
return null;
}
Expand Down
50 changes: 36 additions & 14 deletions src/Embed/EmbedParserAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Uri;
use Hyvor\Unfold\Embed\Exception\ParserException;
use Hyvor\Unfold\UnfoldConfigObject;
use Hyvor\Unfold\Exception\EmbedParserException;
use Hyvor\Unfold\Exception\UnfoldException;
use Hyvor\Unfold\UnfoldConfig;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Message\RequestInterface;

Expand All @@ -15,13 +16,13 @@
*/
abstract class EmbedParserAbstract
{
protected UnfoldConfigObject $config;
protected UnfoldConfig $config;

public function __construct(
protected string $url,
?UnfoldConfigObject $config = null,
?UnfoldConfig $config = null,
) {
$this->config = $config ?? new UnfoldConfigObject();
$this->config = $config ?? new UnfoldConfig();
}


Expand Down Expand Up @@ -65,14 +66,25 @@ public function match(): bool
return false;
}

public function parse(): ?EmbedResponseObject
/**
* @throws UnfoldException
*/
public function parse(): EmbedResponseObject
{
$oEmbedUrl = $this->oEmbedUrl();

if (!$oEmbedUrl) {
// TODO: Check config option for fallback
return null;
if ($this instanceof EmbedParserOEmbedInterface) {
return $this->parseOEmbed();

Check failure on line 75 in src/Embed/EmbedParserAbstract.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Method Hyvor\Unfold\Embed\EmbedParserAbstract::parse() should return Hyvor\Unfold\Embed\EmbedResponseObject but returns Hyvor\Unfold\Embed\EmbedResponseObject|null.
} elseif ($this instanceof EmbedParserCustomInterface) {
return $this->parseCustom();
} else {
throw new \Exception(
'EmbedParserAbstract should be implemented with either EmbedParserOEmbedInterface or EmbedParserCustomInterface'
); // @codeCoverageIgnore
}
}

public function parseOEmbed(): ?EmbedResponseObject
{
$oEmbedUrl = $this->oEmbedUrl();

Check failure on line 87 in src/Embed/EmbedParserAbstract.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Call to an undefined method Hyvor\Unfold\Embed\EmbedParserAbstract::oEmbedUrl().

$uri = Uri::withQueryValues(
new Uri($oEmbedUrl),
Expand All @@ -97,7 +109,7 @@ public function parse(): ?EmbedResponseObject
try {
$response = $client->sendRequest($request);
} catch (ClientExceptionInterface $e) {
throw new ParserException(
throw new EmbedParserException(
"Failed to fetch oEmbed data from the endpoint",
previous: $e
);
Expand All @@ -107,18 +119,28 @@ public function parse(): ?EmbedResponseObject
$content = $response->getBody()->getContents();

if ($status !== 200) {
throw new ParserException(
throw new EmbedParserException(
"Failed to fetch oEmbed data from the endpoint. Status: $status. Response: $content"
);
}

$parsed = json_decode($content, true);

if (!is_array($parsed)) {
throw new ParserException("Failed to parse JSON response from oEmbed endpoint");
throw new EmbedParserException("Failed to parse JSON response from oEmbed endpoint");
}

return EmbedResponseObject::fromArray($parsed);
}

private function parseCustom()

Check failure on line 136 in src/Embed/EmbedParserAbstract.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Method Hyvor\Unfold\Embed\EmbedParserAbstract::parseCustom() has no return type specified.
{
$html = $this->getEmbedHtml();

Check failure on line 138 in src/Embed/EmbedParserAbstract.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Call to an undefined method Hyvor\Unfold\Embed\EmbedParserAbstract::getEmbedHtml().

return EmbedResponseObject::fromArray([
'type' => 'embed',
'html' => $html
]);
}

}
2 changes: 1 addition & 1 deletion src/Embed/EmbedParserOEmbedInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

interface EmbedParserOEmbedInterface
{
public function oEmbedUrl(): ?string;
public function oEmbedUrl(): string;

}
9 changes: 0 additions & 9 deletions src/Embed/Exception/ParserException.php

This file was deleted.

6 changes: 3 additions & 3 deletions src/Embed/Platforms/Instagram.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use GuzzleHttp\Psr7\Uri;
use Hyvor\Unfold\Embed\EmbedParserAbstract;
use Hyvor\Unfold\Embed\EmbedParserOEmbedInterface;
use Hyvor\Unfold\Embed\Exception\ParserException;
use Hyvor\Unfold\Exception\EmbedParserException;
use Psr\Http\Message\RequestInterface;

// TODO:
Expand All @@ -17,7 +17,7 @@ public function oEmbedRequestFilter(RequestInterface $request): RequestInterface
$facebookAccessToken = $this->config->facebookAccessToken;

if (!$facebookAccessToken) {
throw new ParserException('Facebook Access Token is required for Instagram embeds');
throw new EmbedParserException('Facebook Access Token is required for Instagram embeds');
}

$uri = Uri::withQueryValue($uri, 'access_token', $facebookAccessToken);
Expand Down Expand Up @@ -57,7 +57,7 @@ public function regex()
];
}

public function oEmbedUrl(): ?string
public function oEmbedUrl(): string
{
return 'https://graph.facebook.com/v16.0/instagram_oembed';
}
Expand Down
2 changes: 1 addition & 1 deletion src/Embed/Platforms/Reddit.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function regex()
];
}

public function oEmbedUrl(): ?string
public function oEmbedUrl(): string
{
return 'https://www.reddit.com/oembed';
}
Expand Down
5 changes: 3 additions & 2 deletions src/Embed/Platforms/Tiktok.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace Hyvor\Unfold\Embed\Platforms;

use Hyvor\Unfold\Embed\EmbedParserAbstract;
use Hyvor\Unfold\Embed\EmbedParserOEmbedInterface;

class Tiktok extends EmbedParserAbstract
class Tiktok extends EmbedParserAbstract implements EmbedParserOEmbedInterface
{
public function regex()
{
Expand All @@ -14,7 +15,7 @@ public function regex()
];
}

public function oEmbedUrl(): ?string
public function oEmbedUrl(): string
{
return 'https://www.tiktok.com/oembed';
}
Expand Down
2 changes: 1 addition & 1 deletion src/Embed/Platforms/Twitter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function regex()
];
}

public function oEmbedUrl(): ?string
public function oEmbedUrl(): string
{
return 'https://publish.twitter.com/oembed';
}
Expand Down
2 changes: 1 addition & 1 deletion src/Embed/Platforms/Youtube.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function regex()
];
}

public function oEmbedUrl(): ?string
public function oEmbedUrl(): string
{
return 'https://www.youtube.com/oembed';
}
Expand Down
7 changes: 7 additions & 0 deletions src/Exception/EmbedParserException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Hyvor\Unfold\Exception;

class EmbedParserException extends UnfoldException
{
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<?php

namespace Hyvor\Unfold\Embed\Exception;
namespace Hyvor\Unfold\Exception;

use Hyvor\Unfold\UnfoldException;

class UnableToResolveEmbedException extends UnfoldException
class EmbedUnableToResolveException extends UnfoldException
{
public function __construct(string $message = "", int $code = 0, ?\Throwable $previous = null)

Check failure on line 7 in src/Exception/EmbedUnableToResolveException.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Constructor of class Hyvor\Unfold\Exception\EmbedUnableToResolveException has an unused parameter $message.
{
Expand Down
8 changes: 8 additions & 0 deletions src/Exception/LinkScrapeException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Hyvor\Unfold\Exception;

class LinkScrapeException extends UnfoldException
{

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Hyvor\Unfold;
namespace Hyvor\Unfold\Exception;

class UnfoldException extends \Exception
{
Expand Down
15 changes: 9 additions & 6 deletions src/Link/Link.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace Hyvor\Unfold\Link;

use GuzzleHttp\Psr7\Request;
use Hyvor\Unfold\Exception\LinkScrapeException;
use Hyvor\Unfold\Link\Metadata\MetadataParser;
use Hyvor\Unfold\UnfoldConfigObject;
use Hyvor\Unfold\UnfoldConfig;
use Hyvor\Unfold\Unfolded\Unfolded;
use Hyvor\Unfold\UnfoldCallContext;
use Psr\Http\Client\ClientExceptionInterface;
Expand All @@ -13,7 +14,7 @@ class Link
{
public function __construct(
private string $url,
private UnfoldConfigObject $config,
private UnfoldConfig $config,
) {
}

Expand All @@ -27,14 +28,16 @@ public function scrape(): string
try {
$response = $this->config->httpClient->sendRequest($request);
} catch (ClientExceptionInterface $e) {
//
throw new LinkScrapeException($e->getMessage());
}

$status = $response->getStatusCode();
$content = $response->getBody()->getContents();
// TODO:

return $response->getBody();
if ($status < 200 || $status >= 300) {
throw new LinkScrapeException("Unable to scrape link. HTTP status code: $status");
}

return $response->getBody()->getContents();
}


Expand Down
39 changes: 39 additions & 0 deletions src/Link/Metadata/MetadataKeyType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace Hyvor\Unfold\Link\Metadata;

use Hyvor\Unfold\Unfolded\UnfoldedAuthor;
use Hyvor\Unfold\Unfolded\UnfoldedTag;

enum MetadataKeyType
{
case TITLE;
Expand Down Expand Up @@ -48,4 +51,40 @@ enum MetadataKeyType
case TWITTER_DESCRIPTION;
case TWITTER_TITLE;
case TWITTER_IMAGE;

/**
* Gets the value of the metadata from a given content string
* ex: article:published_time is converted to DateTimeInterface
*/
public function getValue(string $content)
{
if (
$this === MetadataKeyType::OG_ARTICLE_PUBLISHED_TIME ||
$this === MetadataKeyType::OG_ARTICLE_MODIFIED_TIME
) {
return MetadataParser::getDateTimeFromString($content);
}

if (
$this === MetadataKeyType::OG_ARTICLE_AUTHOR ||
$this === MetadataKeyType::TWITTER_CREATOR
) {
return $this->getAuthorFromString($content);
}

if ($this === MetadataKeyType::OG_ARTICLE_TAG) {
return new UnfoldedTag($content);
}

return $content;
}

private function getAuthorFromString(string $value): UnfoldedAuthor
{
if (str_contains($value, 'http://') || str_contains($value, 'https://')) {
return new UnfoldedAuthor(null, $value);
} else {
return new UnfoldedAuthor($value, null);
}
}
}
Loading

0 comments on commit 076723c

Please sign in to comment.