-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from hyvor/metadata-priority
metadata priority
- Loading branch information
Showing
11 changed files
with
318 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
<?php | ||
|
||
namespace Hyvor\Unfold\Link\Metadata; | ||
|
||
use Hyvor\Unfold\Unfolded\UnfoldedAuthor; | ||
use DateTimeInterface; | ||
use Hyvor\Unfold\Unfolded\UnfoldedTag; | ||
|
||
/** | ||
* This class select the best metadata to use in the Unfolded object | ||
*/ | ||
class MetadataPriority | ||
{ | ||
|
||
/** | ||
* @param MetadataObject[] $metadata | ||
*/ | ||
public function __construct(private array $metadata) | ||
{ | ||
} | ||
|
||
/** | ||
* @param MetadataKeyType[] $keys | ||
*/ | ||
private function prioritizedAll(array $keys) | ||
{ | ||
$keyedMetadata = []; | ||
|
||
/** | ||
* First, we group the metadata by their key and filters metadata we don't want | ||
* Each key may have multiple metadata | ||
* | ||
* [ | ||
* 'OG_TITLE' => [MetadataObject], | ||
* 'TITLE' => [MetadataObject, MetadataObject], | ||
* ] | ||
*/ | ||
foreach ($this->metadata as $metadata) { | ||
$key = $metadata->key; | ||
if (!in_array($key, $keys)) { | ||
continue; | ||
} | ||
|
||
$keyName = $key->name; | ||
if (isset($keyedMetadata[$keyName])) { | ||
$keyedMetadata[$keyName][] = $metadata; | ||
} else { | ||
$keyedMetadata[$keyName] = [$metadata]; | ||
} | ||
} | ||
|
||
/** | ||
* Next, we are sorting $keyedMetadata by the order of $keys | ||
* If $keys was [TITLE, OG_TITLE], then the order of $keyedMetadata will be | ||
* [ | ||
* 'TITLE' => [MetadataObject, MetadataObject], | ||
* 'OG_TITLE' => [MetadataObject], | ||
* ] | ||
*/ | ||
$keysNames = array_map(fn($key) => $key->name, $keys); | ||
uksort($keyedMetadata, function ($a, $b) use ($keysNames) { | ||
return array_search($a, $keysNames) - array_search($b, $keysNames); | ||
}); | ||
|
||
// index by 0,1,2 | ||
$keyedMetadata = array_values($keyedMetadata); | ||
// return the values | ||
return array_map(fn($metadata) => $metadata->value, $keyedMetadata[0] ?? []); | ||
} | ||
|
||
/** | ||
* @param MetadataKeyType[] $keys | ||
* @return mixed|null | ||
*/ | ||
private function prioritized(array $keys) | ||
{ | ||
return $this->prioritizedAll($keys)[0] ?? null; | ||
} | ||
|
||
public function title(): ?string | ||
{ | ||
return $this->prioritized( | ||
[ | ||
MetadataKeyType::TITLE, | ||
MetadataKeyType::OG_TITLE, | ||
MetadataKeyType::TWITTER_TITLE | ||
] | ||
); | ||
} | ||
|
||
public function description(): ?string | ||
{ | ||
return $this->prioritized([ | ||
MetadataKeyType::DESCRIPTION, | ||
MetadataKeyType::OG_DESCRIPTION, | ||
MetadataKeyType::TWITTER_DESCRIPTION | ||
]); | ||
} | ||
|
||
/** | ||
* @return UnfoldedAuthor[] | ||
*/ | ||
public function authors() | ||
{ | ||
return $this->prioritizedAll([ | ||
MetadataKeyType::RICH_SCHEMA_AUTHOR, | ||
MetadataKeyType::OG_ARTICLE_AUTHOR, | ||
MetadataKeyType::TWITTER_CREATOR | ||
]); | ||
} | ||
|
||
/** | ||
* @return UnfoldedTag[] | ||
*/ | ||
public function tags(): array | ||
{ | ||
return $this->prioritizedAll([ | ||
MetadataKeyType::OG_ARTICLE_TAG | ||
]); | ||
} | ||
|
||
|
||
public function siteName(): ?string | ||
{ | ||
return $this->prioritized([ | ||
MetadataKeyType::OG_SITE_NAME, | ||
MetadataKeyType::TWITTER_SITE | ||
]); | ||
} | ||
|
||
|
||
public function siteUrl(): ?string | ||
{ | ||
return $this->prioritized([ | ||
MetadataKeyType::OG_URL | ||
]); | ||
} | ||
|
||
|
||
public function canonicalUrl(): ?string | ||
{ | ||
return $this->prioritized([ | ||
MetadataKeyType::CANONICAL_URL | ||
]); | ||
} | ||
|
||
|
||
public function publishedTime(): ?DateTimeInterface | ||
{ | ||
return $this->prioritized([ | ||
MetadataKeyType::RICH_SCHEMA_PUBLISHED_TIME, | ||
MetadataKeyType::OG_ARTICLE_PUBLISHED_TIME | ||
]); | ||
} | ||
|
||
|
||
public function modifiedTime(): ?DateTimeInterface | ||
{ | ||
return $this->prioritized([ | ||
MetadataKeyType::RICH_SCHEMA_MODIFIED_TIME, | ||
MetadataKeyType::OG_ARTICLE_MODIFIED_TIME | ||
]); | ||
} | ||
|
||
|
||
public function thumbnailUrl(): ?string | ||
{ | ||
return $this->prioritized([ | ||
MetadataKeyType::OG_IMAGE, | ||
MetadataKeyType::OG_IMAGE_URL, | ||
MetadataKeyType::OG_IMAGE_SECURE_URL, | ||
MetadataKeyType::TWITTER_IMAGE | ||
]); | ||
} | ||
|
||
|
||
public function iconUrl(): ?string | ||
{ | ||
return $this->prioritized([ | ||
MetadataKeyType::FAVICON_URL | ||
]); | ||
} | ||
|
||
|
||
public function locale(): ?string | ||
{ | ||
return $this->prioritized([ | ||
MetadataKeyType::LOCALE, | ||
MetadataKeyType::OG_LOCALE | ||
]); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,7 @@ | ||
<?php | ||
|
||
it('gets link', function () { | ||
// | ||
use Hyvor\Unfold\Unfold; | ||
|
||
}); | ||
|
||
it('gets embed', function () { | ||
// | ||
|
||
}); | ||
it('fetches link', function () { | ||
$response = Unfold::unfold('https://hyvor.com'); | ||
}); |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
|
||
namespace Hyvor\Unfold\Tests\Unit; | ||
|
||
use Hyvor\Unfold\Link\Metadata\MetadataKeyType; | ||
use Hyvor\Unfold\Link\Metadata\MetadataObject; | ||
use Hyvor\Unfold\Link\Metadata\MetadataPriority; | ||
|
||
it('prioritizes title', function () { | ||
$metadata = [ | ||
new MetadataObject(MetadataKeyType::DESCRIPTION, 'description'), // ignored | ||
new MetadataObject(MetadataKeyType::OG_TITLE, 'og title'), | ||
new MetadataObject(MetadataKeyType::TITLE, 'title'), | ||
]; | ||
|
||
$priority = new MetadataPriority($metadata); | ||
$title = $priority->title(); | ||
expect($title)->toBe('title'); | ||
}); | ||
|
||
it('prioritized authors', function () { | ||
$metadata = [ | ||
new MetadataObject(MetadataKeyType::OG_ARTICLE_AUTHOR, 'Author1'), | ||
new MetadataObject(MetadataKeyType::OG_ARTICLE_AUTHOR, 'Author2'), | ||
new MetadataObject(MetadataKeyType::OG_ARTICLE_AUTHOR, 'Author3'), | ||
// some tags | ||
new MetadataObject(MetadataKeyType::OG_ARTICLE_TAG, 'Tag1'), | ||
new MetadataObject(MetadataKeyType::OG_ARTICLE_TAG, 'Tag2'), | ||
]; | ||
|
||
$priority = new MetadataPriority($metadata); | ||
$authors = $priority->authors(); | ||
expect($authors)->toEqual([ | ||
'Author1', | ||
'Author2', | ||
'Author3', | ||
]); | ||
}); | ||
|
||
it('with already correct sort', function () { | ||
$metadata = [ | ||
new MetadataObject(MetadataKeyType::OG_SITE_NAME, 'OG Site name'), | ||
new MetadataObject(MetadataKeyType::TWITTER_SITE, 'Twitter Site Name'), | ||
]; | ||
|
||
$priority = new MetadataPriority($metadata); | ||
$authors = $priority->siteName(); | ||
expect($authors)->toEqual('OG Site name'); | ||
}); |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.