Commit 37574368 authored by git's avatar git Committed by slashrsm

Issue #2736741 by Denchev: Treat each view mode in "Rendered entity" formatter...

Issue #2736741 by Denchev: Treat each view mode in "Rendered entity" formatter as a standalone formatter.
parent c248cda0
......@@ -49,18 +49,19 @@ Entity Embed can be installed via the
* Click on the 'E' button in the text editor.
* Enter part of the title of the entity you're looking for and select
one of the search results.
* For **Display as**, choose one of the following options:
* Rendered Entity
* If the entity you select is a node entity, for **Display as** you can choose
one of the following options:
* Entity ID
* Label
* If chosen **Rendered Entity**, choose one of the following options for
**View mode**:
* Default
* Full content
* RSS
* Search index
* Search result highlighting input
* Teaser
* The last five options depend on the view modes you have on the entity.
* Optionally, choose to align left, center or right.
**Rendered Entity** was available before but now the view modes are
available as entity embed display plugins.
## Embedding entities without WYSIWYG
......
......@@ -29,3 +29,11 @@ embed.embed_type_settings.entity:
display_review:
type: boolean
label: 'Display review step'
entity_embed.settings:
type: config_object
label: 'Entity embed settings'
mapping:
rendered_entity_mode:
type: boolean
label: 'Rendered entity mode'
......@@ -43,3 +43,13 @@ function entity_embed_update_8001() {
$old_embed_button->delete();
}
}
/**
* Updates the default mode settings.
*/
function entity_embed_update_8002() {
\Drupal::configFactory()
->getEditable('entity_embed.settings')
->set('rendered_entity_mode', TRUE)
->save();
}
<?php
/**
* @file
* Contains \Drupal\entity_embed\Annotation\EntityEmbedDisplay.
*/
namespace Drupal\entity_embed\Annotation;
use Drupal\Component\Annotation\Plugin;
......@@ -53,4 +48,11 @@ class EntityEmbedDisplay extends Plugin {
*/
public $entity_types = FALSE;
/**
* Shows plugin in the UI if this is FALSE.
*
* @var bool
*/
public $no_ui = FALSE;
}
<?php
/**
* @file
* Contains \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager.
*/
namespace Drupal\entity_embed\EntityEmbedDisplay;
use Drupal\Core\Cache\CacheBackendInterface;
......@@ -87,7 +82,10 @@ class EntityEmbedDisplayManager extends DefaultPluginManager {
}
/**
* Provides a list of plugins that can be used for a certain entity.
* Gets definition options for entity.
*
* Provides a list of plugins that can be used for a certain entity and
* filters out plugins that should be hidden in the UI.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* An entity object.
......@@ -97,13 +95,32 @@ class EntityEmbedDisplayManager extends DefaultPluginManager {
*/
public function getDefinitionOptionsForEntity(EntityInterface $entity) {
$definitions = $this->getDefinitionsForContexts(array('entity' => $entity, 'entity_type' => $entity->getEntityTypeId()));
$definitions = $this->filterExposedDefinitions($definitions);
return array_map(function ($definition) {
return (string) $definition['label'];
}, $definitions);
}
/**
* Provides a list of plugins that can be used for a certain entity type.
* Filters out plugins from definitions that should be hidden in the UI.
*
* @param array $definitions
* The array of plugin definitions.
*
* @return array
* Returns plugin definitions that should be displayed in the UI.
*/
protected function filterExposedDefinitions(array $definitions) {
return array_filter($definitions, function($definition) {
return empty($definition['no_ui']);
});
}
/**
* Gets definition options for entity type.
*
* Provides a list of plugins that can be used for a certain entity type and
* filters out plugins that should be hidden in the UI.
*
* @param string $entity_type
* The entity type id.
......@@ -113,6 +130,7 @@ class EntityEmbedDisplayManager extends DefaultPluginManager {
*/
public function getDefinitionOptionsForEntityType($entity_type) {
$definitions = $this->getDefinitionsForContexts(array('entity_type' => $entity_type));
$definitions = $this->filterExposedDefinitions($definitions);
return array_map(function ($definition) {
return (string) $definition['label'];
}, $definitions);
......
<?php
/**
* @file
* Contains \Drupal\entity_embed\EntityEmbedDisplay\FieldFormatterEntityEmbedDisplayBase.
*/
namespace Drupal\entity_embed\EntityEmbedDisplay;
use Drupal\Core\Access\AccessResult;
......@@ -123,10 +118,20 @@ abstract class FieldFormatterEntityEmbedDisplayBase extends EntityEmbedDisplayBa
* Returns the access result.
*/
protected function isApplicableFieldFormatter() {
$definition = $this->formatterPluginManager->getDefinition($this->getDerivativeId());
$definition = $this->formatterPluginManager->getDefinition($this->getFieldFormatterId());
return AccessResult::allowedIf($definition['class']::isApplicable($this->getFieldDefinition()));
}
/**
* Returns the field formatter id.
*
* @return string|null
* Returns field formatter id or null.
*/
public function getFieldFormatterId() {
return $this->getDerivativeId();
}
/**
* {@inheritdoc}
*/
......@@ -163,7 +168,7 @@ abstract class FieldFormatterEntityEmbedDisplayBase extends EntityEmbedDisplayBa
* {@inheritdoc}
*/
public function defaultConfiguration() {
return $this->formatterPluginManager->getDefaultSettings($this->getDerivativeId());
return $this->formatterPluginManager->getDefaultSettings($this->getFieldFormatterId());
}
/**
......@@ -182,7 +187,7 @@ abstract class FieldFormatterEntityEmbedDisplayBase extends EntityEmbedDisplayBa
public function getFieldFormatter() {
if (!isset($this->fieldFormatter)) {
$display = array(
'type' => $this->getDerivativeId(),
'type' => $this->getFieldFormatterId(),
'settings' => $this->getConfiguration(),
'label' => 'hidden',
);
......@@ -223,7 +228,7 @@ abstract class FieldFormatterEntityEmbedDisplayBase extends EntityEmbedDisplayBa
public function calculateDependencies() {
$this->addDependencies(parent::calculateDependencies());
$definition = $this->formatterPluginManager->getDefinition($this->getDerivativeId());
$definition = $this->formatterPluginManager->getDefinition($this->getFieldFormatterId());
$this->addDependency('module', $definition['provider']);
// @todo Investigate why this does not work currently.
//$this->calculatePluginDependencies($this->getFieldFormatter());
......
<?php
/**
* @file
* Contains \Drupal\entity_embed\Plugin\Derivative\FieldFormatterDeriver.
*/
namespace Drupal\entity_embed\Plugin\Derivative;
use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Field\FormatterPluginManager;
......@@ -26,14 +22,24 @@ class FieldFormatterDeriver extends DeriverBase implements ContainerDeriverInter
*/
protected $formatterManager;
/**
* The config factory service.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Constructs new FieldFormatterEntityEmbedDisplayBase.
*
* @param \Drupal\Core\Field\FormatterPluginManager $formatter_manager
* The field formatter plugin manager.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* A config factory for retrieving required config objects.
*/
public function __construct(FormatterPluginManager $formatter_manager) {
public function __construct(FormatterPluginManager $formatter_manager, ConfigFactoryInterface $config_factory) {
$this->formatterManager = $formatter_manager;
$this->configFactory = $config_factory;
}
/**
......@@ -41,7 +47,8 @@ class FieldFormatterDeriver extends DeriverBase implements ContainerDeriverInter
*/
public static function create(ContainerInterface $container, $base_plugin_id) {
return new static(
$container->get('plugin.manager.field.formatter')
$container->get('plugin.manager.field.formatter'),
$container->get('config.factory')
);
}
......@@ -58,9 +65,17 @@ class FieldFormatterDeriver extends DeriverBase implements ContainerDeriverInter
if (!isset($base_plugin_definition['field_type'])) {
throw new \LogicException("Undefined field_type definition in plugin {$base_plugin_definition['id']}.");
}
$mode = $this->configFactory->get('entity_embed.settings')->get('rendered_entity_mode');
foreach ($this->formatterManager->getOptions($base_plugin_definition['field_type']) as $formatter => $label) {
$this->derivatives[$formatter] = $base_plugin_definition;
$this->derivatives[$formatter]['label'] = $label;
// Don't show entity_reference_entity_view in the UI if the rendered
// entity mode is FALSE. In that case we show view modes from
// ViewModeDeriver, entity_reference_entity_view is kept for backwards
// compatibility.
if ($formatter == 'entity_reference_entity_view' && $mode == FALSE) {
$this->derivatives[$formatter]['no_ui'] = TRUE;
}
}
return $this->derivatives;
}
......
<?php
namespace Drupal\entity_embed\Plugin\Derivative;
use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides Entity Embed Display plugin definitions for view modes.
*
* @see \Drupal\entity_embed\FieldFormatterEntityEmbedDisplayBase
*/
class ViewModeDeriver extends DeriverBase implements ContainerDeriverInterface {
/**
* The entity display repository.
*
* @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
*/
protected $entityDisplayRepository;
/**
* The config factory service.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Constructs a ViewModeDeriver object.
*
* @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
* The entity display repository.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* A config factory for retrieving required config objects.
*/
public function __construct(EntityDisplayRepositoryInterface $entity_display_repository, ConfigFactoryInterface $config_factory) {
$this->entityDisplayRepository = $entity_display_repository;
$this->configFactory = $config_factory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, $base_plugin_id) {
return new static(
$container->get('entity_display.repository'),
$container->get('config.factory')
);
}
/**
* {@inheritdoc}
*/
public function getDerivativeDefinitions($base_plugin_definition) {
$mode = $this->configFactory->get('entity_embed.settings')->get('rendered_entity_mode');
foreach ($this->entityDisplayRepository->getAllViewModes() as $view_modes) {
foreach ($view_modes as $view_mode => $definition) {
$this->derivatives[$definition['id']] = $base_plugin_definition;
$this->derivatives[$definition['id']]['label'] = new TranslatableMarkup($definition['label']);
$this->derivatives[$definition['id']]['view_mode'] = $view_mode;
$this->derivatives[$definition['id']]['entity_types'] = $definition['targetEntityType'];
$this->derivatives[$definition['id']]['no_ui'] = $mode;
}
}
return $this->derivatives;
}
}
<?php
namespace Drupal\entity_embed\Plugin\entity_embed\EntityEmbedDisplay;
use Drupal\Core\Form\FormStateInterface;
/**
* Entity Embed Display reusing entity reference field formatters.
*
* @see \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayInterface
*
* @EntityEmbedDisplay(
* id = "view_mode",
* label = @Translation("View Mode"),
* deriver = "Drupal\entity_embed\Plugin\Derivative\ViewModeDeriver",
* field_type = "entity_reference"
* )
*/
class ViewModeFieldFormatter extends EntityReferenceFieldFormatter {
/**
* {@inheritdoc}
*/
public function getFieldFormatter() {
if (!isset($this->fieldFormatter)) {
$display = [
'type' => $this->getFieldFormatterId(),
'settings' => [
'view_mode' => $this->getPluginDefinition()['view_mode'],
],
'label' => 'hidden',
];
// Create the formatter plugin. Will use the default formatter for that
// field type if none is passed.
$this->fieldFormatter = $this->formatterPluginManager->getInstance(
[
'field_definition' => $this->getFieldDefinition(),
'view_mode' => '_entity_embed',
'configuration' => $display,
]
);
}
return $this->fieldFormatter;
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
// Configuration form is not needed as the view mode is defined implicitly.
return [];
}
/**
* {@inheritdoc}
*/
public function getFieldFormatterId() {
return 'entity_reference_entity_view';
}
}
......@@ -92,9 +92,39 @@ class EntityEmbedDialogTest extends EntityEmbedTestBase {
// Check that 'Next' is a primary button.
$this->assertFieldByXPath('//input[contains(@class, "button--primary")]', 'Next', 'Next is a primary button');
$title = $this->node->getTitle() . ' (' . $this->node->id() . ')';
$title = $this->node->getTitle() . ' (' . $this->node->id() . ')';
$edit = ['entity_id' => $title];
$this->drupalPostAjaxForm(NULL, $edit, 'op');
$response = $this->drupalPostAjaxForm(NULL, $edit, 'op');
$plugins = [
'entity_reference:entity_reference_label',
'entity_reference:entity_reference_entity_id',
'view_mode:node.full',
'view_mode:node.rss',
'view_mode:node.search_index',
'view_mode:node.search_result',
'view_mode:node.teaser',
];
foreach ($plugins as $plugin) {
$this->assertTrue(strpos($response[2]['data'], $plugin), 'Plugin ' . $plugin . ' is available in selection.');
}
$this->container->get('config.factory')->getEditable('entity_embed.settings')
->set('rendered_entity_mode', TRUE)->save();
$this->displayPluginManager()->clearCachedDefinitions();
$this->getEmbedDialog('custom_format', 'node');
$title = $this->node->getTitle() . ' (' . $this->node->id() . ')';
$edit = ['entity_id' => $title];
$response = $this->drupalPostAjaxForm(NULL, $edit, 'op');
$plugins = [
'entity_reference:entity_reference_label',
'entity_reference:entity_reference_entity_id',
'entity_reference:entity_reference_entity_view',
];
foreach ($plugins as $plugin) {
$this->assertTrue(strpos($response[2]['data'], $plugin), 'Plugin ' . $plugin . ' is available in selection.');
}
/*$this->drupalPostForm(NULL, $edit, 'Next');
// Ensure form structure of the 'embed' step and submit form.
$this->assertFieldByName('attributes[data-entity-embed-display]', 'Entity Embed Display plugin field is present.');
......
<?php
namespace Drupal\entity_embed\Tests;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests the update hooks in entity_embed module.
*
* @group entity_embed
*/
class EntityEmbedUpdateHookTest extends UpdatePathTestBase {
/**
* Set database dump files to be used.
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
DRUPAL_ROOT . '/core/modules/system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../tests/fixtures/update/entity_embed.update-hook-test.php',
];
}
/**
* {@inheritdoc}
*/
protected function doSelectionTest() {
parent::doSelectionTest();
$this->assertRaw('8002 - Updates the default mode settings.');
}
/**
* Tests entity_embed_update_8002().
*/
public function testPostUpdate() {
$this->runUpdates();
$mode = $this->container->get('config.factory')
->get('entity_embed.settings')
->get('rendered_entity_mode');
$this->assertTrue($mode, 'Render entity mode settings after update is correct.');
}
}
<?php
/**
* @file
* Contains \Drupal\entity_embed\Tests\EntityReferenceFieldFormatterTest.
*/
namespace Drupal\entity_embed\Tests;
use Drupal\Core\Form\FormState;
......@@ -40,6 +35,20 @@ class EntityReferenceFieldFormatterTest extends EntityEmbedTestBase {
*/
public function testEntityReferenceFieldFormatter() {
// Ensure that entity reference field formatters are available as plugins.
$this->assertAvailableDisplayPlugins($this->node, [
'entity_reference:entity_reference_label',
'entity_reference:entity_reference_entity_id',
'view_mode:node.full',
'view_mode:node.rss',
'view_mode:node.search_index',
'view_mode:node.search_result',
'view_mode:node.teaser',
]);
$this->container->get('config.factory')->getEditable('entity_embed.settings')
->set('rendered_entity_mode', TRUE)->save();
$this->displayPluginManager()->clearCachedDefinitions();
$this->assertAvailableDisplayPlugins($this->node, [
'entity_reference:entity_reference_label',
'entity_reference:entity_reference_entity_id',
......
<?php
namespace Drupal\entity_embed\Tests;
use Drupal\Core\Form\FormState;
/**
* Tests the view mode entity embed display provided by entity_embed.
*
* @group entity_embed
*/
class ViewModeFieldFormatterTest extends EntityEmbedTestBase {
private $plugins = [
'view_mode:node.full',
'view_mode:node.rss',
'view_mode:node.search_index',
'view_mode:node.search_result',
'view_mode:node.teaser',
];
/**
* Tests view mode entity embed display.
*/
public function testViewModeFieldFormatter() {
// Ensure that view mode plugins have no configuration form.
foreach ($this->plugins as $plugin) {
$form = [];
$form_state = new FormState();
$display = $this->displayPluginManager()->createInstance($plugin, []);
$display->setContextValue('entity', $this->node);
$conf_form = $display->buildConfigurationForm($form, $form_state);
$this->assertIdentical(array_keys($conf_form), []);
}
}
/**
* Tests filter using view mode entity embed display plugins.
*/
public function testFilterViewModePlugins() {
foreach ($this->plugins as $plugin) {
$content = '<drupal-entity data-entity-type="node" data-entity-uuid="' . $this->node->uuid() . '" data-entity-embed-display="' . $plugin . '"></drupal-entity>';
$settings = [];
$settings['type'] = 'page';
$settings['title'] = 'Test ' . $plugin . ' Entity Embed Display plugin';
$settings['body'] = [['value' => $content, 'format' => 'custom_format']];
$node = $this->drupalCreateNode($settings);
$this->drupalGet('node/' . $node->id());
$plugin = explode('.', $plugin);
$view_mode = str_replace('_', '-', end($plugin));
$this->assertRaw('node--view-mode-' . $view_mode, 'Node rendered in the correct view mode: ' . $view_mode . '.');
}
}
}
<?php
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Set the schema version.
$connection->merge('key_value')
->condition('collection', 'system.schema')
->condition('name', 'entity_embed')
->fields([
'collection' => 'system.schema',
'name' => 'entity_embed',
'value' => 's:4:"8001";',
])
->execute();
// Update core.extension.
$extensions = $connection->select('config')
->fields('config', ['data'])
->condition('collection', '')
->condition('name', 'core.extension')
->execute()
->fetchField();
$extensions = unserialize($extensions);
$extensions['module']['entity_embed'] = 8001;
$connection->update('config')
->fields([
'data' => serialize($extensions),
])
->condition('collection', '')
->condition('name', 'core.extension')
->execute();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment