Jake Vanderwerf
2026-03-29 275c0d74cd68677622a5431505c5c870c473063d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<?php
namespace JVBase\managers\SEO\render\Traits;
 
if (!defined('ABSPATH')) {
    exit;
}
 
use JVBase\managers\SEO\render\DataType\Date;
use JVBase\managers\SEO\render\DataType\DateTime;
use JVBase\managers\SEO\render\DataType\Time;
use JVBase\managers\SEO\render\Thing\Thing;
use JVBase\managers\SEO\render\Traits\_Properties\additionalTypeTrait;
use JVBase\managers\SEO\render\Traits\_Properties\alternateNameTrait;
use JVBase\managers\SEO\render\Traits\_Properties\descriptionTrait;
use JVBase\managers\SEO\render\Traits\_Properties\disambiguatingDescriptionTrait;
use JVBase\managers\SEO\render\Traits\_Properties\imageTrait;
use JVBase\managers\SEO\render\Traits\_Properties\mainEntityOfPageTrait;
use JVBase\managers\SEO\render\Traits\_Properties\nameTrait;
use JVBase\managers\SEO\render\Traits\_Properties\ownerTrait;
use JVBase\managers\SEO\render\Traits\_Properties\potentialActionTrait;
use JVBase\managers\SEO\render\Traits\_Properties\sameAsTrait;
use JVBase\managers\SEO\render\Traits\_Properties\subjectOfTrait;
use JVBase\managers\SEO\render\Traits\_Properties\urlTrait;
 
trait ThingSchema {
    use additionalTypeTrait, alternateNameTrait, descriptionTrait,
        disambiguatingDescriptionTrait, imageTrait, mainEntityOfPageTrait,
        nameTrait, ownerTrait, potentialActionTrait, sameAsTrait, subjectOfTrait, urlTrait;
 
    protected string $id;
 
    protected array $ignore = [
        'mappedMethods',
        'ignore',
        'id'
    ];
    public function outputSchema():array
    {
        global $wp;
        $current = home_url( add_query_arg( $_GET, $wp->request ) );
        $id = (isset($this->id)) ? $this->id : $current.'#'.strtolower($this->getTypeName());
        $elements = array_map(
            function ($value) {
 
                if (is_a($value, Thing::class)) {
                    return $value->outputSchema();
                } elseif (is_array($value)) {
                    $temp = [];
                    foreach ($value as $v) {
                        if (is_a($v, Thing::class)) {
                            $temp[] = $v->outputSchema();
                        } else {
                            $temp[] = $v;
                        }
                    }
                    return $temp;
                }elseif (is_a($value, DateTime::class)) {
                    $value = $value->getDateTime();
                }else if (is_a($value, Date::class)) {
                    $value = $value->getDate();
                } else if (is_a($value, Time::class)) {
                    $value = $value->getTime();
                }else if (!is_string($value)) {
 
                    error_log('Normal value? '.print_r($value, true));
                }
 
                return $value;
            },
            array_filter(get_object_vars($this), function ($property) {
                return !in_array($property, $this->ignore);
            }, ARRAY_FILTER_USE_KEY)
        );
 
        return  array_merge([
            '@type' => $this->getTypeName(),
            '@id'   => $id,
        ], array_filter($elements));
    }
 
    public function getTypeName():string
    {
        return (new \ReflectionClass($this))->getShortName();
    }
 
    public function getProperties():array
    {
        $properties = get_class_vars(self::class);
        $remove = [
            'mappedMethods'
        ];
        return array_filter($properties, function($property) use ($remove) {
            return !in_array($property, $remove);
        }, ARRAY_FILTER_USE_KEY);
    }
 
 
    public static function fromArray(array $config):self
    {
        $instance = new self();
        foreach ($config as $key => $value) {
            if (!property_exists($instance, $key)){
                error_log('[SEO]Could not instantiate '.get_class($instance).' property: '.$key);
                continue;
            }
            $instance->$key = $value;
        }
        return $instance;
    }
 
    public function getId():string {
        return $this->id??false;
    }
    public function setId(string $id):void
    {
        if (!filter_var($id, FILTER_VALIDATE_URL)) {
            error_log('[SEO]Could not set id: '.$id.'. Should be a valid URL');
            return;
        }
        $this->id = $id;
    }
 
    public function delete(string $property):void
    {
        if (property_exists($this, $property)) {
            unset($this->$property);
        }
    }
}