Skip to content

Commit b21263e

Browse files
Added support for structured data templates on Terms
2 parents c2aa6c4 + ecdb9a8 commit b21263e

File tree

15 files changed

+216
-67
lines changed

15 files changed

+216
-67
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This Statamic addon provides a powerful and flexible way to add structured data
44

55
## Features
66

7-
- 🔄 Dynamic JSON-LD generation based on entry data
7+
- 🔄 Dynamic JSON-LD generation based on entry and term data
88
- 📝 Template-based structured data configuration
99
- 🔌 Automatic injection of structured data into your pages
1010
- 🎯 Support for multiple schemas per page
@@ -37,7 +37,7 @@ Create templates in your Statamic control panel that define your structured data
3737

3838
### 2. Assigning Templates to Entries
3939

40-
In your entry's content, you can assign one or more structured data templates using the `structured_data_templates` field. The addon will automatically process these templates and generate the appropriate JSON-LD scripts.
40+
In your entry or term's content, you can assign one or more structured data templates using the `structured_data_templates` field. The addon will automatically process these templates and generate the appropriate JSON-LD scripts.
4141

4242
### 3. Automatic Injection
4343

@@ -71,4 +71,4 @@ Here's an example of how you might structure a basic Organization schema:
7171

7272
## Configuration
7373

74-
The addon works out of the box with sensible defaults. Configuration can be customized through your entry blueprints and templates.
74+
The addon works out of the box with sensible defaults. Configuration can be customized through your entry and term blueprints and templates.

config/structured-data.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@
55
// Add collection handles here that should have structured data templates
66
// Example: 'pages', 'blog', 'products'
77
],
8+
'taxonomies' => [
9+
// Add taxonomy handles here that should have structured data objects
10+
// Example: 'categories', 'tags'
11+
],
812
];

resources/blueprints/collections/structured_data_templates/structured_data_templates.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ tabs:
3232
type: slug
3333
localizable: true
3434
validate: 'max:200'
35+
-
36+
handle: blueprint_type
37+
field:
38+
options:
39+
-
40+
key: collection
41+
value: Collection
42+
-
43+
key: taxonomy
44+
value: Taxonomy
45+
max_items: 1
46+
default: collection
47+
type: select
48+
display: 'Blueprint type'
49+
localizable: true
3550
-
3651
handle: use_for_collection
3752
field:
@@ -40,7 +55,22 @@ tabs:
4055
display: 'Use for collection'
4156
localizable: true
4257
validate:
58+
- sometimes
59+
- required
60+
if:
61+
blueprint_type: 'equals collection'
62+
-
63+
handle: use_for_taxonomy
64+
field:
65+
max_items: 1
66+
type: taxonomies
67+
display: 'Use for taxonomy'
68+
localizable: true
69+
validate:
70+
- sometimes
4371
- required
72+
if:
73+
blueprint_type: 'equals taxonomy'
4474
-
4575
handle: structured_data_available_variables
4676
field:

resources/dist/build/assets/statamic-structured-data-33d7377e.css renamed to resources/dist/build/assets/statamic-structured-data-05ad0e35.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/dist/build/assets/statamic-structured-data-08e9c173.js renamed to resources/dist/build/assets/statamic-structured-data-0787df7f.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/dist/build/manifest.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
"src": "resources/css/statamic-structured-data.css"
66
},
77
"resources/js/statamic-structured-data.css": {
8-
"file": "assets/statamic-structured-data-33d7377e.css",
8+
"file": "assets/statamic-structured-data-05ad0e35.css",
99
"src": "resources/js/statamic-structured-data.css"
1010
},
1111
"resources/js/statamic-structured-data.js": {
1212
"css": [
13-
"assets/statamic-structured-data-33d7377e.css"
13+
"assets/statamic-structured-data-05ad0e35.css"
1414
],
15-
"file": "assets/statamic-structured-data-08e9c173.js",
15+
"file": "assets/statamic-structured-data-0787df7f.js",
1616
"isEntry": true,
1717
"src": "resources/js/statamic-structured-data.js"
1818
}

resources/js/components/fieldtypes/AvailableVariables.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ export default {
6868
variables() {
6969
return this.meta?.variables || {
7070
config: {},
71-
entry: []
71+
entry: [],
72+
term: []
7273
};
7374
},
7475

src/Fieldtypes/AvailableVariablesFieldtype.php

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ protected function getAvailableVariables(): array
3131
{
3232
return [
3333
'site' => [
34-
['name' => 'site:name', 'description' => 'Site Name'],
35-
['name' => 'site:url', 'description' => 'Site URL'],
36-
],
34+
['name' => 'site:name', 'description' => 'Site Name'],
35+
['name' => 'site:url', 'description' => 'Site URL'],
36+
],
3737
'globals' => $this->getGlobalVariables(),
3838
'entry' => $this->getEntryFields(),
39+
'term' => $this->getTermFields(),
3940
];
4041
}
4142

@@ -65,15 +66,15 @@ protected function getEntryFields(): array
6566
return [];
6667
}
6768

68-
$fields = collect($dataTemplate?->use_for_collection?->entryBlueprints()?->reduce(function($carry, $blueprint) {
69+
$fields = collect($dataTemplate?->use_for_collection?->entryBlueprints()?->reduce(function ($carry, $blueprint) {
6970
return array_merge($carry, $blueprint->fields()->items()->toArray());
7071
}, []) ?? []);
7172

72-
if(class_exists(OnPageSeoBlueprint::class)) {
73+
if (class_exists(OnPageSeoBlueprint::class)) {
7374
$fields = $fields->merge(OnPageSeoBlueprint::requestBlueprint()->fields()?->items());
7475
}
7576

76-
if (!$fields) {
77+
if (! $fields) {
7778
return [];
7879
}
7980

@@ -82,9 +83,41 @@ protected function getEntryFields(): array
8283
$collectionFields = $fields->map(function ($field) {
8384
return $this->setFieldData($field);
8485
})
85-
->filter()
86-
->values()
87-
->all();
86+
->filter()
87+
->values()
88+
->all();
89+
90+
return array_merge($baseFields, $collectionFields);
91+
}
92+
93+
protected function getTermFields(): array
94+
{
95+
$dataTemplate = $this->field->parent();
96+
97+
if (! $dataTemplate?->use_for_taxonomy?->termBlueprints()?->first()) {
98+
return [];
99+
}
100+
101+
$fields = collect($dataTemplate?->use_for_taxonomy?->termBlueprints()?->reduce(function ($carry, $blueprint) {
102+
return array_merge($carry, $blueprint->fields()->items()->toArray());
103+
}, []) ?? []);
104+
105+
if (class_exists(OnPageSeoBlueprint::class)) {
106+
$fields = $fields->merge(OnPageSeoBlueprint::requestBlueprint()->fields()?->items());
107+
}
108+
109+
if (! $fields) {
110+
return [];
111+
}
112+
113+
$baseFields = [['name' => 'absolute_url', 'description' => 'Full URL']];
114+
115+
$collectionFields = $fields->map(function ($field) {
116+
return $this->setFieldData($field);
117+
})
118+
->filter()
119+
->values()
120+
->all();
88121

89122
return array_merge($baseFields, $collectionFields);
90123
}
@@ -99,8 +132,9 @@ protected function getGlobalVariables(): array
99132

100133
if ($fields) {
101134
$globalVariables = $fields->items()->map(function ($field) use ($globalSet) {
102-
$name = ($globalSet->handle() . ':' . ($field['handle'] ?? ''));
135+
$name = ($globalSet->handle().':'.($field['handle'] ?? ''));
103136
$description = ($field['field']['display'] ?? ($field['handle'] ?? ''));
137+
104138
return $this->setFieldData($field, $name, $description);
105139
})->values()->all();
106140
}
@@ -113,27 +147,28 @@ protected function getGlobalVariables(): array
113147

114148
protected function getCollectionVariables(string $collectionHandle, array $field): array
115149
{
116-
if(!$collectionHandle || $collectionHandle === 'structured_data_templates') {
150+
if (! $collectionHandle || $collectionHandle === 'structured_data_templates') {
117151
return [];
118152
}
119153

120154
return Collection::find($collectionHandle)?->entryBlueprints()?->first()?->fields()?->items()?->map(function ($entryField) use ($field) {
121-
$name = ($field['handle'] . ':' . ($entryField['handle'] ?? ''));
122-
$description = (($field['field']['display'] ?? '') . ': ' . ($entryField['field']['display'] ?? ($entryField['handle'] ?? '')));
155+
$name = ($field['handle'].':'.($entryField['handle'] ?? ''));
156+
$description = (($field['field']['display'] ?? '').': '.($entryField['field']['display'] ?? ($entryField['handle'] ?? '')));
157+
123158
return $this->setFieldData($entryField, $name, $description, false);
124159
})->filter()->values()->all();
125160
}
126161

127162
protected function setFieldData(array $field, ?string $name = null, ?string $description = null, bool $recursive = true): ?array
128163
{
129-
if(!($field['handle'] ?? false) || $field['handle'] === 'parent' || !($field['field']['type'] ?? false) || !$this->fieldTypeIsEligible($field['field']['type'])) {
164+
if (! ($field['handle'] ?? false) || $field['handle'] === 'parent' || ! ($field['field']['type'] ?? false) || ! $this->fieldTypeIsEligible($field['field']['type'])) {
130165
return null;
131166
}
132167

133168
$children = [];
134169

135-
if($field['field']['type'] === 'entries' && $recursive) {
136-
if(!isset($field['field']['collections'][0])) {
170+
if ($field['field']['type'] === 'entries' && $recursive) {
171+
if (! isset($field['field']['collections'][0])) {
137172
return null;
138173
}
139174

@@ -143,7 +178,7 @@ protected function setFieldData(array $field, ?string $name = null, ?string $des
143178
return [
144179
'name' => $name ?? $field['handle'],
145180
'description' => $description ?? ($field['field']['display'] ?? $field['handle']),
146-
'children' => $children
181+
'children' => $children,
147182
];
148183
}
149184
}

src/Fieldtypes/StructuredDataBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
use Illuminate\Support\Collection;
66
use Statamic\Facades\Site;
7-
use Statamic\Fields\Fieldtype;
87
use Statamic\Facades\Taxonomy;
8+
use Statamic\Fields\Fieldtype;
99

1010
class StructuredDataBuilder extends Fieldtype
1111
{

src/Http/Controllers/StructuredDataController.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Justbetter\StatamicStructuredData\Parser\StructuredDataParser;
77
use Statamic\Facades\Entry;
88
use Statamic\Facades\Site;
9+
use Statamic\Facades\Term;
910
use Statamic\Http\Controllers\CP\CpController;
1011

1112
class StructuredDataController extends CpController
@@ -36,6 +37,10 @@ public function getTemplates(Request $request)
3637
$templateIds = $request->input('ids', []);
3738
$contentEntry = Entry::find($request->input('entry_id'));
3839

40+
if (! $contentEntry) {
41+
$contentEntry = Term::find($request->input('entry_id'));
42+
}
43+
3944
if (! $contentEntry) {
4045
return response()->json(['error' => 'Content entry not found'], 404);
4146
}
@@ -50,7 +55,7 @@ public function getTemplates(Request $request)
5055

5156
$structuredData = $entry->schema_data;
5257

53-
if (!$structuredData) {
58+
if (! $structuredData) {
5459
return null;
5560
}
5661

@@ -86,7 +91,7 @@ public function getAvailableVariables(Request $request)
8691
'entry' => [],
8792
];
8893

89-
if (!$entry) {
94+
if (! $entry) {
9095
return response()->json($variables);
9196
}
9297

0 commit comments

Comments
 (0)