<?php
|
namespace JVBase\registrar\config\seo;
|
|
use JVBase\managers\Cache;
|
use JVBase\managers\SEO\render\Thing\CreativeWork\MediaObject\ImageObject;
|
use JVBase\managers\SEO\render\Thing\Intangible\Quantity\Distance;
|
use JVBase\meta\Meta;
|
use JVBase\registrar\Registrar;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
|
class Resolver {
|
protected static ?Meta $meta;
|
|
public static function resolve(string $template, ?Meta $meta): string
|
{
|
if (!$meta) {
|
if (is_singular()){
|
$meta = Meta::forPost(get_the_ID());
|
}else if (is_tax()) {
|
$meta = Meta::forTerm(get_queried_object()->term_id);
|
}
|
}
|
self::$meta = $meta;
|
return preg_replace_callback(
|
'/\{\{([^}]+)}}/',
|
fn($matches) => self::resolveVariable($matches[1], $meta),
|
$template
|
);
|
}
|
protected static function resolveVariable(string $variable, ?Meta $meta = null): mixed
|
{
|
$variable = trim($variable);
|
switch ($variable) {
|
case 'CREATOR':
|
return JVB()->seo()->getCreator();
|
case 'name':
|
if (is_post_type_archive()) {
|
$obj = get_queried_object();
|
|
$registrar = Registrar::getInstance($obj->name);
|
return $registrar ? $registrar->getPlural() : $obj->label;
|
}
|
break;
|
}
|
if (str_contains($variable, '.')) {
|
return self::resolveRelation($variable, $meta);
|
}
|
if ($meta && $variable === 'post_permalink') {
|
return get_the_permalink($meta->id());
|
}
|
if (!$meta) {
|
return '';
|
}
|
$config = $meta->config($variable);
|
if (!$config) {
|
error_log('[SEO]Meta Resolver. Could not find meta configuration for variable: '.$variable);
|
return '';
|
}
|
if ($variable === 'post_content') {
|
return self::resolvePostContent($variable, $meta);
|
}
|
return match($config['type']) {
|
'upload', 'image', 'gallery' => self::resolveImage($variable, $meta),
|
'selector', 'taxonomy', 'user', 'post' => self::resolveObject($variable, $meta),
|
default => $meta->get($variable),
|
};
|
}
|
|
protected static function resolveRelation(string $path, ?Meta $meta = null): string
|
{
|
$parts = explode('.', $path);
|
$relation = array_shift($parts);
|
$field = implode('.', $parts);
|
|
//We need to:
|
// 1) Get the id of the item we're fetching (meta value of the $relation)
|
if ($relation === 'registrar') {
|
if (count($parts) === 2) {
|
return self::resolveRegistrar($parts[0], $parts[1]);
|
} else {
|
error_log('[Resolver]::resolveRelation: Registrar relation requires registrar.[slug].[property]');
|
return '';
|
}
|
|
}
|
|
if (!$meta) {
|
return'';
|
}
|
$ID = $meta->get($relation);
|
if (!$ID || $ID === '') {
|
return '';
|
}
|
// 2) Create new Meta for that relation
|
$config = $meta->config($relation);
|
if (!$config) {
|
return '';
|
}
|
|
$type = false;
|
if ($config['type'] === 'taxonomy' || array_key_exists('taxonomy', $config)) {
|
$type = 'term';
|
} elseif ($config['type'] === 'user' || array_key_exists('user', $config)){
|
$type = 'user';
|
} elseif ($config['type'] === 'post' || array_key_exists('post', $config)){
|
$type = 'post';
|
}
|
|
if (!$type) {
|
error_log('[SEO]Meta Resolver. Could not find type for relation: '.$relation.': '.$field);
|
return '';
|
}
|
$newMeta = new Meta($ID, $type);
|
// 3) Pass to resolver
|
return self::resolve($field, $newMeta);
|
}
|
|
protected static function resolvePostContent(string $variable, ?Meta $meta):string{
|
return wp_strip_all_tags(str_replace("\n", '', $meta->get('post_content')));
|
}
|
protected static function resolveImage(string $variable, ?Meta $meta, bool $returnID = false): string
|
{
|
$imgID = $meta->get($variable);
|
if (!$imgID || $imgID === '') {
|
return '';
|
}
|
if ($returnID) {
|
return $imgID;
|
}
|
$image = wp_get_attachment_image_src($imgID,'full');
|
if (!$image) {
|
return '';
|
}
|
return $image[0];
|
}
|
protected static function resolveObject(string $variable, ?Meta $meta): string
|
{
|
//Hmmm... this should already be handled by dot notation.
|
return '';
|
}
|
|
/**
|
* SCHEMA RESOLVING
|
* We need to map the values to what schema.org expects.
|
* Most are defined in the JVBase\managers\schema\render namespace.
|
*/
|
public static function resolveForSchema(string $property, string $value, mixed $schema, ?Meta $meta = null):mixed
|
{
|
$check = 'resolve'.ucfirst($property).'Property';
|
if (method_exists(self::class, $check)) {
|
return self::$check($property, $value, $meta);
|
}
|
|
$checkType = self::checkPropertyType($property, $value, $schema, $meta);
|
if ($checkType !== false) {
|
return $checkType;
|
}
|
|
$ignore = ['description', 'name'];
|
if (!in_array($property, $ignore)) {
|
error_log('[SEO]Resolver - No method found for '.$property.' with value: '.print_r($value, true).'. Defaulting to base Resolver');
|
}
|
|
|
return self::resolve($value, $meta);
|
}
|
|
public static function checkPropertyType(string $property, mixed $value, mixed $schema, ?Meta $meta):mixed
|
{
|
return match($property) {
|
'logo', 'image', 'photo', 'primaryImageOfPage', 'thumbnail', 'associatedMedia' => self::resolveImageProperty($property, $value, $schema, $meta),
|
'creator' => self::resolveCreator($property, $value, $schema, $meta),
|
default => false
|
};
|
}
|
|
public static function resolveImageProperty(string $property, mixed $value, mixed $schema, ?Meta $meta):?ImageObject
|
{
|
if (!$meta) {
|
return null;
|
}
|
$value = str_replace('{{', '', str_replace('}}', '', $value));
|
$imgID = $meta->get($value);
|
error_log('Got image id: '.print_r($imgID, true));
|
if (!$imgID || $imgID === '') {
|
return null;
|
}
|
$img = wp_get_attachment_image_src($imgID,'full');
|
if (!$img) {
|
return null;
|
}
|
if (JVB_TESTING){
|
Cache::for('imageSchemaObject')->flush();
|
}
|
|
return Cache::for('imageSchemaObject')->connect('post')->remember(
|
$imgID,
|
function () use ($imgID, $img) {
|
$imageObject = new ImageObject();
|
$imageObject->setContentUrl($img[0]);
|
$width = new Distance();
|
$width->setName($img[1].' px');
|
$imageObject->setWidth($width);
|
$height = new Distance();
|
$height->setName($img[2].' px');
|
$imageObject->setHeight($height);
|
|
$image_path = get_attached_file($imgID);
|
if ($image_path && file_exists($image_path)) {
|
$bytes = filesize($image_path);
|
$imageObject->setContentSize($bytes);
|
|
$fileType = wp_check_filetype($image_path);
|
if ($fileType['ext']) {
|
$imageObject->setEncodingFormat($fileType['ext']);
|
}
|
}
|
|
$caption = wp_get_attachment_caption($imgID)??get_post($imgID)->post_content??false;
|
if ($caption && $caption!== '') {
|
$imageObject->setCaption($caption);
|
}
|
return $imageObject;
|
}
|
);
|
|
}
|
|
public static function resolveCreator(string $type, mixed $value, mixed $schema, ?Meta $meta):mixed
|
{
|
if (is_numeric($value)) {
|
//TODO generate from id
|
|
} else if (str_contains($value, 'CREATOR')) {
|
return JVB()->seo()->getCreator();
|
}
|
return '';
|
}
|
|
public static function resolveRegistrar(string $type, string $property):string
|
{
|
$registrar = Registrar::getInstance($type);
|
if (!$registrar) {
|
return '';
|
}
|
$method = 'get'.ucfirst($property);
|
if (!method_exists($registrar, $method)) {
|
error_log('[Resolver]::resolveRegistrar: Invalid property getter: '.$property);
|
return '';
|
}
|
return $registrar->$method();
|
}
|
}
|