schemadotorg_starterkit_layout-1.0.x-dev/src/Plugin/StyleOption/SchemaDotOrgComponent.php
src/Plugin/StyleOption/SchemaDotOrgComponent.php
<?php
declare(strict_types=1);
namespace Drupal\schemadotorg_starterkit_layout\Plugin\StyleOption;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Theme\ComponentPluginManager;
use Drupal\mercury_editor\Form\EditComponentForm;
use Drupal\paragraphs\ParagraphInterface;
use Drupal\style_options\Plugin\StyleOptionPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Define the Schema.org: Component plugin.
*
* @StyleOption(
* id = "schemadotorg_component",
* label = @Translation("Schema.org: Component"),
* )
*/
class SchemaDotOrgComponent extends StyleOptionPluginBase {
/**
* The single directory component manager.
*/
protected ComponentPluginManager $componentManager;
/**
* {@inheritDoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$instance->componentManager = $container->get('plugin.manager.sdc');
return $instance;
}
/**
* {@inheritDoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
$form_object = $form_state->getFormObject();
if (!$form_object instanceof EditComponentForm) {
return $form;
}
// Get components that match the paragraph's bundle.
/** @var \Drupal\paragraphs\ParagraphInterface $paragraph */
$paragraph = $form_object->getParagraph();
$component_base_id = 'schemadotorg_starterkit_layout:' . $paragraph->bundle();
$options = [];
$definitions = $this->componentManager->getDefinitions();
foreach ($definitions as $component_id => $component) {
if (str_starts_with($component_id, $component_base_id)) {
$options[$component_id] = $component['name'];
}
}
if (empty($options)) {
return $form;
}
$form['component'] = [
'#type' => 'select',
'#title' => $this->getLabel(),
'#description' => $this->t('Select a component.'),
'#options' => $options,
'#empty_option' => $this->t('- None -'),
'#default_value' => $this->getValue('component') ?? '',
];
return $form;
}
/**
* {@inheritDoc}
*/
public function build(array $build): array {
// Get the single directory component.
$component = $this->getValue('component');
if (empty($component)) {
return $build;
}
// Make sure the component exists.
if (!$this->componentManager->hasDefinition($component)) {
return $build;
}
// Get the paragraphs.
$paragraph = $build['#paragraph'] ?? NULL;
if (!$paragraph instanceof ParagraphInterface) {
return $build;
}
// Get the Schema.org mapping.
/** @var \Drupal\schemadotorg\SchemaDotOrgMappingStorageInterface $mapping_storage */
$mapping_storage = $this->entityTypeManager->getStorage('schemadotorg_mapping');
$mapping = $mapping_storage->loadByEntity($paragraph);
if (!$mapping) {
return $build;
}
// Get the slots and remove the fields.
$slots = [];
foreach (Element::children($build) as $child_key) {
$schema_property = $mapping->getSchemaPropertyMapping($child_key);
if ($schema_property) {
$slots[$schema_property] = $build[$child_key];
unset($build[$child_key]);
}
}
// Get the properties.
$props = [];
// Return the component.
$build['component'] = [
'#type' => 'component',
'#component' => $component,
'#props' => $props,
'#slots' => $slots,
];
return $build;
}
}
