From 3127e2092c73a6a7e77204548db9e4010b2a166b Mon Sep 17 00:00:00 2001 From: Josh Waihi Date: Mon, 21 Jul 2025 08:14:20 +1200 Subject: [PATCH] #867 - Make preview a per site configuration --- modules/next/config/schema/next.schema.yml | 14 ++- modules/next/next.install | 36 +++++++ modules/next/src/Entity/NextSite.php | 46 ++++++++ modules/next/src/Entity/NextSiteInterface.php | 38 +++++++ modules/next/src/Form/NextSettingsForm.php | 82 -------------- modules/next/src/Form/NextSiteForm.php | 102 ++++++++++++++++++ .../Plugin/Next/SitePreviewer/Redirect.php | 98 +++++++++++++++++ .../src/Render/MainContent/HtmlRenderer.php | 12 ++- .../tests/src/Kernel/Entity/NextSiteTest.php | 31 ++++++ .../src/Kernel/NextSettingsManagerTest.php | 3 +- .../Renderer/MainContent/HtmlRendererTest.php | 94 ++++++++++++++++ 11 files changed, 466 insertions(+), 90 deletions(-) create mode 100644 modules/next/src/Plugin/Next/SitePreviewer/Redirect.php diff --git a/modules/next/config/schema/next.schema.yml b/modules/next/config/schema/next.schema.yml index bde59648f..0fbcb4c91 100644 --- a/modules/next/config/schema/next.schema.yml +++ b/modules/next/config/schema/next.schema.yml @@ -23,6 +23,11 @@ next.next_site.*: revalidate_secret: type: string label: 'Revalidate secret' + site_previewer: + type: string + label: 'Site previewer' + site_previewer_configuration: + type: next.site_previewer.configuration.[%parent.site_previewer] next.next_entity_type_config.*: type: config_entity @@ -77,11 +82,6 @@ next.settings: type: config_object label: 'Next settings' mapping: - site_previewer: - type: string - label: 'Site previewer' - site_previewer_configuration: - type: next.site_previewer.configuration.[%parent.site_previewer] preview_url_generator: type: string label: 'Preview URL generator' @@ -103,6 +103,10 @@ next.site_previewer.configuration.iframe: type: string label: 'Sync route skip pages' +next.site_previewer.configuration.redirect: + type: mapping + mapping: {} + next.preview_url_generator.configuration.simple_oauth: type: mapping mapping: diff --git a/modules/next/next.install b/modules/next/next.install index 0afb4e602..169bccf58 100644 --- a/modules/next/next.install +++ b/modules/next/next.install @@ -104,3 +104,39 @@ function next_update_9106() { $config->set('debug', FALSE) ->save(); } + +/** + * Migrate global site previewer settings to site-level settings. + */ +function next_update_9107() { + // First, install the new fields for site previewer configuration. + $entity_definition_update = \Drupal::entityDefinitionUpdateManager(); + + $storage_definition = BaseFieldDefinition::create('string') + ->setLabel(t('Site previewer')); + $entity_definition_update->installFieldStorageDefinition('site_previewer', 'next_site', 'next_site', $storage_definition); + + $storage_definition = BaseFieldDefinition::create('map') + ->setLabel(t('Site previewer configuration')); + $entity_definition_update->installFieldStorageDefinition('site_previewer_configuration', 'next_site', 'next_site', $storage_definition); + + // Now migrate the global settings to site-level settings. + $config = \Drupal::configFactory()->get('next.settings'); + $global_site_previewer = $config->get('site_previewer'); + $global_site_previewer_configuration = $config->get('site_previewer_configuration') ?: []; + + // Only migrate if there are global settings configured. + if ($global_site_previewer) { + /** @var \Drupal\next\Entity\NextSiteInterface[] $sites */ + $sites = \Drupal::entityTypeManager()->getStorage('next_site')->loadMultiple(); + + foreach ($sites as $site) { + // Only set if the site doesn't already have a previewer configured. + if (!$site->getSitePreviewer()) { + $site->setSitePreviewer($global_site_previewer); + $site->setSitePreviewerConfiguration($global_site_previewer_configuration); + $site->save(); + } + } + } +} diff --git a/modules/next/src/Entity/NextSite.php b/modules/next/src/Entity/NextSite.php index 098f06a26..672361691 100644 --- a/modules/next/src/Entity/NextSite.php +++ b/modules/next/src/Entity/NextSite.php @@ -49,6 +49,8 @@ * "preview_secret", * "revalidate_url", * "revalidate_secret", + * "site_previewer", + * "site_previewer_configuration", * }, * links = { * "add-form" = "/admin/config/services/next/sites/add", @@ -97,6 +99,20 @@ class NextSite extends ConfigEntityBase implements NextSiteInterface { */ protected $revalidate_secret; + /** + * The site previewer plugin ID. + * + * @var string + */ + protected $site_previewer; + + /** + * The site previewer configuration. + * + * @var array + */ + protected $site_previewer_configuration; + /** * {@inheritdoc} */ @@ -172,6 +188,36 @@ public function setRevalidateSecret(string $revalidate_secret): NextSiteInterfac return $this; } + /** + * {@inheritdoc} + */ + public function getSitePreviewer(): ?string { + return $this->site_previewer; + } + + /** + * {@inheritdoc} + */ + public function setSitePreviewer(string $site_previewer): NextSiteInterface { + $this->set('site_previewer', $site_previewer); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getSitePreviewerConfiguration(): array { + return $this->site_previewer_configuration ?: []; + } + + /** + * {@inheritdoc} + */ + public function setSitePreviewerConfiguration(array $site_previewer_configuration): NextSiteInterface { + $this->set('site_previewer_configuration', $site_previewer_configuration); + return $this; + } + /** * {@inheritdoc} */ diff --git a/modules/next/src/Entity/NextSiteInterface.php b/modules/next/src/Entity/NextSiteInterface.php index 95a69a84c..ad9423928 100644 --- a/modules/next/src/Entity/NextSiteInterface.php +++ b/modules/next/src/Entity/NextSiteInterface.php @@ -128,6 +128,44 @@ public function getRevalidateSecret(): ?string; */ public function setRevalidateSecret(string $revalidate_secret): self; + /** + * Returns the site_previewer for the next_site. + * + * @return string|null + * The site_previewer for the next_site. + */ + public function getSitePreviewer(): ?string; + + /** + * Sets the site_previewer for the next_site. + * + * @param string $site_previewer + * The site_previewer. + * + * @return \Drupal\next\Entity\NextSiteInterface + * The next_site entity. + */ + public function setSitePreviewer(string $site_previewer): self; + + /** + * Returns the site_previewer_configuration for the next_site. + * + * @return array + * The site_previewer_configuration for the next_site. + */ + public function getSitePreviewerConfiguration(): array; + + /** + * Sets the site_previewer_configuration for the next_site. + * + * @param array $site_previewer_configuration + * The site_previewer_configuration. + * + * @return \Drupal\next\Entity\NextSiteInterface + * The next_site entity. + */ + public function setSitePreviewerConfiguration(array $site_previewer_configuration): self; + /** * Returns the revalidate url for given path. * diff --git a/modules/next/src/Form/NextSettingsForm.php b/modules/next/src/Form/NextSettingsForm.php index 3ade1db21..b07fa02ac 100644 --- a/modules/next/src/Form/NextSettingsForm.php +++ b/modules/next/src/Form/NextSettingsForm.php @@ -6,9 +6,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\SubformState; use Drupal\next\Plugin\ConfigurablePreviewUrlGeneratorInterface; -use Drupal\next\Plugin\ConfigurableSitePreviewerInterface; use Drupal\next\Plugin\PreviewUrlGeneratorManagerInterface; -use Drupal\next\Plugin\SitePreviewerManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -16,13 +14,6 @@ */ class NextSettingsForm extends ConfigFormBase { - /** - * The site previewer manager. - * - * @var \Drupal\next\Plugin\SitePreviewerManagerInterface - */ - protected SitePreviewerManagerInterface $sitePreviewerManager; - /** * The preview url generator manager. * @@ -36,7 +27,6 @@ class NextSettingsForm extends ConfigFormBase { public static function create(ContainerInterface $container) { $instance = parent::create($container); - $instance->sitePreviewerManager = $container->get('plugin.manager.next.site_previewer'); $instance->previewUrlGeneratorManager = $container->get('plugin.manager.next.preview_url_generator'); return $instance; @@ -105,46 +95,6 @@ public function buildForm(array $form, FormStateInterface $form_state) { } } - $form['site_previewer_container'] = [ - '#title' => $this->t('Site previewer'), - '#type' => 'details', - '#group' => 'settings', - ]; - - $form['site_previewer_container']['site_previewer'] = [ - '#title' => $this->t('Plugin'), - '#description' => $this->t('Select a plugin to use for the site preview.'), - '#type' => 'select', - '#options' => array_column($this->sitePreviewerManager->getDefinitions(), 'label', 'id'), - '#default_value' => $config->get('site_previewer'), - '#required' => TRUE, - '#limit_validation_errors' => [['site_previewer']], - '#submit' => ['::submitSitePreviewer'], - '#executes_submit_callback' => TRUE, - '#ajax' => [ - 'callback' => '::ajaxReplaceSitePreviewerSettingsForm', - 'wrapper' => 'site-previewer-settings', - 'method' => 'replace', - ], - ]; - - $form['site_previewer_container']['settings_container'] = [ - '#type' => 'container', - '#prefix' => '
', - '#suffix' => '
', - ]; - - if (($site_previewer_id = $form_state->getValue('site_previewer')) || ($site_previewer_id = $config->get('site_previewer'))) { - $site_previewer = $this->sitePreviewerManager->createInstance($site_previewer_id, $config->get('site_previewer_configuration')); - if ($site_previewer instanceof ConfigurableSitePreviewerInterface) { - $form['site_previewer_configuration'] = [ - '#tree' => TRUE, - ]; - $subform_state = SubformState::createForSubform($form['site_previewer_configuration'], $form, $form_state); - $form['site_previewer_container']['settings_container']['site_previewer_configuration'] = $site_previewer->buildConfigurationForm($form['site_previewer_configuration'], $subform_state); - } - } - $form['development'] = [ '#title' => $this->t('Development'), '#type' => 'details', @@ -161,20 +111,6 @@ public function buildForm(array $form, FormStateInterface $form_state) { return parent::buildForm($form, $form_state); } - /** - * Handles submit call when site_previewer is selected. - */ - public function submitSitePreviewer(array $form, FormStateInterface $form_state) { - $form_state->setRebuild(); - } - - /** - * Handles switching the site_previewer selector. - */ - public function ajaxReplaceSitePreviewerSettingsForm($form, FormStateInterface $form_state) { - return $form['site_previewer_settings_container']; - } - /** * Handles submit call when preview_url_generator is selected. */ @@ -195,14 +131,6 @@ public function ajaxReplacePreviewUrlGeneratorSettingsForm($form, FormStateInter public function validateForm(array &$form, FormStateInterface $form_state) { parent::validateForm($form, $form_state); - if ($site_previewer_id = $form_state->getValue('site_previewer')) { - $site_previewer = $this->sitePreviewerManager->createInstance($site_previewer_id); - if ($site_previewer instanceof ConfigurableSitePreviewerInterface) { - $subform_state = SubformState::createForSubform($form['site_previewer_configuration'], $form, $form_state); - $site_previewer->validateConfigurationForm($form, $subform_state); - } - } - if ($preview_url_generator_id = $form_state->getValue('preview_url_generator')) { $preview_url_generator = $this->previewUrlGeneratorManager->createInstance($preview_url_generator_id); if ($preview_url_generator instanceof ConfigurablePreviewUrlGeneratorInterface && isset($form['preview_url_generator_container']['settings_container'])) { @@ -218,14 +146,6 @@ public function validateForm(array &$form, FormStateInterface $form_state) { public function submitForm(array &$form, FormStateInterface $form_state) { parent::submitForm($form, $form_state); - if ($site_previewer_id = $form_state->getValue('site_previewer')) { - $site_previewer = $this->sitePreviewerManager->createInstance($site_previewer_id); - if ($site_previewer instanceof ConfigurableSitePreviewerInterface) { - $subform_state = SubformState::createForSubform($form['site_previewer_configuration'], $form, $form_state); - $site_previewer->submitConfigurationForm($form, $subform_state); - } - } - if ($preview_url_generator_id = $form_state->getValue('preview_url_generator')) { $preview_url_generator = $this->previewUrlGeneratorManager->createInstance($preview_url_generator_id); if ($preview_url_generator instanceof ConfigurablePreviewUrlGeneratorInterface) { @@ -235,8 +155,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) { } $this->config('next.settings') - ->set('site_previewer', $form_state->getValue('site_previewer')) - ->set('site_previewer_configuration', $form_state->getValue('site_previewer_configuration')) ->set('preview_url_generator', $form_state->getValue('preview_url_generator')) ->set('preview_url_generator_configuration', $form_state->getValue('preview_url_generator_configuration')) ->set('debug', $form_state->getValue('debug')) diff --git a/modules/next/src/Form/NextSiteForm.php b/modules/next/src/Form/NextSiteForm.php index 9ccfd0d2e..2360770bc 100644 --- a/modules/next/src/Form/NextSiteForm.php +++ b/modules/next/src/Form/NextSiteForm.php @@ -4,12 +4,32 @@ use Drupal\Core\Entity\EntityForm; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Form\SubformState; +use Drupal\next\Plugin\ConfigurableSitePreviewerInterface; +use Drupal\next\Plugin\SitePreviewerManagerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Base form for next_site. */ class NextSiteForm extends EntityForm { + /** + * The site previewer manager. + * + * @var \Drupal\next\Plugin\SitePreviewerManagerInterface + */ + protected SitePreviewerManagerInterface $sitePreviewerManager; + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + $instance = parent::create($container); + $instance->sitePreviewerManager = $container->get('plugin.manager.next.site_previewer'); + return $instance; + } + /** * {@inheritdoc} */ @@ -96,15 +116,97 @@ public function form(array $form, FormStateInterface $form_state) { '#default_value' => $entity->getRevalidateSecret(), ]; + $form['site_previewer_container'] = [ + '#title' => $this->t('Site Preview'), + '#description' => $this->t('Configure how content preview works for this site.'), + '#type' => 'details', + '#group' => 'settings', + ]; + + $form['site_previewer_container']['site_previewer'] = [ + '#title' => $this->t('Plugin'), + '#description' => $this->t('Select a plugin to use for the site preview.'), + '#type' => 'select', + '#options' => array_column($this->sitePreviewerManager->getDefinitions(), 'label', 'id'), + '#default_value' => $entity->getSitePreviewer(), + '#limit_validation_errors' => [['site_previewer']], + '#submit' => ['::submitSitePreviewer'], + '#executes_submit_callback' => TRUE, + '#ajax' => [ + 'callback' => '::ajaxReplaceSitePreviewerSettingsForm', + 'wrapper' => 'site-previewer-settings', + 'method' => 'replace', + ], + ]; + + $form['site_previewer_container']['settings_container'] = [ + '#type' => 'container', + '#prefix' => '
', + '#suffix' => '
', + ]; + + if (($site_previewer_id = $form_state->getValue('site_previewer')) || ($site_previewer_id = $entity->getSitePreviewer())) { + $site_previewer = $this->sitePreviewerManager->createInstance($site_previewer_id, $entity->getSitePreviewerConfiguration()); + if ($site_previewer instanceof ConfigurableSitePreviewerInterface) { + $form['site_previewer_configuration'] = [ + '#tree' => TRUE, + ]; + $subform_state = SubformState::createForSubform($form['site_previewer_configuration'], $form, $form_state); + $form['site_previewer_container']['settings_container']['site_previewer_configuration'] = $site_previewer->buildConfigurationForm($form['site_previewer_configuration'], $subform_state); + } + } + return $form; } + /** + * Handles submit call when site_previewer is selected. + */ + public function submitSitePreviewer(array $form, FormStateInterface $form_state) { + $form_state->setRebuild(); + } + + /** + * Handles switching the site_previewer selector. + */ + public function ajaxReplaceSitePreviewerSettingsForm($form, FormStateInterface $form_state) { + return $form['site_previewer_container']['settings_container']; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + parent::validateForm($form, $form_state); + + if ($site_previewer_id = $form_state->getValue('site_previewer')) { + $site_previewer = $this->sitePreviewerManager->createInstance($site_previewer_id); + if ($site_previewer instanceof ConfigurableSitePreviewerInterface) { + $subform_state = SubformState::createForSubform($form['site_previewer_configuration'], $form, $form_state); + $site_previewer->validateConfigurationForm($form, $subform_state); + } + } + } + /** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { /** @var \Drupal\next\Entity\NextSiteInterface $next_site */ $next_site = $this->entity; + + // Handle site previewer configuration. + if ($site_previewer_id = $form_state->getValue('site_previewer')) { + $next_site->setSitePreviewer($site_previewer_id); + + $site_previewer = $this->sitePreviewerManager->createInstance($site_previewer_id); + if ($site_previewer instanceof ConfigurableSitePreviewerInterface) { + $subform_state = SubformState::createForSubform($form['site_previewer_configuration'], $form, $form_state); + $site_previewer->submitConfigurationForm($form, $subform_state); + $next_site->setSitePreviewerConfiguration($form_state->getValue('site_previewer_configuration') ?: []); + } + } + $status = $next_site->save(); $this->messenger()->addStatus($this->t('Next.js site %label has been %action.', [ diff --git a/modules/next/src/Plugin/Next/SitePreviewer/Redirect.php b/modules/next/src/Plugin/Next/SitePreviewer/Redirect.php new file mode 100644 index 000000000..eb164b29a --- /dev/null +++ b/modules/next/src/Plugin/Next/SitePreviewer/Redirect.php @@ -0,0 +1,98 @@ +request = $request; + } + + /** + * {@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() + ); + } + + /** + * {@inheritdoc} + */ + public function render(EntityInterface $entity, array $sites) { + $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); + } + + $preview_url = $site->getPreviewUrlForEntity($entity); + + // Return empty render array since we're redirecting. + return [ + '#type' => 'markup', + '#markup' => '

Redirecting to preview...

', + '#attached' => [ + 'html_head' => [ + [ + [ + '#tag' => 'meta', + '#attributes' => [ + 'http-equiv' => 'refresh', + 'content' => '0;url=' . $preview_url->toString(), + ], + ], + 'redirect_meta', + ], + ], + ], + // Prevent caching. + '#cache' => ['max-age' => 0], + ]; + } + +} diff --git a/modules/next/src/Render/MainContent/HtmlRenderer.php b/modules/next/src/Render/MainContent/HtmlRenderer.php index b60a20361..eff3642f4 100644 --- a/modules/next/src/Render/MainContent/HtmlRenderer.php +++ b/modules/next/src/Render/MainContent/HtmlRenderer.php @@ -122,10 +122,18 @@ protected function prepare(array $main_content, Request $request, RouteMatchInte return $build; } + // For simplicity, use the first site to determine the site previewer. + // In practice, you might want to handle multiple sites differently. + $site = reset($sites); + $config = $this->configFactory->get('next.settings'); - $site_previewer_id = $config->get('site_previewer'); + + // Use site-level configuration if available, otherwise fall back to global. + $site_previewer_id = $site->getSitePreviewer() ?: $config->get('site_previewer'); + $site_previewer_configuration = $site->getSitePreviewerConfiguration() ?: ($config->get('site_previewer_configuration') ?? []); + /** @var \Drupal\next\Plugin\SitePreviewerInterface $site_previewer */ - $site_previewer = $this->sitePreviewerManager->createInstance($site_previewer_id, $config->get('site_previewer_configuration') ?? []); + $site_previewer = $this->sitePreviewerManager->createInstance($site_previewer_id, $site_previewer_configuration); if (!$site_previewer) { throw new PluginNotFoundException('Invalid site previewer.'); } diff --git a/modules/next/tests/src/Kernel/Entity/NextSiteTest.php b/modules/next/tests/src/Kernel/Entity/NextSiteTest.php index 18e676f3b..0ae438b3d 100644 --- a/modules/next/tests/src/Kernel/Entity/NextSiteTest.php +++ b/modules/next/tests/src/Kernel/Entity/NextSiteTest.php @@ -81,6 +81,8 @@ public function testGetPreviewUrlForEntity() { * @covers ::getPreviewSecret * @covers ::getRevalidateUrl * @covers ::getRevalidateSecret + * @covers ::getSitePreviewer + * @covers ::getSitePreviewerConfiguration */ public function test() { $marketing = NextSite::create([ @@ -91,6 +93,10 @@ public function test() { 'preview_secret' => 'two', 'revalidate_url' => 'https://marketing.com/api/revalidate', 'revalidate_secret' => 'three', + 'site_previewer' => 'redirect', + 'site_previewer_configuration' => [ + 'custom_setting' => 'value', + ], ]); $marketing->save(); @@ -99,6 +105,8 @@ public function test() { $this->assertSame('two', $marketing->getPreviewSecret()); $this->assertSame('https://marketing.com/api/revalidate', $marketing->getRevalidateUrl()); $this->assertSame('three', $marketing->getRevalidateSecret()); + $this->assertSame('redirect', $marketing->getSitePreviewer()); + $this->assertSame(['custom_setting' => 'value'], $marketing->getSitePreviewerConfiguration()); $marketing->setBaseUrl('http://blog.com'); $this->assertSame('http://blog.com', $marketing->getBaseUrl()); @@ -114,6 +122,29 @@ public function test() { $marketing->setRevalidateSecret('xxxxxx'); $this->assertSame('xxxxxx', $marketing->getRevalidateSecret()); + + $marketing->setSitePreviewer('iframe'); + $this->assertSame('iframe', $marketing->getSitePreviewer()); + + $marketing->setSitePreviewerConfiguration(['width' => '100%']); + $this->assertSame(['width' => '100%'], $marketing->getSitePreviewerConfiguration()); + } + + /** + * @covers ::getSitePreviewer + * @covers ::getSitePreviewerConfiguration + */ + public function testSitePreviewerDefaults() { + $site = NextSite::create([ + 'label' => 'Test', + 'id' => 'test', + 'base_url' => 'https://test.com', + ]); + $site->save(); + + // Should return null/empty for unset values. + $this->assertNull($site->getSitePreviewer()); + $this->assertSame([], $site->getSitePreviewerConfiguration()); } /** diff --git a/modules/next/tests/src/Kernel/NextSettingsManagerTest.php b/modules/next/tests/src/Kernel/NextSettingsManagerTest.php index b9be68fdb..ff7d87dde 100644 --- a/modules/next/tests/src/Kernel/NextSettingsManagerTest.php +++ b/modules/next/tests/src/Kernel/NextSettingsManagerTest.php @@ -50,7 +50,7 @@ protected function setUp(): void { */ public function test() { $settings = $this->nextSettingsManager->all(); - $this->assertSame('iframe', $settings['site_previewer']); + // Note: site_previewer is no longer in global settings $this->assertSame('simple_oauth', $settings['preview_url_generator']); $this->assertFalse($settings['debug']); $this->assertFalse($this->nextSettingsManager->isDebug()); @@ -63,6 +63,7 @@ public function test() { $this->assertTrue($settings['debug']); $this->assertTrue($this->nextSettingsManager->isDebug()); + // Test that getSitePreviewer() now falls back to iframe when no global setting exists $this->assertInstanceOf(Iframe::class, $this->nextSettingsManager->getSitePreviewer()); $this->assertInstanceOf(SimpleOauth::class, $this->nextSettingsManager->getPreviewUrlGenerator()); } diff --git a/modules/next/tests/src/Kernel/Renderer/MainContent/HtmlRendererTest.php b/modules/next/tests/src/Kernel/Renderer/MainContent/HtmlRendererTest.php index 31ef6543f..31fb0ccd6 100644 --- a/modules/next/tests/src/Kernel/Renderer/MainContent/HtmlRendererTest.php +++ b/modules/next/tests/src/Kernel/Renderer/MainContent/HtmlRendererTest.php @@ -58,6 +58,10 @@ protected function setUp(): void { 'base_url' => 'https://blog.com', 'preview_url' => 'https://blog.com/api/preview', 'preview_secret' => 'one', + 'site_previewer' => 'iframe', + 'site_previewer_configuration' => [ + 'width' => '100%', + ], ]); $blog->save(); @@ -101,4 +105,94 @@ public function testPrepare() { $this->assertEmpty($fields); } + /** + * @covers ::prepare + */ + public function testPrepareWithRedirectSitePreviewer() { + // Test with redirect site previewer. + $marketing = NextSite::create([ + 'label' => 'Marketing', + 'id' => 'marketing', + 'base_url' => 'https://marketing.com', + 'preview_url' => 'https://marketing.com/api/preview', + 'preview_secret' => 'secret', + 'site_previewer' => 'redirect', + 'site_previewer_configuration' => [], + ]); + $marketing->save(); + + // Create entity type config for articles to use the marketing site. + $entity_type_config = NextEntityTypeConfig::create([ + 'id' => 'node.article', + 'site_resolver' => 'site_selector', + 'configuration' => [ + 'sites' => [ + 'marketing' => 'marketing', + ], + ], + ]); + $entity_type_config->save(); + + $this->setCurrentUser($this->createUser(['access content'])); + + $article = $this->createNode(['type' => 'article']); + $request = Request::create($article->toUrl()->toString(), 'GET'); + $response = $this->container->get('http_kernel')->handle($request); + $this->setRawContent($response->getContent()); + + // Check for redirect meta tag instead of iframe. + $preview_url = 'https://marketing.com/api/preview?path=/node/2'; + $fields = $this->xpath("//meta[@http-equiv='refresh' and contains(@content, '$preview_url')]"); + $this->assertCount(1, $fields); + + // Should not have iframe. + $fields = $this->xpath("//iframe"); + $this->assertEmpty($fields); + } + + /** + * @covers ::prepare + */ + public function testPrepareWithFallbackToGlobalSettings() { + // Test fallback to global settings when site doesn't have site_previewer set. + $legacy_site = NextSite::create([ + 'label' => 'Legacy', + 'id' => 'legacy', + 'base_url' => 'https://legacy.com', + 'preview_url' => 'https://legacy.com/api/preview', + 'preview_secret' => 'legacy', + // No site_previewer or site_previewer_configuration set + ]); + $legacy_site->save(); + + // Create entity type config for a test content type. + NodeType::create([ + 'type' => 'test', + 'label' => 'Test', + ])->save(); + + $entity_type_config = NextEntityTypeConfig::create([ + 'id' => 'node.test', + 'site_resolver' => 'site_selector', + 'configuration' => [ + 'sites' => [ + 'legacy' => 'legacy', + ], + ], + ]); + $entity_type_config->save(); + + $this->setCurrentUser($this->createUser(['access content'])); + + $test_node = $this->createNode(['type' => 'test']); + $request = Request::create($test_node->toUrl()->toString(), 'GET'); + $response = $this->container->get('http_kernel')->handle($request); + $this->setRawContent($response->getContent()); + + // Should fall back to global iframe setting. + $preview_url = 'https://legacy.com/api/preview?path=/node/3'; + $fields = $this->xpath("//iframe[contains(@src, '$preview_url')]"); + $this->assertCount(1, $fields); + } + }