Jake Vanderwerf
2026-02-09 2d0b98416804d8a132895720c9c33e6061bd6752
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<?php
namespace JVBase\managers\SEO\schemas\resolvers;
 
use JVBase\managers\SEO\schemas\SchemaDefinition;
use JVBase\managers\SEO\SchemaFieldHelpers;
use JVBase\managers\SEO\SchemaReferenceBuilder;
use JVBase\meta\Meta;
 
if (!defined('ABSPATH')) {
    exit;
}
 
/**
 * Resolver for VisualArtwork and its children (Tattoo, etc.)
 *
 * Auto-enrichment:
 * - Derives `artform` from taxonomy terms (tattoo-style → "American Traditional")
 * - Derives `artMedium` from taxonomy terms (tattoo-colour → "Black and Grey")
 * - Adds `creator` as Person reference from post author
 * - Adds `keywords` from associated taxonomy terms
 */
class VisualArtworkResolver extends BaseResolver
{
    public function getAutoFields(SchemaDefinition $definition): array
    {
        $fields = [];
 
        if (!$definition->objectId || $definition->objectType !== 'post') {
            return $fields;
        }
 
        $contentConfig = $this->getContentConfig($definition->contentType);
 
        if (empty($contentConfig)) {
            return $fields;
        }
 
        // Derive artform from style taxonomy terms
        $artform = $this->deriveFromTaxonomy($definition->objectId, $contentConfig, 'style');
        if (!empty($artform)) {
            $fields['artform'] = count($artform) === 1 ? $artform[0] : $artform;
        }
 
        // Derive artMedium from medium/colour taxonomy terms
        $medium = $this->deriveFromTaxonomy($definition->objectId, $contentConfig, 'colour');
        if (!empty($medium)) {
            $fields['artMedium'] = count($medium) === 1 ? $medium[0] : $medium;
        }
 
        // Add creator from post author
        $creator = $this->buildCreatorRef($definition->objectId);
        if (!empty($creator)) {
            $fields['creator'] = $creator;
        }
 
        // Add keywords from all associated taxonomy terms
        $keywords = $this->buildKeywords($definition->objectId, $contentConfig);
        if (!empty($keywords)) {
            $fields['keywords'] = $keywords;
        }
 
        return $fields;
    }
 
    /**
     * Derive values from taxonomy terms associated with this post.
     *
     * Looks for taxonomies whose slug contains $hint (e.g., 'style', 'colour').
     */
    private function deriveFromTaxonomy(int $postId, array $contentConfig, string $hint): array
    {
        $values = [];
        $taxonomies = $contentConfig['taxonomies'] ?? [];
 
        foreach ($taxonomies as $taxSlug) {
            $slug = is_array($taxSlug) ? ($taxSlug['taxonomy'] ?? '') : $taxSlug;
 
            if (!str_contains($slug, $hint)) {
                continue;
            }
 
            $fullTax = str_starts_with($slug, BASE) ? $slug : BASE . $slug;
            $terms = wp_get_post_terms($postId, $fullTax, ['fields' => 'names']);
 
            if (!is_wp_error($terms) && !empty($terms)) {
                $values = array_merge($values, $terms);
            }
        }
 
        return array_unique($values);
    }
 
    /**
     * Build Person reference from the post author.
     */
    private function buildCreatorRef(int $postId): ?array
    {
        $post = get_post($postId);
 
        if (!$post || !$post->post_author) {
            return null;
        }
 
        return SchemaReferenceBuilder::build(
            $post->post_author,
            'user',
            'Person'
        );
    }
 
    /**
     * Collect all taxonomy term names as keywords.
     */
    private function buildKeywords(int $postId, array $contentConfig): array
    {
        $keywords = [];
        $taxonomies = $contentConfig['taxonomies'] ?? [];
 
        foreach ($taxonomies as $taxSlug) {
            $slug = is_array($taxSlug) ? ($taxSlug['taxonomy'] ?? '') : $taxSlug;
            $fullTax = str_starts_with($slug, BASE) ? $slug : BASE . $slug;
 
            $terms = wp_get_post_terms($postId, $fullTax, ['fields' => 'names']);
 
            if (!is_wp_error($terms)) {
                $keywords = array_merge($keywords, $terms);
            }
        }
 
        return array_unique($keywords);
    }
 
    /**
     * Get content config from JVB_CONTENT constant.
     */
    private function getContentConfig(?string $contentType): array
    {
        if (!$contentType || !defined('JVB_CONTENT')) {
            return [];
        }
 
        $slug = jvbNoBase($contentType);
 
        return JVB_CONTENT[$slug] ?? [];
    }
}