Skip to content
Snippets Groups Projects
Commit 021bce29 authored by jrockowitz's avatar jrockowitz
Browse files

Issue #3429468: Add subtype support to Schema.org WebPage module

parent e741b48a
No related branches found
No related tags found
No related merge requests found
webpage_schema_subtypes:
- MedicalWebPage
webpage_schema_properties:
- dateCreated
- dateModified
......
......@@ -2,12 +2,18 @@ schemadotorg_webpage.settings:
type: config_object
label: 'Schema.org WebPage settings'
mapping:
webpage_schema_subtypes:
type: sequence
label: 'WebPage Schema.org subtypes'
sequence:
type: string
label: 'WebPage Schema.org subtype'
webpage_schema_properties:
type: sequence
label: 'WebPage Schema.org properties'
sequence:
type: string
label: 'WebPage Schema.org properties'
label: 'WebPage Schema.org property'
default_schema_types:
type: sequence
label: 'Default WebPage Schema.org types'
......
......@@ -2,6 +2,9 @@
type: mapping
label: 'Schema.org WebPage third party settings'
mapping:
schema_subtype:
type: string
label: 'Schema.org WebPage subtype'
schema_properties:
type: sequence
label: 'Schema.org properties'
......
......@@ -19,3 +19,13 @@ function schemadotorg_webpage_install(bool $is_syncing): void {
// all the JSON-LD is create for the current Schema.org content type.
module_set_weight('schemadotorg_webpage', 1);
}
/**
* Add subtype support to Schema.org WebPage module.
*/
function schemadotorg_webpage_update_10000(): void {
\Drupal::configFactory()
->getEditable('schemadotorg_webpage.settings')
->set('webpage_schema_subtypes', ['MedicalWebPage'])
->save();
}
......@@ -10,6 +10,7 @@ declare(strict_types=1);
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\schemadotorg\SchemaDotOrgMappingInterface;
use Drupal\schemadotorg\Utility\SchemaDotOrgArrayHelper;
/**
* Implements hook_schemadotorg_mapping_defaults_alter().
......@@ -89,6 +90,26 @@ function schemadotorg_webpage_schemadotorg_jsonld_alter(array &$data, RouteMatch
$jsonld_builder = \Drupal::service('schemadotorg_jsonld.builder');
$webpage_data = $jsonld_builder->buildEntity($entity, $webpage_mapping);
// Apply subtype.
$webpage_schema_subtype = $mapping->getThirdPartySetting('schemadotorg_webpage', 'schema_subtype');
if ($webpage_schema_subtype) {
// Use the subtype property to override the mapping Schema.org type or
// set the additionalType property.
/** @var \Drupal\schemadotorg\SchemaDotOrgSchemaTypeManagerInterface $schema_type_manager */
$schema_type_manager = \Drupal::service('schemadotorg.schema_type_manager');
if ($schema_type_manager->isSubTypeOf($webpage_schema_subtype, 'WebPage')) {
$webpage_data['@type'] = $webpage_schema_subtype;
}
else {
SchemaDotOrgArrayHelper::insertAfter(
$webpage_data,
'@url',
'additionalType',
$webpage_schema_subtype
);
}
}
// Move BreadCrumb to the WebPage's breadcrumb property.
if (isset($data['schemadotorg_jsonld_breadcrumb_schemadotorg_jsonld'])) {
$webpage_data['breadcrumb'] = $data['schemadotorg_jsonld_breadcrumb_schemadotorg_jsonld'];
......@@ -120,6 +141,17 @@ function schemadotorg_webpage_form_schemadotorg_types_settings_form_alter(array
'#type' => 'details',
'#title' => t('WebPage settings'),
];
$form['schemadotorg_webpage']['webpage_schema_subtypes'] = [
'#type' => 'schemadotorg_settings',
'#title' => t('WebPage Schema.org subtype'),
'#description' => t('Enter the WebPage Schema.org subtypes that should be available when creating a Schema.org WebPage mapping.')
. ' '
. t('Any sub type that is not a subtype of WebPage will be included as an <a href=":href">additional type</a> via JSON-LD.', [':href' => '/additionalType']),
'#description_link' => 'types',
'#example' => "
- MedicalWebPage
",
];
$form['schemadotorg_webpage']['webpage_schema_properties'] = [
'#type' => 'schemadotorg_settings',
'#title' => t('WebPage Schema.org properties'),
......
......@@ -197,6 +197,20 @@ class SchemaDotOrgWebPageManager implements SchemaDotOrgWebPageManagerInterface
'#description' => $this->t('Select the Schema.org properties to be mapped to a WebPage Schema.org type.'),
'#open' => (boolean) $schema_properties,
];
$webpage_schema_subtypes = $this->configFactory
->get('schemadotorg_webpage.settings')
->get('webpage_schema_subtypes');
if ($webpage_schema_subtypes) {
$schema_subtype = $mapping_defaults['third_party_settings']['schemadotorg_webpage']['schema_subtype'] ?? '';
$form['mapping']['third_party_settings']['schemadotorg_webpage']['schema_subtype'] = [
'#type' => 'select',
'#title' => $this->t('WebPage mapping subtype'),
'#description' => $this->t('Select a WebPage Schema.org subtype that should be applied to this mapping.'),
'#options' => array_combine($webpage_schema_subtypes, $webpage_schema_subtypes),
'#empty_option' => $this->t('- Select WebPage subtype -'),
'#default_value' => $schema_subtype,
];
}
$form['mapping']['third_party_settings']['schemadotorg_webpage']['schema_properties'] = [
'#type' => 'tableselect',
'#title' => $this->t('WebPage mapping properties'),
......
......@@ -39,7 +39,7 @@ class SchemaDotOrgWebPageJsonLdKernelTest extends SchemaDotOrgJsonLdKernelTestBa
public function testWebPage(): void {
\Drupal::currentUser()->setAccount($this->createUser(['access content']));
$this->createSchemaEntity('node', 'Recipe');
$mapping = $this->createSchemaEntity('node', 'Recipe');
$node = Node::create([
'type' => 'recipe',
......@@ -56,6 +56,25 @@ class SchemaDotOrgWebPageJsonLdKernelTest extends SchemaDotOrgJsonLdKernelTestBa
$this->assertEquals('WebPage', $jsonld['@type']);
$this->assertEquals('BreadcrumbList', $jsonld['breadcrumb']['@type']);
$this->assertEquals('Recipe', $jsonld['mainEntity']['@type']);
// Check that the JSON-LD WebPage subtyping works as expected with
// a sub type.
$mapping
->setThirdPartySetting('schemadotorg_webpage', 'schema_subtype', 'MedicalWebPage')
->save();
$route_match = $this->manager->getEntityRouteMatch($node);
$jsonld = $this->builder->build($route_match);
$this->assertEquals('MedicalWebPage', $jsonld['@type']);
// Check that the JSON-LD WebPage subtyping works as expected with
// an additional type.
$mapping
->setThirdPartySetting('schemadotorg_webpage', 'schema_subtype', 'NotAWebPage')
->save();
$route_match = $this->manager->getEntityRouteMatch($node);
$jsonld = $this->builder->build($route_match);
$this->assertEquals('WebPage', $jsonld['@type']);
$this->assertEquals('NotAWebPage', $jsonld['additionalType']);
}
}
<?php
declare(strict_types=1);
namespace Drupal\schemadotorg\Utility;
/**
* Provides helper to operate on arrays.
*/
class SchemaDotOrgArrayHelper {
/**
* Inserts a new key/value before the key in the array.
*
* @param array &$array
* An array to insert in to.
* @param string $target_key
* The key to insert before.
* @param string $new_key
* The key to insert.
* @param mixed $new_value
* An value to insert.
*/
public static function insertBefore(array &$array, string $target_key, string $new_key, mixed $new_value): void {
$new = [];
foreach ($array as $k => $value) {
if ($k === $target_key) {
$new[$new_key] = $new_value;
}
$new[$k] = $value;
}
$array = $new;
}
/**
* Inserts a new key/value after the key in the array.
*
* @param array &$array
* An array to insert in to.
* @param string $target_key
* The key to insert after.
* @param string $new_key
* The key to insert.
* @param mixed $new_value
* An value to insert.
*/
public static function insertAfter(array &$array, string $target_key, string $new_key, mixed $new_value): void {
$new = [];
foreach ($array as $key => $value) {
$new[$key] = $value;
if ($key === $target_key) {
$new[$new_key] = $new_value;
}
}
$array = $new;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment