next-1.0.0-alpha2/src/Plugin/Next/SitePreviewer/Iframe.php
src/Plugin/Next/SitePreviewer/Iframe.php
<?php
namespace Drupal\next\Plugin\Next\SitePreviewer;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\RevisionableInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\next\Form\IframeSitePreviewerSwitcherForm;
use Drupal\next\Plugin\ConfigurableSitePreviewerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Provides a site resolver plugin for entity reference fields.
*
* @SitePreviewer(
* id = "iframe",
* label = "Iframe",
* description = "Displays the site preview in an iframe."
* )
*/
class Iframe extends ConfigurableSitePreviewerBase implements ContainerFactoryPluginInterface {
/**
* The current request.
*
* @var \Symfony\Component\HttpFoundation\Request
*/
protected $request;
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The date formatter.
*
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected $dateFormatter;
/**
* Iframe constructor.
*
* @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 \Symfony\Component\HttpFoundation\Request $request
* The current request.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
* The date formatter.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, Request $request, FormBuilderInterface $form_builder, EntityTypeManagerInterface $entity_type_manager, DateFormatterInterface $date_formatter) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->request = $request;
$this->formBuilder = $form_builder;
$this->entityTypeManager = $entity_type_manager;
$this->dateFormatter = $date_formatter;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('request_stack')->getCurrentRequest(),
$container->get('form_builder'),
$container->get('entity_type.manager'),
$container->get('date.formatter')
);
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['width'] = [
'#title' => $this->t('Width'),
'#size' => 10,
'#type' => 'textfield',
'#description' => $this->t('Provide a width for the iframe. Example: <em>100%</em> or <em>500px</em>.'),
'#required' => TRUE,
'#default_value' => $this->configuration['width'],
];
$form['sync_route'] = [
'#title' => $this->t('Sync routes (Experimental)'),
'#type' => 'checkbox',
'#description' => $this->t('If checked, route changes inside the iframe preview will be captured and synced with the Drupal site. <a href=":doc_link" target="_blank">Learn more</a>.', [
':doc_link' => 'https://next-drupal.org/docs/guides/route-syncing',
]),
'#default_value' => $this->configuration['sync_route'] ?: FALSE,
];
$form['sync_route_skip_routes'] = [
'#type' => 'textarea',
'#title' => $this->t('Skip routes'),
'#default_value' => $this->configuration['sync_route_skip_routes'] ?: NULL,
'#description' => $this->t('Specify routes to ignore syncing by using their paths. Enter one path per line. Example %example.', [
'%example' => '/blog',
]),
'#states' => [
'visible' => [
':input[name="site_previewer_configuration[sync_route]"]' => ['checked' => TRUE],
],
],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['width'] = $form_state->getValue('width');
$this->configuration['sync_route'] = $form_state->getValue('sync_route');
}
/**
* {@inheritdoc}
*/
public function render(EntityInterface $entity, array $sites) {
$build = [];
$site = reset($sites);
// Get site from query.
if ($site_id = $this->request->query->get('site')) {
$_sites = array_filter($sites, function ($site) use ($site_id) {
return $site->id() === $site_id;
});
$site = reset($_sites);
}
if (count($sites) > 1) {
$build['form'] = $this->formBuilder->getForm(IframeSitePreviewerSwitcherForm::class, $entity, $sites, $site->id());
}
$preview_url = $site->getPreviewUrlForEntity($entity);
$build['toolbar'] = [
'#prefix' => '<div class="next-site-preview-toolbar">',
'#suffix' => '</div>',
'info' => [
'#type' => 'inline_template',
'#template' => '<p class="heading-f">{{title}} ({{ bundle }})</p>',
'#context' => [
'bundle' => $entity->bundle(),
'title' => $entity->label(),
],
],
'links' => [
'#theme' => 'links',
'#links' => [],
'#attributes' => [
'class' => ['operations', 'clearfix'],
],
],
];
if ($entity instanceof EntityPublishedInterface) {
$build['toolbar']['links']['#links']['status'] = [
'title' => $entity->isPublished() ? $this->t('Published') : $this->t('Unpublished'),
'attributes' => [
'class' => [
$entity->isPublished() ? 'published' : '',
],
],
];
}
// Always show a live link.
$build['toolbar']['links']['#links']['live_link'] = [
'title' => $this->t('View'),
'url' => $preview_url,
'attributes' => [
'class' => [
'button',
'button--small',
'button--primary',
],
'target' => '_blank',
'rel' => 'nofollow',
],
];
// Handle revisions.
if ($entity instanceof RevisionableInterface && !$entity->isDefaultRevision()) {
/** @var \Drupal\Core\Entity\RevisionableStorageInterface $entity_storage */
$entity_storage = $this->entityTypeManager->getStorage($entity->getEntityTypeId());
$revision = $entity_storage->loadRevision($entity->getRevisionId());
$build['toolbar']['links']['#links']['status'] = [
'title' => $this->t('Revision: @date', [
'@date' => $this->dateFormatter->format($revision->revision_timestamp->value, 'short'),
]),
'attributes' => [],
];
unset($build['toolbar']['links']['#links']['live_link']);
}
$build['iframe'] = [
'#type' => 'html_tag',
'#tag' => 'iframe',
'#prefix' => '<div class="next-site-preview-container">',
'#suffix' => '</div>',
'#attributes' => [
'src' => $preview_url->toString(),
'frameborder' => 0,
'scrolling' => FALSE,
'allowtransparency' => TRUE,
'width' => $this->configuration['width'],
'class' => ['next-site-preview-iframe'],
],
'#attached' => [
'drupalSettings' => [
'next' => [
'iframe_preview' => [
'sync_route' => $this->configuration['sync_route'],
'skip_routes' => array_map('trim', explode("\n", mb_strtolower($this->configuration['sync_route_skip_routes']))),
],
],
],
'library' => [
'next/site_preview.iframe',
],
],
];
// We want a new preview url for each request.
// Do not cache the iframe.
$build['#cache']['max-age'] = 0;
return $build;
}
}
