class FieldBlock in Field as Block 8.2
Same name and namespace in other branches
- 8 src/Plugin/Block/FieldBlock.php \Drupal\fieldblock\Plugin\Block\FieldBlock
Provides a fieldblock.
Plugin annotation
@Block(
id = "fieldblock",
admin_label = @Translation("Field as Block"),
deriver = "Drupal\fieldblock\Plugin\Derivative\FieldBlockDeriver"
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Component\Plugin\ContextAwarePluginBase implements ContextAwarePluginInterface
- class \Drupal\Core\Plugin\ContextAwarePluginBase implements CacheableDependencyInterface, ContextAwarePluginInterface uses DependencySerializationTrait, StringTranslationTrait, TypedDataTrait
- class \Drupal\Core\Block\BlockBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface uses BlockPluginTrait, ContextAwarePluginAssignmentTrait
- class \Drupal\fieldblock\Plugin\Block\FieldBlock implements ContainerFactoryPluginInterface
- class \Drupal\Core\Block\BlockBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface uses BlockPluginTrait, ContextAwarePluginAssignmentTrait
- class \Drupal\Core\Plugin\ContextAwarePluginBase implements CacheableDependencyInterface, ContextAwarePluginInterface uses DependencySerializationTrait, StringTranslationTrait, TypedDataTrait
- class \Drupal\Component\Plugin\ContextAwarePluginBase implements ContextAwarePluginInterface
Expanded class hierarchy of FieldBlock
File
- src/
Plugin/ Block/ FieldBlock.php, line 34
Namespace
Drupal\fieldblock\Plugin\BlockView source
class FieldBlock extends BlockBase implements ContainerFactoryPluginInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
/**
* The field formatter plugin manager.
*
* @var \Drupal\Core\Field\FormatterPluginManager
*/
protected $formatterPluginManager;
/**
* The current route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
/**
* The language manager
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
private $languageManager;
/**
* The entity to be used when displaying the block.
*
* @var \Drupal\Core\Entity\ContentEntityInterface
*/
protected $fieldBlockEntity;
/**
* Constructs a FieldBlock object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
* The entity field manager.
* @param \Drupal\Core\Field\FormatterPluginManager $formatter_plugin_manager
* The field formatter plugin manager.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entityTypeManager, EntityFieldManagerInterface $entityFieldManager, FormatterPluginManager $formatter_plugin_manager, RouteMatchInterface $route_match, LanguageManagerInterface $languageManager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityTypeManager = $entityTypeManager;
$this->entityFieldManager = $entityFieldManager;
$this->formatterPluginManager = $formatter_plugin_manager;
$this->routeMatch = $route_match;
$this->languageManager = $languageManager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('entity_type.manager'), $container
->get('entity_field.manager'), $container
->get('plugin.manager.field.formatter'), $container
->get('current_route_match'), $container
->get('language_manager'));
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'label_from_field' => TRUE,
'field_name' => '',
'formatter_id' => '',
'formatter_settings' => [],
];
}
/**
* Returns field options.
*
* @return array
* Array of field option names keyed by their machine name.
*/
protected function getFieldOptions() {
$field_definitions = $this->entityFieldManager
->getFieldStorageDefinitions($this
->getDerivativeId());
$options = [];
foreach ($field_definitions as $definition) {
$options[$definition
->getName()] = $definition
->getLabel();
}
return $options;
}
/**
* Returns field formatter names.
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The definition of the field.
*
* @return array
* Array of formatter names keyed by field type.
*/
protected function getFormatterOptions(FieldDefinitionInterface $field_definition) {
$options = $this->formatterPluginManager
->getOptions($field_definition
->getType());
foreach ($options as $id => $label) {
$definition = $this->formatterPluginManager
->getDefinition($id, FALSE);
$formatter_plugin_class = isset($definition['class']) ? $definition['class'] : NULL;
$applicable = $formatter_plugin_class instanceof FormatterInterface && $formatter_plugin_class::isApplicable($field_definition);
if ($applicable) {
unset($options[$id]);
}
}
return $options;
}
/**
* Gets the field definition.
*
* A FieldBlock works on an entity type across bundles, and thus only has
* access to field storage definitions. In order to be able to use formatters,
* we create a generic field definition out of that storage definition.
*
* @param string $field_name
* The field name.
*
* @see BaseFieldDefinition::createFromFieldStorageDefinition()
* @see \Drupal\views\Plugin\views\field\Field::getFieldDefinition()
*
* @return \Drupal\Core\Field\FieldDefinitionInterface
* The field definition used by this block.
*/
protected function getFieldDefinition($field_name) {
$field_storage_config = $this
->getFieldStorageDefinition($field_name);
return BaseFieldDefinition::createFromFieldStorageDefinition($field_storage_config);
}
/**
* Gets the field storage definition.
*
* @param string $field_name
* The field name.
*
* @return \Drupal\Core\Field\FieldStorageDefinitionInterface
* The field storage definition used by this block.
*/
protected function getFieldStorageDefinition($field_name) {
$field_storage_definitions = $this->entityFieldManager
->getFieldStorageDefinitions($this
->getDerivativeId());
return $field_storage_definitions[$field_name];
}
/**
* {@inheritdoc}
*/
public function blockForm($form, FormStateInterface $form_state) {
// This method receives a sub form state instead of the full form state.
// There is an ongoing discussion around this which could result in the
// passed form state going back to a full form state. In order to prevent
// future breakage because of a core update we'll just check which type of
// FormStateInterface we've been passed and act accordingly.
// @See https://www.drupal.org/node/2798261
if ($form_state instanceof SubformStateInterface) {
$form_state = $form_state
->getCompleteFormState();
}
$form['label_from_field'] = [
'#title' => $this
->t('Use field label as block title'),
'#type' => 'checkbox',
'#default_value' => $this->configuration['label_from_field'],
];
$form['field_name'] = [
'#title' => $this
->t('Field'),
'#type' => 'select',
'#options' => $this
->getFieldOptions(),
'#default_value' => $this->configuration['field_name'],
'#required' => TRUE,
'#ajax' => [
'callback' => [
$this,
'blockFormChangeFieldOrFormatterAjax',
],
'wrapper' => 'edit-block-formatter-wrapper',
],
];
$form['formatter'] = [
'#type' => 'container',
'#id' => 'edit-block-formatter-wrapper',
];
$field_name = $form_state
->getValue([
'settings',
'field_name',
], $this->configuration['field_name']);
$field_definition = NULL;
$formatter_id = $form_state
->getValue([
'settings',
'formatter',
'id',
], $this->configuration['formatter_id']);
if ($field_name) {
$field_definition = $this
->getFieldDefinition($field_name);
$formatter_options = $this
->getFormatterOptions($field_definition);
if (empty($formatter_options)) {
$formatter_id = '';
}
else {
if (empty($formatter_id)) {
$formatter_id = key($formatter_options);
}
$form['formatter']['id'] = [
'#title' => $this
->t('Formatter'),
'#type' => 'select',
'#options' => $formatter_options,
'#default_value' => $this->configuration['formatter_id'],
'#required' => TRUE,
'#ajax' => [
'callback' => [
$this,
'blockFormChangeFieldOrFormatterAjax',
],
'wrapper' => 'edit-block-formatter-wrapper',
],
];
}
}
$form['formatter']['change'] = [
'#type' => 'submit',
'#name' => 'fieldblock_change_field',
'#value' => $this
->t('Change field'),
'#attributes' => [
'class' => [
'js-hide',
],
],
'#limit_validation_errors' => [
[
'settings',
],
],
'#submit' => [
[
get_class($this),
'blockFormChangeFieldOrFormatter',
],
],
];
if ($formatter_id) {
$formatter_settings = $this->configuration['formatter_settings'] + $this->formatterPluginManager
->getDefaultSettings($formatter_id);
$formatter_options = [
'field_definition' => $field_definition,
'view_mode' => '_custom',
'configuration' => [
'type' => $formatter_id,
'settings' => $formatter_settings,
'label' => '',
'weight' => 0,
],
];
if ($formatter_plugin = $this->formatterPluginManager
->getInstance($formatter_options)) {
$formatter_settings_form = $formatter_plugin
->settingsForm($form, $form_state);
// Convert field UI selector states to work in the block configuration
// form.
FormHelper::rewriteStatesSelector($formatter_settings_form, "fields[{$field_name}][settings_edit_form]", 'settings[formatter][settings]');
}
if (!empty($formatter_settings_form)) {
$form['formatter']['settings'] = $formatter_settings_form;
$form['formatter']['settings']['#type'] = 'fieldset';
$form['formatter']['settings']['#title'] = $this
->t('Formatter settings');
}
}
return $form;
}
/**
* Element submit handler for non-JS field/formatter changes.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public static function blockFormChangeFieldOrFormatter(array $form, FormStateInterface $form_state) {
$form_state
->setRebuild();
}
/**
* Ajax callback on changing field_name or formatter_id form element.
*
* @param array $form
* The form.
*
* @return array
* The part of the form that has changed.
*/
public function blockFormChangeFieldOrFormatterAjax(array $form) {
return $form['settings']['formatter'];
}
/**
* {@inheritdoc}
*/
public function blockSubmit($form, FormStateInterface $form_state) {
$this->configuration['label_from_field'] = $form_state
->getValue('label_from_field');
$this->configuration['field_name'] = $form_state
->getValue('field_name');
$this->configuration['formatter_id'] = $form_state
->getValue([
'formatter',
'id',
], '');
$this->configuration['formatter_settings'] = $form_state
->getValue([
'formatter',
'settings',
], []);
}
/**
* {@inheritdoc}
*
* @see \Drupal\views\Plugin\views\field\Field::calculateDependencies()
*/
public function calculateDependencies() {
$dependencies = parent::calculateDependencies();
// Add the module providing the configured field storage as a dependency.
if (($field_storage_definition = $this
->getFieldStorageDefinition($this->configuration['field_name'])) && $field_storage_definition instanceof EntityInterface) {
$dependencies['config'][] = $field_storage_definition
->getConfigDependencyName();
}
// Add the module providing the formatter.
if (!empty($this->configuration['formatter_id'])) {
$dependencies['module'][] = $this->formatterPluginManager
->getDefinition($this->configuration['formatter_id'])['provider'];
}
return $dependencies;
}
/**
* {@inheritdoc}
*/
protected function blockAccess(AccountInterface $account) {
$entity = $this
->getEntity();
if ($entity) {
$field = $entity
->get($this->configuration['field_name']);
return AccessResult::allowedIf(!$field
->isEmpty() && $field
->access('view', $account));
}
return AccessResult::forbidden();
}
/**
* {@inheritdoc}
*/
public function build() {
$build = [];
$entity = $this
->getEntity();
if ($entity) {
$build['field'] = $this
->getTranslatedFieldFromEntity($entity)
->view([
'label' => 'hidden',
'type' => $this->configuration['formatter_id'],
'settings' => $this->configuration['formatter_settings'],
]);
if ($this->configuration['label_from_field'] && !empty($build['field']['#title'])) {
$build['#title'] = $build['field']['#title'];
}
}
return $build;
}
/**
* Ensure that the field gets correctly translated into the current language
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
*
* @return \Drupal\Core\Field\FieldItemListInterface
*/
private function getTranslatedFieldFromEntity(ContentEntityInterface $entity) {
$language = $this->languageManager
->getCurrentLanguage()
->getId();
$field = $entity
->get($this->configuration['field_name']);
if ($entity
->hasTranslation($language)) {
$translatedEntity = $entity
->getTranslation($language);
$adapter = EntityAdapter::createFromEntity($translatedEntity);
$field
->setContext($this->configuration['field_name'], $adapter);
}
return $field;
}
/**
* {@inheritdoc}
*/
public function getCacheTags() {
$entity = $this
->getEntity();
if ($entity) {
return $entity
->getCacheTags();
}
return parent::getCacheTags();
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
// This block must be cached per route: every entity has its own canonical
// url and its own fields.
return [
'route',
];
}
/**
* Finds the entity to be used when displaying the block.
*
* @return \Drupal\Core\Entity\ContentEntityInterface|null
* The entity to be used when displaying the block.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function getEntity() {
if (!isset($this->fieldBlockEntity)) {
$entity_type = $this
->getDerivativeId();
$entity = NULL;
$field_name = $this->configuration['field_name'];
$route_name = $this->routeMatch
->getRouteName();
$is_canonical_route = $route_name === 'entity.' . $entity_type . '.canonical';
$is_latest_route = $route_name == 'entity.' . $entity_type . '.latest_version';
if ($is_canonical_route || $is_latest_route) {
$entity = $this->routeMatch
->getParameter($entity_type);
}
elseif ($entity_type === 'node') {
if ($route_name == 'entity.node.revision') {
$entity_revision = $this->routeMatch
->getParameter('node_revision');
$entity = $this->entityTypeManager
->getStorage('node')
->loadRevision($entity_revision);
}
elseif ($route_name == 'entity.node.preview' && $this->routeMatch
->getParameter('view_mode_id') === 'full') {
$entity = $this->routeMatch
->getParameter('node_preview');
}
}
if ($entity instanceof ContentEntityInterface && $entity
->getEntityTypeId() === $entity_type && $entity
->hasField($field_name)) {
$this->fieldBlockEntity = $entity;
}
}
return $this->fieldBlockEntity;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
BlockPluginInterface:: |
constant | Indicates the block label (title) should be displayed to end users. | ||
BlockPluginTrait:: |
protected | property | The transliteration service. | |
BlockPluginTrait:: |
public | function | ||
BlockPluginTrait:: |
protected | function | Returns generic default configuration for block plugins. | |
BlockPluginTrait:: |
public | function | 3 | |
BlockPluginTrait:: |
public | function | Creates a generic configuration form for all block types. Individual block plugins can add elements to this form by overriding BlockBase::blockForm(). Most block plugins should not override this method unless they need to alter the generic form elements. | 2 |
BlockPluginTrait:: |
public | function | 1 | |
BlockPluginTrait:: |
public | function | 1 | |
BlockPluginTrait:: |
public | function | 3 | |
BlockPluginTrait:: |
public | function | ||
BlockPluginTrait:: |
public | function | ||
BlockPluginTrait:: |
public | function | ||
BlockPluginTrait:: |
public | function | Sets the transliteration service. | |
BlockPluginTrait:: |
public | function | Most block plugins should not override this method. To add submission handling for a specific block type, override BlockBase::blockSubmit(). | |
BlockPluginTrait:: |
protected | function | Wraps the transliteration service. | |
BlockPluginTrait:: |
public | function | Most block plugins should not override this method. To add validation for a specific block type, override BlockBase::blockValidate(). | 1 |
ContextAwarePluginAssignmentTrait:: |
protected | function | Builds a form element for assigning a context to a given slot. | |
ContextAwarePluginAssignmentTrait:: |
protected | function | Wraps the context handler. | |
ContextAwarePluginBase:: |
protected | property | The data objects representing the context of this plugin. | |
ContextAwarePluginBase:: |
private | property | Data objects representing the contexts passed in the plugin configuration. | |
ContextAwarePluginBase:: |
protected | function |
Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
The maximum age for which this object may be cached. Overrides CacheableDependencyInterface:: |
7 |
ContextAwarePluginBase:: |
public | function |
This code is identical to the Component in order to pick up a different
Context class. Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Gets a mapping of the expected assignment names to their context names. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Gets the defined contexts. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Gets the value for a defined context. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Gets the values for all defined contexts. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Set a context on this plugin. Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Sets a mapping of the expected assignment names to their context names. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function |
Sets the value for a defined context. Overrides ContextAwarePluginBase:: |
|
ContextAwarePluginBase:: |
public | function |
Validates the set values for the defined contexts. Overrides ContextAwarePluginInterface:: |
|
ContextAwarePluginBase:: |
public | function | Implements magic __get() method. | |
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FieldBlock:: |
protected | property | The entity field manager. | |
FieldBlock:: |
protected | property | The entity type manager. | |
FieldBlock:: |
protected | property | The entity to be used when displaying the block. | |
FieldBlock:: |
protected | property | The field formatter plugin manager. | |
FieldBlock:: |
private | property | The language manager | |
FieldBlock:: |
protected | property | The current route match. | |
FieldBlock:: |
protected | function |
Indicates whether the block should be shown. Overrides BlockPluginTrait:: |
|
FieldBlock:: |
public | function |
Overrides BlockPluginTrait:: |
|
FieldBlock:: |
public static | function | Element submit handler for non-JS field/formatter changes. | |
FieldBlock:: |
public | function | Ajax callback on changing field_name or formatter_id form element. | |
FieldBlock:: |
public | function |
Overrides BlockPluginTrait:: |
|
FieldBlock:: |
public | function |
Builds and returns the renderable array for this block plugin. Overrides BlockPluginInterface:: |
|
FieldBlock:: |
public | function |
Overrides BlockPluginTrait:: |
|
FieldBlock:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
|
FieldBlock:: |
public | function |
Overrides BlockPluginTrait:: |
|
FieldBlock:: |
public | function |
The cache contexts associated with this object. Overrides ContextAwarePluginBase:: |
|
FieldBlock:: |
public | function |
The cache tags associated with this object. Overrides ContextAwarePluginBase:: |
|
FieldBlock:: |
protected | function | Finds the entity to be used when displaying the block. | |
FieldBlock:: |
protected | function | Gets the field definition. | |
FieldBlock:: |
protected | function | Returns field options. | |
FieldBlock:: |
protected | function | Gets the field storage definition. | |
FieldBlock:: |
protected | function | Returns field formatter names. | |
FieldBlock:: |
private | function | Ensure that the field gets correctly translated into the current language | |
FieldBlock:: |
public | function |
Constructs a FieldBlock object. Overrides BlockPluginTrait:: |
|
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
PluginWithFormsTrait:: |
public | function | ||
PluginWithFormsTrait:: |
public | function | ||
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
TypedDataTrait:: |
protected | property | The typed data manager used for creating the data types. | |
TypedDataTrait:: |
public | function | Gets the typed data manager. | 2 |
TypedDataTrait:: |
public | function | Sets the typed data manager. | 2 |